quiet compiler
[freeradius.git] / src / lib / misc.c
index f062ecf..587482f 100644 (file)
@@ -31,6 +31,28 @@ RCSID("$Id$")
 #include <pwd.h>
 #include <sys/uio.h>
 
+#ifdef HAVE_DIRENT_H
+#include <dirent.h>
+
+/*
+ *     Some versions of Linux don't have closefrom(), but they will
+ *     have /proc.
+ *
+ *     BSD systems will generally have closefrom(), but not proc.
+ *
+ *     OSX doesn't have closefrom() or /proc/self/fd, but it does
+ *     have /dev/fd
+ */
+#ifdef __linux__
+#define CLOSEFROM_DIR "/proc/self/fd"
+#elif defined(__APPLE__)
+#define CLOSEFROM_DIR "/dev/fd"
+#else
+#undef HAVE_DIRENT_H
+#endif
+
+#endif
+
 #define FR_PUT_LE16(a, val)\
        do {\
                a[1] = ((uint16_t) (val)) >> 8;\
@@ -280,10 +302,12 @@ static int ip_prefix_from_str(char const *str, uint32_t *paddr)
 }
 
 
-/** Parse an IPv4 address or IPv4 prefix in presentation format (and others)
+/**
+ * Parse an IPv4 address, IPv4 prefix in presentation format (and others), or
+ * a hostname.
  *
  * @param out Where to write the ip address value.
- * @param value to parse, may be dotted quad [+ prefix], or integer, or octal number, or '*' (INADDR_ANY).
+ * @param value to parse, may be dotted quad [+ prefix], or integer, or octal number, or '*' (INADDR_ANY), or a hostname.
  * @param inlen Length of value, if value is \0 terminated inlen may be -1.
  * @param resolve If true and value doesn't look like an IP address, try and resolve value as a hostname.
  * @param fallback to IPv6 resolution if no A records can be found.
@@ -295,8 +319,8 @@ int fr_pton4(fr_ipaddr_t *out, char const *value, ssize_t inlen, bool resolve, b
        unsigned int mask;
        char *eptr;
 
-       /* Dotted quad + / + [0-9]{1,2} */
-       char buffer[INET_ADDRSTRLEN + 3];
+       /* Dotted quad + / + [0-9]{1,2} or a hostname (RFC1035 2.3.4 Size limits) */
+       char buffer[256];
 
        /*
         *      Copy to intermediary buffer if we were given a length
@@ -378,7 +402,9 @@ int fr_pton4(fr_ipaddr_t *out, char const *value, ssize_t inlen, bool resolve, b
        return 0;
 }
 
-/** Parse an IPv6 address or IPv6 prefix in presentation format (and others)
+/**
+ * Parse an IPv6 address or IPv6 prefix in presentation format (and others),
+ * or a hostname.
  *
  * @param out Where to write the ip address value.
  * @param value to parse.
@@ -393,8 +419,8 @@ int fr_pton6(fr_ipaddr_t *out, char const *value, ssize_t inlen, bool resolve, b
        unsigned int prefix;
        char *eptr;
 
-       /* IPv6  + / + [0-9]{1,3} */
-       char buffer[INET6_ADDRSTRLEN + 4];
+       /* IPv6  + / + [0-9]{1,3} or a hostname (RFC1035 2.3.4 Size limits) */
+       char buffer[256];
 
        /*
         *      Copy to intermediary buffer if we were given a length
@@ -600,7 +626,7 @@ do_port:
         *      input length indicates there are more than 5 chars
         *      after the ':' then there's an issue.
         */
-       if (inlen > ((q + sizeof(buffer)) - value)) {
+       if (len > (size_t) ((q + sizeof(buffer)) - value)) {
        error:
                fr_strerror_printf("IP string contains trailing garbage after port delimiter");
                return -1;
@@ -1359,6 +1385,9 @@ int closefrom(int fd)
 {
        int i;
        int maxfd = 256;
+#ifdef HAVE_DIRENT_H
+       DIR *dir;
+#endif
 
 #ifdef F_CLOSEM
        if (fcntl(fd, F_CLOSEM) == 0) {
@@ -1378,6 +1407,33 @@ int closefrom(int fd)
        }
 #endif
 
+#ifdef HAVE_DIRENT_H
+       /*
+        *      Use /proc/self/fd directory if it exists.
+        */
+       dir = opendir(CLOSEFROM_DIR);
+       if (dir != NULL) {
+               long my_fd;
+               char *endp;
+               struct dirent *dp;
+
+               while ((dp = readdir(dir)) != NULL) {
+                       my_fd = strtol(dp->d_name, &endp, 10);
+                       if (my_fd <= 0) continue;
+
+                       if (*endp) continue;
+
+                       if (my_fd == dirfd(dir)) continue;
+
+                       if ((my_fd >= fd) && (my_fd <= maxfd)) {
+                               (void) close((int) my_fd);
+                       }
+               }
+               (void) closedir(dir);
+               return 0;
+       }
+#endif
+
 #ifdef F_MAXFD
 do_close:
 #endif