]> git.ipfire.org Git - thirdparty/dhcpcd.git/commitdiff
Reduce stack usage by using malloc more.
authorRoy Marples <roy@marples.name>
Thu, 11 Oct 2007 13:26:16 +0000 (13:26 +0000)
committerRoy Marples <roy@marples.name>
Thu, 11 Oct 2007 13:26:16 +0000 (13:26 +0000)
ChangeLog
configure.c
dhcp.c
dhcpcd.c
info.c
interface.c
socket.c

index 2857757c7ca08a97d2e092c66be8b99319b79821..94df85f64d1f78cdcb9856f6d4922a5ba2aa2f7e 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,4 @@
+Reduce stack usage by using malloc more.
 If we're on a different subnet from the one we get DHCP for, don't
 use our current address in messages. Thanks to Wilson Callan.
 Skip over bogus EINTR error on select when arp checking for a
index 7ecf6fc84f38b6f2e965073025a20c582fcf75f6..66ff70afc5290da366b4e05e7d5002d892ecf9bc 100644 (file)
@@ -113,14 +113,15 @@ static int make_resolv (const char *ifname, const dhcp_t *dhcp)
 {
        FILE *f;
        struct stat buf;
-       char resolvconf[PATH_MAX] = {0};
+       char *resolvconf = NULL;
        address_t *address;
 
 #ifdef RESOLVCONF
        if (stat (RESOLVCONF, &buf) == 0) {
                logger (LOG_DEBUG, "sending DNS information to resolvconf");
-               snprintf (resolvconf, PATH_MAX, RESOLVCONF" -a %s", ifname);
+               asprintf (&resolvconf, RESOLVCONF" -a %s", ifname);
                f = popen (resolvconf, "w");
+               free (resolvconf);
 
                if (! f)
                        logger (LOG_ERR, "popen: %s", strerror (errno));
@@ -145,7 +146,7 @@ static int make_resolv (const char *ifname, const dhcp_t *dhcp)
        for (address = dhcp->dnsservers; address; address = address->next)
                fprintf (f, "nameserver %s\n", inet_ntoa (address->address));
 
-       if (*resolvconf)
+       if (resolvconf)
                pclose (f);
        else
                fclose (f);
@@ -155,7 +156,7 @@ static int make_resolv (const char *ifname, const dhcp_t *dhcp)
        return (0);
 }
 
-static void restore_resolv(const char *ifname)
+static void restore_resolv (const char *ifname)
 {
 #ifdef RESOLVCONF
        struct stat buf;
@@ -169,12 +170,13 @@ static void restore_resolv(const char *ifname)
 }
 
 #ifdef ENABLE_NTP
+#define BUFFERSIZE 1024
 static int _make_ntp (const char *file, const char *ifname, const dhcp_t *dhcp)
 {
        FILE *f;
        address_t *address;
        char *a;
-       char buffer[1024];
+       char *buffer;
        int tomatch = 0;
        char *token;
        bool ntp = false;
@@ -190,8 +192,9 @@ static int _make_ntp (const char *file, const char *ifname, const dhcp_t *dhcp)
                        return -1;
                }
        } else {
-               memset (buffer, 0, sizeof (buffer));
-               while (fgets (buffer, sizeof (buffer), f)) {
+               buffer = xmalloc (sizeof (char *) * BUFFERSIZE);
+               memset (buffer, 0, BUFFERSIZE);
+               while (fgets (buffer, BUFFERSIZE, f)) {
                        a = buffer;
                        token = strsep (&a, " ");
                        if (! token || strcmp (token, "server") != 0)
@@ -209,6 +212,7 @@ static int _make_ntp (const char *file, const char *ifname, const dhcp_t *dhcp)
                        if (tomatch == 0)
                                break;
                }
+               free (buffer);
                fclose (f);
 
                /* File has the same name servers that we do, so no need to restart ntp */
@@ -288,11 +292,12 @@ static int make_ntp (const char *ifname, const dhcp_t *dhcp)
 #endif
 
 #ifdef ENABLE_NIS
+#define PREFIXSIZE 256
 static int make_nis (const char *ifname, const dhcp_t *dhcp)
 {
        FILE *f;
        address_t *address;
-       char prefix[256] = {0};
+       char *prefix;
 
        logger (LOG_DEBUG, "writing "NISFILE);
        if (! (f = fopen(NISFILE, "w"))) {
@@ -300,21 +305,25 @@ static int make_nis (const char *ifname, const dhcp_t *dhcp)
                return -1;
        }
 
+       prefix = xmalloc (sizeof (char *) * PREFIXSIZE);
+       *prefix = '\0';
        fprintf (f, "# Generated by dhcpcd for interface %s\n", ifname);
+
        if (dhcp->nisdomain) {
                setdomainname (dhcp->nisdomain, strlen (dhcp->nisdomain));
 
                if (dhcp->nisservers)
-                       snprintf (prefix, sizeof (prefix), "domain %s server", dhcp->nisdomain);
+                       snprintf (prefix, PREFIXSIZE, "domain %s server", dhcp->nisdomain);
                else
                        fprintf (f, "domain %s broadcast\n", dhcp->nisdomain);
        }
        else
-               snprintf (prefix, sizeof (prefix), "%s", "ypserver");
+               snprintf (prefix, PREFIXSIZE, "%s", "ypserver");
 
        for (address = dhcp->nisservers; address; address = address->next)
                fprintf (f, "%s %s\n", prefix, inet_ntoa (address->address));
 
+       free (prefix);
        fclose (f);
 
        exec_cmd (NISSERVICE, NISRESTARTARGS, (char *) NULL);
@@ -328,8 +337,8 @@ int configure (const options_t *options, interface_t *iface,
        route_t *route = NULL;
        route_t *new_route = NULL;
        route_t *old_route = NULL;
-       char newhostname[MAXHOSTNAMELEN] = {0};
-       char curhostname[MAXHOSTNAMELEN] = {0};
+       char *newhostname = NULL;
+       char *curhostname = NULL;
 
        if (! options || ! iface || ! dhcp)
                return (-1);
@@ -522,6 +531,11 @@ int configure (const options_t *options, interface_t *iface,
                make_nis(iface->name, dhcp);
 #endif
 
+       curhostname = xmalloc (sizeof (char *) * MAXHOSTNAMELEN);
+       *curhostname = '\0';
+       newhostname = xmalloc (sizeof (char *) * MAXHOSTNAMELEN);
+       *newhostname = '\0';
+
        /* Now we have made a resolv.conf we can obtain a hostname if we need it */
        if (options->dohostname && (! dhcp->hostname || options->dohostname > 3)) { 
                union {
@@ -529,17 +543,18 @@ int configure (const options_t *options, interface_t *iface,
                        struct sockaddr_in sin;
                } su;
                socklen_t salen;
-               char addr[NI_MAXHOST];
+               char *addr;
                struct addrinfo hints, *res;
                int result;
 
+               addr = xmalloc (sizeof (char *) * NI_MAXHOST);
                salen = sizeof (struct sockaddr);
                memset (&su.sa, 0, salen);
                su.sin.sin_family = AF_INET;
                memcpy (&su.sin.sin_addr, &dhcp->address, sizeof (struct in_addr));
 
                logger (LOG_DEBUG, "Looking up hostname via DNS");
-               if ((result = getnameinfo (&su.sa, salen, addr, sizeof (addr),
+               if ((result = getnameinfo (&su.sa, salen, addr, NI_MAXHOST,
                                                 NULL, 0, NI_NAMEREQD)) != 0)
                        logger (LOG_ERR, "Failed to lookup hostname via DNS: %s", gai_strerror (result));
                else {
@@ -587,12 +602,13 @@ int configure (const options_t *options, interface_t *iface,
                                                        break;
                                        }
                                }
-                               strlcpy (newhostname, addr, sizeof (newhostname));
+                               strlcpy (newhostname, addr, MAXHOSTNAMELEN);
                        }
                }
+               free (addr);
        }
 
-       gethostname (curhostname, sizeof (curhostname));
+       gethostname (curhostname, MAXHOSTNAMELEN);
 
        if (options->dohostname
                || strlen (curhostname) == 0
@@ -600,13 +616,16 @@ int configure (const options_t *options, interface_t *iface,
                || strcmp (curhostname, "localhost") == 0)
        {
                if (dhcp->hostname)
-                       strlcpy (newhostname, dhcp->hostname, sizeof (newhostname)); 
+                       strlcpy (newhostname, dhcp->hostname, MAXHOSTNAMELEN);
 
                if (*newhostname) {
                        logger (LOG_INFO, "setting hostname to `%s'", newhostname);
                        sethostname (newhostname, strlen (newhostname));
                }
        }
+       
+       free (curhostname);
+       free (newhostname);
 
 #ifdef ENABLE_INFO
        if (! dhcp->frominfo)
diff --git a/dhcp.c b/dhcp.c
index 2328c8365364f1532e6c487df85952ad8e9d7bb5..94e5510f771e1c2b815a59ed2a65cbfa9a9bf763 100644 (file)
--- a/dhcp.c
+++ b/dhcp.c
@@ -59,10 +59,10 @@ size_t send_message (const interface_t *iface, const dhcp_t *dhcp,
                                         unsigned long xid, char type,
                                         const options_t *options)
 {
-       dhcpmessage_t message;
-       struct udp_dhcp_packet packet;
-       unsigned char *m = (unsigned char *) &message;
-       unsigned char *p = (unsigned char *) &message.options;
+       struct udp_dhcp_packet *packet;
+       dhcpmessage_t *message;
+       unsigned char *m;
+       unsigned char *p;
        unsigned char *n_params = NULL;
        unsigned long l;
        struct in_addr from;
@@ -71,6 +71,7 @@ size_t send_message (const interface_t *iface, const dhcp_t *dhcp,
        uint32_t ul;
        uint16_t sz;
        unsigned int message_length;
+       size_t retval;
 
        if (!iface || !options || !dhcp)
                return -1;
@@ -81,49 +82,52 @@ size_t send_message (const interface_t *iface, const dhcp_t *dhcp,
        if (type == DHCP_RELEASE)
                to.s_addr = dhcp->serveraddress.s_addr;
 
-       memset (&message, 0, sizeof (dhcpmessage_t));
+       message = xmalloc (sizeof (dhcpmessage_t));
+       memset (message, 0, sizeof (dhcpmessage_t));
+       m = (unsigned char *) message;
+       p = (unsigned char *) &message->options;
 
        if (type == DHCP_INFORM ||
                type == DHCP_RELEASE ||
                type == DHCP_REQUEST)
        {
-               message.ciaddr = iface->previous_address.s_addr;
+               message->ciaddr = iface->previous_address.s_addr;
                from.s_addr = iface->previous_address.s_addr;
 
                /* Just incase we haven't actually configured the address yet */
                if (type == DHCP_INFORM && iface->previous_address.s_addr == 0)
-                       message.ciaddr = dhcp->address.s_addr;
-
+                       message->ciaddr = dhcp->address.s_addr;
+               
                /* Zero the address if we're currently on a different subnet */
                if (type == DHCP_REQUEST &&
                        iface->previous_netmask.s_addr != dhcp->netmask.s_addr)
                        message->ciaddr = from.s_addr = 0;
        }
 
-       message.op = DHCP_BOOTREQUEST;
-       message.hwtype = iface->family;
+       message->op = DHCP_BOOTREQUEST;
+       message->hwtype = iface->family;
        switch (iface->family) {
                case ARPHRD_ETHER:
                case ARPHRD_IEEE802:
-                       message.hwlen = ETHER_ADDR_LEN;
-                       memcpy (&message.chaddr, &iface->hwaddr, ETHER_ADDR_LEN);
+                       message->hwlen = ETHER_ADDR_LEN;
+                       memcpy (&message->chaddr, &iface->hwaddr, ETHER_ADDR_LEN);
                        break;
                case ARPHRD_IEEE1394:
                case ARPHRD_INFINIBAND:
-                       if (message.ciaddr == 0)
-                               message.flags = (int16_t) htons (BROADCAST_FLAG);
-                       message.hwlen = 0;
+                       if (message->ciaddr == 0)
+                               message->flags = (int16_t) htons (BROADCAST_FLAG);
+                       message->hwlen = 0;
                        break;
                default:
                        logger (LOG_ERR, "dhcp: unknown hardware type %d", iface->family);
        }
 
        if (up < 0 || up > UINT16_MAX)
-               message.secs = htons ((short) UINT16_MAX);
+               message->secs = htons ((short) UINT16_MAX);
        else
-               message.secs = htons (up);
-       message.xid = xid;
-       message.cookie = htonl (MAGIC_COOKIE);
+               message->secs = htons (up);
+       message->xid = xid;
+       message->cookie = htonl (MAGIC_COOKIE);
 
        *p++ = DHCP_MESSAGETYPE; 
        *p++ = 1;
@@ -144,19 +148,19 @@ size_t send_message (const interface_t *iface, const dhcp_t *dhcp,
 
        if (type != DHCP_INFORM) {
 #define PUTADDR(_type, _val) \
-       { \
-               *p++ = _type; \
-               *p++ = 4; \
-               memcpy (p, &_val.s_addr, 4); \
-               p += 4; \
-       }
-       if (dhcp->address.s_addr != 0 && iface->previous_address.s_addr == 0
-               && type != DHCP_RELEASE)
-               PUTADDR (DHCP_ADDRESS, dhcp->address);
+               { \
+                       *p++ = _type; \
+                       *p++ = 4; \
+                       memcpy (p, &_val.s_addr, 4); \
+                       p += 4; \
+               }
+               if (dhcp->address.s_addr != iface->previous_address.s_addr &&
+                       type != DHCP_RELEASE)
+                       PUTADDR (DHCP_ADDRESS, dhcp->address);
 
-       if (dhcp->serveraddress.s_addr != 0 && dhcp->address.s_addr !=0 &&
-               (iface->previous_address.s_addr == 0 || type == DHCP_RELEASE))
-               PUTADDR (DHCP_SERVERIDENTIFIER, dhcp->serveraddress);
+               if (dhcp->serveraddress.s_addr != 0 && dhcp->address.s_addr !=0 &&
+                       (iface->previous_address.s_addr == 0 || type == DHCP_RELEASE))
+                       PUTADDR (DHCP_SERVERIDENTIFIER, dhcp->serveraddress);
 #undef PUTADDR
        }
 
@@ -290,14 +294,19 @@ size_t send_message (const interface_t *iface, const dhcp_t *dhcp,
 
        message_length = p - m;
 
-       memset (&packet, 0, sizeof (struct udp_dhcp_packet));
-       make_dhcp_packet (&packet, (unsigned char *) &message, message_length,
+       packet = xmalloc (sizeof (struct udp_dhcp_packet));
+       memset (packet, 0, sizeof (struct udp_dhcp_packet));
+       make_dhcp_packet (packet, (unsigned char *) message, message_length,
                                          from, to);
-
-       logger (LOG_DEBUG, "sending %s with xid 0x%lx", dhcp_message[(int) type], xid);
-       return send_packet (iface, ETHERTYPE_IP, (unsigned char *) &packet,
-                                               message_length + sizeof (struct ip) +
-                                               sizeof (struct udphdr));
+       free (message);
+
+       logger (LOG_DEBUG, "sending %s with xid 0x%lx",
+                       dhcp_message[(int) type], xid);
+       retval = send_packet (iface, ETHERTYPE_IP, (unsigned char *) packet,
+                                                 message_length + sizeof (struct ip) +
+                                                 sizeof (struct udphdr));
+       free (packet);
+       return (retval);
 }
 
 /* Decode an RFC3397 DNS search order option into a space
index f9870520efb3b08baf96a7edcecc1c7c0005f92c..25519da64927a8fedebdf6920cd8eb1cdd3f3799 100644 (file)
--- a/dhcpcd.c
+++ b/dhcpcd.c
 #include "logger.h"
 #include "version.h"
 
+static int doversion = 0;
+static int dohelp = 0;
+#define EXTRA_OPTS
+static const struct option longopts[] = {
+       {"arp",         no_argument,        NULL, 'a'},
+       {"script",      required_argument,  NULL, 'c'},
+       {"debug",       no_argument,        NULL, 'd'},
+       {"hostname",    optional_argument,  NULL, 'h'},
+       {"classid",     optional_argument,  NULL, 'i'},
+       {"release",     no_argument,        NULL, 'k'},
+       {"leasetime",   required_argument,  NULL, 'l'},
+       {"metric",      required_argument,  NULL, 'm'},
+       {"renew",       no_argument,        NULL, 'n'},
+       {"persistent",  no_argument,        NULL, 'p'},
+       {"inform",      optional_argument,  NULL, 's'},
+       {"request",     optional_argument,  NULL, 'r'},
+       {"timeout",     required_argument,  NULL, 't'},
+       {"userclass",   required_argument,  NULL, 'u'},
+       {"exit",        no_argument,        NULL, 'x'},
+       {"lastlease",   no_argument,        NULL, 'E'},
+       {"fqdn",        required_argument,  NULL, 'F'},
+       {"nogateway",   no_argument,        NULL, 'G'},
+       {"sethostname", no_argument,        NULL, 'H'},
+       {"clientid",    optional_argument,  NULL, 'I'},
+       {"noipv4ll",    no_argument,            NULL, 'L'},
+       {"nomtu",       no_argument,        NULL, 'M'},
+       {"nontp",       no_argument,        NULL, 'N'},
+       {"nodns",       no_argument,        NULL, 'R'},
+       {"test",        no_argument,        NULL, 'T'},
+       {"nonis",       no_argument,        NULL, 'Y'},
+       {"help",        no_argument,        &dohelp, 1},
+       {"version",     no_argument,        &doversion, 1},
+#ifdef THERE_IS_NO_FORK
+       {"daemonised",  no_argument,            NULL, 'f'},
+       {"skiproutes",  required_argument,      NULL, 'g'},
+#endif
+       {NULL,          0,                  NULL, 0}
+};
+
+
 #define STRINGINT(_string, _int) { \
        char *_tmp; \
        long _number = strtol (_string, &_tmp, 0); \
@@ -67,6 +107,8 @@ char dhcpcd[PATH_MAX];
 char **dhcpcd_argv = NULL;
 int dhcpcd_argc = 0;
 char *dhcpcd_skiproutes = NULL;
+#undef EXTRA_OPTS
+#define EXTRA_OPTS "fg:"
 #endif
 
 static pid_t read_pid (const char *pidfile)
@@ -94,85 +136,49 @@ static void usage ()
 
 int main(int argc, char **argv)
 {
-       options_t options;
-       int doversion = 0;
-       int dohelp = 0;
+       options_t *options;
        int userclasses = 0;
        int opt;
        int option_index = 0;
-       char prefix[IF_NAMESIZE + 3];
+       char *prefix;
        pid_t pid;
        int debug = 0;
        int i;
        int pidfd = -1;
        int sig = 0;
 
-       const struct option longopts[] = {
-               {"arp",         no_argument,        NULL, 'a'},
-               {"script",      required_argument,  NULL, 'c'},
-               {"debug",       no_argument,        NULL, 'd'},
-               {"hostname",    optional_argument,  NULL, 'h'},
-               {"classid",     optional_argument,  NULL, 'i'},
-               {"release",     no_argument,        NULL, 'k'},
-               {"leasetime",   required_argument,  NULL, 'l'},
-               {"metric",      required_argument,  NULL, 'm'},
-               {"renew",       no_argument,        NULL, 'n'},
-               {"persistent",  no_argument,        NULL, 'p'},
-               {"inform",      optional_argument,  NULL, 's'},
-               {"request",     optional_argument,  NULL, 'r'},
-               {"timeout",     required_argument,  NULL, 't'},
-               {"userclass",   required_argument,  NULL, 'u'},
-               {"exit",        no_argument,        NULL, 'x'},
-               {"lastlease",   no_argument,        NULL, 'E'},
-               {"fqdn",        required_argument,  NULL, 'F'},
-               {"nogateway",   no_argument,        NULL, 'G'},
-               {"sethostname", no_argument,        NULL, 'H'},
-               {"clientid",    optional_argument,  NULL, 'I'},
-               {"noipv4ll",    no_argument,            NULL, 'L'},
-               {"nomtu",       no_argument,        NULL, 'M'},
-               {"nontp",       no_argument,        NULL, 'N'},
-               {"nodns",       no_argument,        NULL, 'R'},
-               {"test",        no_argument,        NULL, 'T'},
-               {"nonis",       no_argument,        NULL, 'Y'},
-               {"help",        no_argument,        &dohelp, 1},
-               {"version",     no_argument,        &doversion, 1},
-#ifdef THERE_IS_NO_FORK
-               {"daemonised",  no_argument,            NULL, 'f'},
-               {"skiproutes",  required_argument,      NULL, 'g'},
-#endif
-               {NULL,          0,                  NULL, 0}
-       };
-
        /* Close any un-needed fd's */
        for (i = getdtablesize() - 1; i >= 3; --i)
                close (i);
 
        openlog (PACKAGE, LOG_PID, LOG_LOCAL0);
 
-       memset (&options, 0, sizeof (options_t));
-       options.script = (char *) DEFAULT_SCRIPT;
-       snprintf (options.classid, CLASS_ID_MAX_LEN, "%s %s", PACKAGE, VERSION);
-       options.classid_len = strlen (options.classid);
-
-       options.doarp = true;
-       options.dodns = true;
-       options.domtu = true;
-       options.donis = true;
-       options.dontp = true;
-       options.dogateway = true;
-       options.daemonise = true;
-       options.doinform = false;
-       options.doipv4ll = true;
-       options.timeout = DEFAULT_TIMEOUT;
-
-       gethostname (options.hostname, sizeof (options.hostname));
-       if (strcmp (options.hostname, "(none)") == 0 ||
-               strcmp (options.hostname, "localhost") == 0)
-               memset (options.hostname, 0, sizeof (options.hostname));
+       options = xmalloc (sizeof (options_t));
+       memset (options, 0, sizeof (options_t));
+       options->script = (char *) DEFAULT_SCRIPT;
+       snprintf (options->classid, CLASS_ID_MAX_LEN, "%s %s", PACKAGE, VERSION);
+       options->classid_len = strlen (options->classid);
+
+       options->doarp = true;
+       options->dodns = true;
+       options->domtu = true;
+       options->donis = true;
+       options->dontp = true;
+       options->dogateway = true;
+       options->daemonise = true;
+       options->doinform = false;
+       options->doipv4ll = true;
+       options->timeout = DEFAULT_TIMEOUT;
+
+       gethostname (options->hostname, sizeof (options->hostname));
+       if (strcmp (options->hostname, "(none)") == 0 ||
+               strcmp (options->hostname, "localhost") == 0)
+               memset (options->hostname, 0, sizeof (options->hostname));
 
        /* Don't set any optional arguments here so we retain POSIX
         * compatibility with getopt */
-       while ((opt = getopt_long(argc, argv, "c:dh:i:kl:m:npr:s:t:u:xAEF:GHI:LMNRTY",
+       while ((opt = getopt_long(argc, argv, EXTRA_OPTS
+                                                         "c:dh:i:kl:m:npr:s:t:u:xAEF:GHI:LMNRTY",
                                                          longopts, &option_index)) != -1)
        {
                switch (opt) {
@@ -184,7 +190,7 @@ int main(int argc, char **argv)
                                exit (EXIT_FAILURE);
                                break;
                        case 'c':
-                               options.script = optarg;
+                               options->script = optarg;
                                break;
                        case 'd':
                                debug++;
@@ -193,13 +199,13 @@ int main(int argc, char **argv)
                                                setloglevel (LOG_DEBUG);
                                                break;
                                        case 2:
-                                               options.daemonise = false;
+                                               options->daemonise = false;
                                                break;
                                }
                                break;
 #ifdef THERE_IS_NO_FORK
                        case 'f':
-                               options.daemonised = true;
+                               options->daemonised = true;
                                close_fds ();
                                break;
                        case 'g':
@@ -208,50 +214,50 @@ int main(int argc, char **argv)
 #endif
                        case 'h':
                                if (! optarg)
-                                       memset (options.hostname, 0, sizeof (options.hostname));
+                                       memset (options->hostname, 0, sizeof (options->hostname));
                                else if (strlen (optarg) > MAXHOSTNAMELEN) {
                                        logger (LOG_ERR, "`%s' too long for HostName string, max is %d",
                                                        optarg, MAXHOSTNAMELEN);
                                        exit (EXIT_FAILURE);
                                } else
-                                       strlcpy (options.hostname, optarg, sizeof (options.hostname));
+                                       strlcpy (options->hostname, optarg, sizeof (options->hostname));
                                break;
                        case 'i':
                                if (! optarg) {
-                                       memset (options.classid, 0, sizeof (options.classid));
-                                       options.classid_len = 0;
+                                       memset (options->classid, 0, sizeof (options->classid));
+                                       options->classid_len = 0;
                                } else if (strlen (optarg) > CLASS_ID_MAX_LEN) {
                                        logger (LOG_ERR, "`%s' too long for ClassID string, max is %d",
                                                        optarg, CLASS_ID_MAX_LEN);
                                        exit (EXIT_FAILURE);
                                } else
-                                       options.classid_len = strlcpy (options.classid, optarg,
-                                                                                                  sizeof (options.classid));
+                                       options->classid_len = strlcpy (options->classid, optarg,
+                                                                                                  sizeof (options->classid));
                                break;
                        case 'k':
                                sig = SIGHUP;
                                break;
                        case 'l':
-                               STRINGINT (optarg, options.leasetime);
-                               if (options.leasetime <= 0) {
+                               STRINGINT (optarg, options->leasetime);
+                               if (options->leasetime <= 0) {
                                        logger (LOG_ERR, "leasetime must be a positive value");
                                        exit (EXIT_FAILURE);
                                }
                                break;
                        case 'm':
-                               STRINGINT (optarg, options.metric);
+                               STRINGINT (optarg, options->metric);
                                break;
                        case 'n':
                                sig = SIGALRM;
                                break;
                        case 'p':
-                               options.persistent = true;
+                               options->persistent = true;
                                break;
                        case 's':
-                               options.doinform = true;
-                               options.doarp = false;
+                               options->doinform = true;
+                               options->doarp = false;
                                if (! optarg || strlen (optarg) == 0) {
-                                       options.request_address.s_addr = 0;
+                                       options->request_address.s_addr = 0;
                                        break;
                                } else {
                                        char *slash = strchr (optarg, '/');
@@ -261,7 +267,7 @@ int main(int argc, char **argv)
                                                 * address */
                                                *slash++ = '\0';
                                                if (sscanf (slash, "%d", &cidr) != 1 ||
-                                                       inet_cidrtoaddr (cidr, &options.request_netmask) != 0) {
+                                                       inet_cidrtoaddr (cidr, &options->request_netmask) != 0) {
                                                        logger (LOG_ERR, "`%s' is not a valid CIDR", slash);
                                                        exit (EXIT_FAILURE);
                                                }
@@ -269,18 +275,18 @@ int main(int argc, char **argv)
                                        /* fall through */
                                }
                        case 'r':
-                               if (! options.doinform)
-                                       options.dorequest = true;
+                               if (! options->doinform)
+                                       options->dorequest = true;
                                if (strlen (optarg) > 0 &&
-                                       ! inet_aton (optarg, &options.request_address))
+                                       ! inet_aton (optarg, &options->request_address))
                                { 
                                        logger (LOG_ERR, "`%s' is not a valid IP address", optarg);
                                        exit (EXIT_FAILURE);
                                }
                                break;
                        case 't':
-                               STRINGINT (optarg, options.timeout);
-                               if (options.timeout < 0) {
+                               STRINGINT (optarg, options->timeout);
+                               if (options->timeout < 0) {
                                        logger (LOG_ERR, "timeout must be a positive value");
                                        exit (EXIT_FAILURE);
                                }
@@ -289,16 +295,16 @@ int main(int argc, char **argv)
                                {
                                        int offset = 0;
                                        for (i = 0; i < userclasses; i++)
-                                               offset += (int) options.userclass[offset] + 1;
+                                               offset += (int) options->userclass[offset] + 1;
                                        if (offset + 1 + strlen (optarg) > USERCLASS_MAX_LEN) {
                                                logger (LOG_ERR, "userclass overrun, max is %d",
                                                                USERCLASS_MAX_LEN);
                                                exit (EXIT_FAILURE);
                                        }
                                        userclasses++;
-                                       memcpy (options.userclass + offset + 1 , optarg, strlen (optarg));
-                                       options.userclass[offset] = strlen (optarg);
-                                       options.userclass_len += (strlen (optarg)) + 1;
+                                       memcpy (options->userclass + offset + 1 , optarg, strlen (optarg));
+                                       options->userclass[offset] = strlen (optarg);
+                                       options->userclass_len += (strlen (optarg)) + 1;
                                }
                                break;
                        case 'x':
@@ -309,32 +315,32 @@ int main(int argc, char **argv)
                                logger (LOG_ERR, "arp support not compiled into dhcpcd");
                                exit (EXIT_FAILURE);
 #endif
-                               options.doarp = false;
+                               options->doarp = false;
                                break;
                        case 'E':
 #ifndef ENABLE_INFO
                                logger (LOG_ERR, "info support not compiled into dhcpcd");
                                exit (EXIT_FAILURE);
 #endif
-                               options.dolastlease = true;
+                               options->dolastlease = true;
                                break;
                        case 'F':
                                if (strncmp (optarg, "none", strlen (optarg)) == 0)
-                                       options.fqdn = FQDN_NONE;
+                                       options->fqdn = FQDN_NONE;
                                else if (strncmp (optarg, "ptr", strlen (optarg)) == 0)
-                                       options.fqdn = FQDN_PTR;
+                                       options->fqdn = FQDN_PTR;
                                else if (strncmp (optarg, "both", strlen (optarg)) == 0)
-                                       options.fqdn = FQDN_BOTH;
+                                       options->fqdn = FQDN_BOTH;
                                else {
                                        logger (LOG_ERR, "invalid value `%s' for FQDN", optarg);
                                        exit (EXIT_FAILURE);
                                }
                                break;
                        case 'G':
-                               options.dogateway = false;
+                               options->dogateway = false;
                                break;
                        case 'H':
-                               options.dohostname++;
+                               options->dohostname++;
                                break;
                        case 'I':
                                if (optarg) {
@@ -343,38 +349,38 @@ int main(int argc, char **argv)
                                                                optarg, CLIENT_ID_MAX_LEN);
                                                exit (EXIT_FAILURE);
                                        }
-                                       options.clientid_len = strlcpy (options.clientid, optarg,
-                                                                                                       sizeof (options.clientid));
+                                       options->clientid_len = strlcpy (options->clientid, optarg,
+                                                                                                       sizeof (options->clientid));
                                        /* empty string disabled duid */
-                                       if (options.clientid_len == 0)
-                                               options.clientid_len = -1;
+                                       if (options->clientid_len == 0)
+                                               options->clientid_len = -1;
                                } else {
-                                       memset (options.clientid, 0, sizeof (options.clientid));
-                                       options.clientid_len = -1;
+                                       memset (options->clientid, 0, sizeof (options->clientid));
+                                       options->clientid_len = -1;
                                }
                                break;
                        case 'L':
-                               options.doipv4ll = false;
+                               options->doipv4ll = false;
                                break;
                        case 'M':
-                               options.domtu = false;
+                               options->domtu = false;
                                break;
                        case 'N':
-                               options.dontp = false;
+                               options->dontp = false;
                                break;
                        case 'R':
-                               options.dodns = false;
+                               options->dodns = false;
                                break;
                        case 'T':
 #ifndef ENABLE_INFO
                                logger (LOG_ERR, "info support not compiled into dhcpcd");
                                exit (EXIT_FAILURE);
 #endif
-                               options.test = true;
-                               options.persistent = true;
+                               options->test = true;
+                               options->persistent = true;
                                break;
                        case 'Y':
-                               options.donis = false;
+                               options->donis = false;
                                break;
                        case '?':
                                usage ();
@@ -414,8 +420,8 @@ int main(int argc, char **argv)
                                        argv[optind], IF_NAMESIZE);
                        exit (EXIT_FAILURE);
                }
-               strlcpy (options.interface, argv[optind],
-                                sizeof (options.interface));
+               strlcpy (options->interface, argv[optind],
+                                sizeof (options->interface));
        } else {
                /* If only version was requested then exit now */
                if (doversion || dohelp)
@@ -425,15 +431,15 @@ int main(int argc, char **argv)
                exit (EXIT_FAILURE);
        }
 
-       if (strchr (options.hostname, '.')) {
-               if (options.fqdn == FQDN_DISABLE)
-                       options.fqdn = FQDN_BOTH;
+       if (strchr (options->hostname, '.')) {
+               if (options->fqdn == FQDN_DISABLE)
+                       options->fqdn = FQDN_BOTH;
        } else
-               options.fqdn = FQDN_DISABLE;
+               options->fqdn = FQDN_DISABLE;
 
-       if (options.request_address.s_addr == 0 && options.doinform) {
-               if ((options.request_address.s_addr = get_address (options.interface)) != 0)
-                       options.keep_address = true;
+       if (options->request_address.s_addr == 0 && options->doinform) {
+               if ((options->request_address.s_addr = get_address (options->interface)) != 0)
+                       options->keep_address = true;
        }
 
        if (geteuid ()) {
@@ -441,10 +447,12 @@ int main(int argc, char **argv)
                exit (EXIT_FAILURE);
        }
 
-       snprintf (prefix, IF_NAMESIZE, "%s: ", options.interface);
+       prefix = xmalloc (sizeof (char *) * IF_NAMESIZE + 3);
+       snprintf (prefix, IF_NAMESIZE, "%s: ", options->interface);
        setlogprefix (prefix);
-       snprintf (options.pidfile, sizeof (options.pidfile), PIDFILE,
-                         options.interface);
+       snprintf (options->pidfile, sizeof (options->pidfile), PIDFILE,
+                         options->interface);
+       free (prefix);
 
        chdir ("/");
        umask (022);
@@ -463,13 +471,13 @@ int main(int argc, char **argv)
                exit (EXIT_FAILURE);
        }
 
-       if (options.test) {
-               if (options.dorequest || options.doinform) {
+       if (options->test) {
+               if (options->dorequest || options->doinform) {
                        logger (LOG_ERR, "cannot test with --inform or --request");
                        exit (EXIT_FAILURE);
                }
 
-               if (options.dolastlease) {
+               if (options->dolastlease) {
                        logger (LOG_ERR, "cannot test with --lastlease");
                        exit (EXIT_FAILURE);
                }
@@ -482,7 +490,7 @@ int main(int argc, char **argv)
 
        if (sig != 0) {
                int killed = -1;
-               pid = read_pid (options.pidfile);
+               pid = read_pid (options->pidfile);
                if (pid != 0)
                        logger (LOG_INFO, "sending signal %d to pid %d", sig, pid);
 
@@ -490,7 +498,7 @@ int main(int argc, char **argv)
                        logger (sig == SIGALRM ? LOG_INFO : LOG_ERR, ""PACKAGE" not running");
 
                if (pid != 0 && (sig != SIGALRM || killed != 0))
-                       unlink (options.pidfile);
+                       unlink (options->pidfile);
 
                if (killed == 0)
                        exit (EXIT_SUCCESS);
@@ -499,22 +507,22 @@ int main(int argc, char **argv)
                        exit (EXIT_FAILURE);
        }
 
-       if (! options.test && ! options.daemonised) {
-               if ((pid = read_pid (options.pidfile)) > 0 && kill (pid, 0) == 0) {
+       if (! options->test && ! options->daemonised) {
+               if ((pid = read_pid (options->pidfile)) > 0 && kill (pid, 0) == 0) {
                        logger (LOG_ERR, ""PACKAGE" already running on pid %d (%s)",
-                                       pid, options.pidfile);
+                                       pid, options->pidfile);
                        exit (EXIT_FAILURE);
                }
 
-               pidfd = open (options.pidfile, O_WRONLY | O_CREAT | O_NONBLOCK, 0660);
+               pidfd = open (options->pidfile, O_WRONLY | O_CREAT | O_NONBLOCK, 0660);
                if (pidfd == -1) {
-                       logger (LOG_ERR, "open `%s': %s", options.pidfile, strerror (errno));
+                       logger (LOG_ERR, "open `%s': %s", options->pidfile, strerror (errno));
                        exit (EXIT_FAILURE);
                }
 
                /* Lock the file so that only one instance of dhcpcd runs on an interface */
                if (flock (pidfd, LOCK_EX | LOCK_NB) == -1) {
-                       logger (LOG_ERR, "flock `%s': %s", options.pidfile, strerror (errno));
+                       logger (LOG_ERR, "flock `%s': %s", options->pidfile, strerror (errno));
                        exit (EXIT_FAILURE);
                }
 
@@ -530,9 +538,11 @@ int main(int argc, char **argv)
        srandomdev ();
 
        i = EXIT_FAILURE;
-       if (dhcp_run (&options, &pidfd) == 0)
+       if (dhcp_run (options, &pidfd) == 0)
                i = EXIT_SUCCESS;
 
+       free (options);
+
 #ifdef THERE_IS_NO_FORK
        /* There may have been an error before the dhcp_run function
         * clears this, so just do it here to be safe */
diff --git a/info.c b/info.c
index 316a1362fc264de9569222bf0178eb18f5b0f251..b32771787ccb4ec2ee7b9038ac1695d2055c3659 100644 (file)
--- a/info.c
+++ b/info.c
 #include "info.h"
 
 #ifdef ENABLE_INFO
+#define BUFFERSIZE 1024
+
 static char *cleanmetas (const char *cstr)
 {
        /* The largest single element we can have is 256 bytes according to the RFC,
           so this buffer size should be safe even if it's all ' */
-       static char buffer[1024]; 
+       static char buffer[BUFFERSIZE]; 
        char *b = buffer;
 
        memset (buffer, 0, sizeof (buffer));
@@ -193,10 +195,11 @@ bool write_info(const interface_t *iface, const dhcp_t *dhcp,
                fprintf (f, "CLIENTID='00:%s'\n", cleanmetas (options->clientid));
 #ifdef ENABLE_DUID
        else if (iface->duid_length > 0 && options->clientid_len != -1) {
-               unsigned char duid[256];
-               unsigned char *p = duid;
+               unsigned char *duid;
+               unsigned char *p;
                uint32_t ul;
 
+               p = duid = xmalloc (iface->duid_length + 6);
                *p++ = 255;
 
                /* IAID is 4 bytes, so if the interface name is 4 bytes then use it */
@@ -213,6 +216,7 @@ bool write_info(const interface_t *iface, const dhcp_t *dhcp,
                p += iface->duid_length;
 
                fprintf (f, "CLIENTID='%s'\n", hwaddr_ntoa (duid, p - duid));
+               free (duid);
        }
 #endif
        else
@@ -317,7 +321,7 @@ static bool parse_addresses (address_t **address, char *value, const char *var)
 bool read_info (const interface_t *iface, dhcp_t *dhcp)
 {
        FILE *fp;
-       char buffer[1024];
+       char *buffer;
        char *var;
        char *value;
        char *p;
@@ -336,8 +340,9 @@ bool read_info (const interface_t *iface, dhcp_t *dhcp)
 
        dhcp->frominfo = true;
 
-       memset (buffer, 0, sizeof (buffer));
-       while ((fgets (buffer, sizeof (buffer), fp))) {
+       buffer = xmalloc (sizeof (char *) * BUFFERSIZE);
+       memset (buffer, 0, BUFFERSIZE);
+       while ((fgets (buffer, BUFFERSIZE, fp))) {
                var = buffer;
 
                /* Strip leading spaces/tabs */
@@ -474,6 +479,7 @@ bool read_info (const interface_t *iface, dhcp_t *dhcp)
        }
 
        fclose (fp);
+       free (buffer);
        return (true);
 }
 
index 9a87687bd14b363b25cec67c220db68eb56cb385..9964ad360eaead8715d1c86acdbdbb4dc60a87ca 100644 (file)
@@ -259,8 +259,8 @@ interface_t *read_interface (const char *ifname, int metric)
 {
        int s;
        struct ifreq ifr;
-       interface_t *iface;
-       unsigned char hwaddr[20];
+       interface_t *iface = NULL;
+       unsigned char *hwaddr = NULL;
        int hwlen = 0;
        sa_family_t family = 0;
        unsigned short mtu;
@@ -286,8 +286,7 @@ interface_t *read_interface (const char *ifname, int metric)
        strlcpy (ifr.ifr_name, ifname, sizeof (ifr.ifr_name));
        if (ioctl (s, SIOCGIFHWADDR, &ifr) == -1) {
                logger (LOG_ERR, "ioctl SIOCGIFHWADDR: %s", strerror (errno));
-               close (s);
-               return NULL;
+               goto exit;
        }
 
        switch (ifr.ifr_hwaddr.sa_family) {
@@ -302,10 +301,10 @@ interface_t *read_interface (const char *ifname, int metric)
                        break;
                default:
                        logger (LOG_ERR, "interface is not Ethernet, FireWire, InfiniBand or Token Ring");
-                       close (s);
-                       return NULL;
+                       goto exit;
        }
 
+       hwaddr = xmalloc (sizeof (unsigned char *) * HWADDR_LEN);
        memcpy (hwaddr, ifr.ifr_hwaddr.sa_data, hwlen);
        family = ifr.ifr_hwaddr.sa_family;
 #else
@@ -313,14 +312,13 @@ interface_t *read_interface (const char *ifname, int metric)
        strlcpy (ifr.ifr_name, ifname, sizeof (ifr.ifr_name));
        if (ioctl (s, SIOCSIFMETRIC, &ifr) == -1) {
                logger (LOG_ERR, "ioctl SIOCSIFMETRIC: %s", strerror (errno));
-               close (s);
-               return NULL;
+               goto exit;
        }
-       
+
+       hwaddr = xmalloc (sizeof (unsigned char *) * HWADDR_LEN);
        if (_do_interface (ifname, hwaddr, &hwlen, NULL, false, false) != 1) {
                logger (LOG_ERR, "could not find interface %s", ifname);
-               close (s);
-               return NULL;
+               goto exit;
        }
 
        family = ARPHRD_ETHER;
@@ -329,8 +327,7 @@ interface_t *read_interface (const char *ifname, int metric)
        strlcpy (ifr.ifr_name, ifname, sizeof (ifr.ifr_name));
        if (ioctl (s, SIOCGIFMTU, &ifr) == -1) {
                logger (LOG_ERR, "ioctl SIOCGIFMTU: %s", strerror (errno));
-               close (s);
-               return NULL;
+               goto exit;
        }
 
        if (ifr.ifr_mtu < MTU_MIN) {
@@ -339,8 +336,7 @@ interface_t *read_interface (const char *ifname, int metric)
                strlcpy (ifr.ifr_name, ifname, sizeof (ifr.ifr_name));
                if (ioctl (s, SIOCSIFMTU, &ifr) == -1) {
                        logger (LOG_ERR, "ioctl SIOCSIFMTU,: %s", strerror (errno));
-                       close (s);
-                       return NULL;
+                       goto exit;
                }
        }
        mtu = ifr.ifr_mtu;
@@ -353,21 +349,17 @@ interface_t *read_interface (const char *ifname, int metric)
 #endif
        if (ioctl (s, SIOCGIFFLAGS, &ifr) == -1) {
                logger (LOG_ERR, "ioctl SIOCGIFFLAGS: %s", strerror (errno));
-               close (s);
-               return NULL;
+               goto exit;
        }
 
        if (! (ifr.ifr_flags & IFF_UP) || ! (ifr.ifr_flags & IFF_RUNNING)) {
                ifr.ifr_flags |= IFF_UP | IFF_RUNNING;
                if (ioctl (s, SIOCSIFFLAGS, &ifr) == -1) {
                        logger (LOG_ERR, "ioctl SIOCSIFFLAGS: %s", strerror (errno));
-                       close (s);
-                       return NULL;
+                       goto exit;
                }
        }
 
-       close (s);
-
        iface = xmalloc (sizeof (interface_t));
        memset (iface, 0, sizeof (interface_t));
        strlcpy (iface->name, ifname, IF_NAMESIZE);
@@ -387,6 +379,9 @@ interface_t *read_interface (const char *ifname, int metric)
        /* 0 is a valid fd, so init to -1 */
        iface->fd = -1;
 
+exit:
+       close (s);
+       free (hwaddr);
        return iface;
 }
 
@@ -600,12 +595,13 @@ static int do_route (const char *ifname,
                gateway.s_addr == INADDR_ANY)
        {
                /* Make us a link layer socket */
-               unsigned char hwaddr[HWADDR_LEN];
+               unsigned char *hwaddr;
                int hwlen = 0;
 
                if (netmask.s_addr == INADDR_BROADCAST) 
                        rtm.hdr.rtm_flags |= RTF_HOST;
 
+               hwaddr = xmalloc (sizeof (unsigned char *) * HWADDR_LEN);
                _do_interface (ifname, hwaddr, &hwlen, NULL, false, false);
                memset (&su, 0, sizeof (struct sockaddr_storage));
                su.sdl.sdl_len = sizeof (struct sockaddr_dl);
@@ -619,6 +615,7 @@ static int do_route (const char *ifname,
                l = SA_SIZE (&(su.sa));
                memcpy (bp, &su, l);
                bp += l;
+               free (hwaddr);
        } else {
                rtm.hdr.rtm_flags |= RTF_GATEWAY;
                ADDADDR (gateway);
@@ -650,6 +647,7 @@ static int do_route (const char *ifname,
    This blatently taken from libnetlink.c from the iproute2 package
    which is the only good source of netlink code.
    */
+#define BUFFERLEN 256
 static int send_netlink(struct nlmsghdr *hdr)
 {
        int s;
@@ -658,7 +656,7 @@ static int send_netlink(struct nlmsghdr *hdr)
        struct iovec iov;
        struct msghdr msg;
        static unsigned int seq;
-       char buffer[256];
+       char *buffer;
        int bytes;
        union
        {
@@ -699,11 +697,12 @@ static int send_netlink(struct nlmsghdr *hdr)
                return -1;
        }
 
-       memset (buffer, 0, sizeof (buffer));
+       buffer = xmalloc (sizeof (char *) * BUFFERLEN);
+       memset (buffer, 0, BUFFERLEN);
        iov.iov_base = buffer;
 
        while (1) {
-               iov.iov_len = sizeof (buffer);
+               iov.iov_len = BUFFERLEN;
                bytes = recvmsg (s, &msg, 0);
 
                if (bytes == -1) {
@@ -749,6 +748,7 @@ static int send_netlink(struct nlmsghdr *hdr)
                                        errno = -err->error;
                                        if (errno == 0) {
                                                close (s);
+                                               free (buffer);
                                                return 0;
                                        }
 
@@ -778,6 +778,7 @@ next:
 
 eexit:
        close (s);
+       free (buffer);
        return -1;
 }
 
@@ -824,47 +825,61 @@ static int add_attr_32(struct nlmsghdr *n, unsigned int maxlen, int type,
        return 0;
 }
 
+struct nlma
+{
+       struct nlmsghdr hdr;
+       struct ifaddrmsg ifa; 
+       char buffer[64];
+};
+
+struct nlmr
+{
+       struct nlmsghdr hdr;
+       struct rtmsg rt;
+       char buffer[256];
+};
+
 static int do_address(const char *ifname,
                                          struct in_addr address, struct in_addr netmask,
                                          struct in_addr broadcast, int del)
 {
-       struct
-       {
-               struct nlmsghdr hdr;
-               struct ifaddrmsg ifa;
-               char buffer[64];
-       }
-       nlm;
+       struct nlma *nlm;
+       int retval;
 
        if (!ifname)
                return -1;
 
-       memset (&nlm, 0, sizeof (nlm));
+       nlm = xmalloc (sizeof (struct nlma));
+       memset (nlm, 0, sizeof (struct nlma));
 
-       nlm.hdr.nlmsg_len = NLMSG_LENGTH (sizeof (struct ifaddrmsg));
-       nlm.hdr.nlmsg_flags = NLM_F_REQUEST;
+       nlm->hdr.nlmsg_len = NLMSG_LENGTH (sizeof (struct ifaddrmsg));
+       nlm->hdr.nlmsg_flags = NLM_F_REQUEST;
        if (! del)
-               nlm.hdr.nlmsg_flags |= NLM_F_CREATE | NLM_F_REPLACE;
-       nlm.hdr.nlmsg_type = del ? RTM_DELADDR : RTM_NEWADDR;
-       if (! (nlm.ifa.ifa_index = if_nametoindex (ifname))) {
+               nlm->hdr.nlmsg_flags |= NLM_F_CREATE | NLM_F_REPLACE;
+       nlm->hdr.nlmsg_type = del ? RTM_DELADDR : RTM_NEWADDR;
+       if (! (nlm->ifa.ifa_index = if_nametoindex (ifname))) {
                logger (LOG_ERR, "if_nametoindex: Couldn't find index for interface `%s'",
                                ifname);
+               free (nlm);
                return -1;
        }
-       nlm.ifa.ifa_family = AF_INET;
+       nlm->ifa.ifa_family = AF_INET;
 
-       nlm.ifa.ifa_prefixlen = inet_ntocidr (netmask);
+       nlm->ifa.ifa_prefixlen = inet_ntocidr (netmask);
 
        /* This creates the aliased interface */
-       add_attr_l (&nlm.hdr, sizeof (nlm), IFA_LABEL, ifname, strlen (ifname) + 1);
+       add_attr_l (&nlm->hdr, sizeof (struct nlma), IFA_LABEL,
+                               ifname, strlen (ifname) + 1);
 
-       add_attr_l (&nlm.hdr, sizeof (nlm), IFA_LOCAL, &address.s_addr,
-                               sizeof (address.s_addr));
+       add_attr_l (&nlm->hdr, sizeof (struct nlma), IFA_LOCAL,
+                               &address.s_addr, sizeof (address.s_addr));
        if (! del)
-               add_attr_l (&nlm.hdr, sizeof (nlm), IFA_BROADCAST, &broadcast.s_addr,
-                                       sizeof (broadcast.s_addr));
+               add_attr_l (&nlm->hdr, sizeof (struct nlma), IFA_BROADCAST,
+                                       &broadcast.s_addr, sizeof (broadcast.s_addr));
 
-       return send_netlink (&nlm.hdr);
+       retval = send_netlink (&nlm->hdr);
+       free (nlm);
+       return retval;
 }
 
 static int do_route (const char *ifname,
@@ -873,63 +888,61 @@ static int do_route (const char *ifname,
                                         struct in_addr gateway,
                                         int metric, int change, int del)
 {
+       struct nlmr *nlm;
        unsigned int ifindex;
-       struct
-       {
-               struct nlmsghdr hdr;
-               struct rtmsg rt;
-               char buffer[256];
-       }
-       nlm;
+       int retval;
 
        if (! ifname)
                return -1;
 
        log_route (destination, netmask, gateway, metric, change, del);
 
-       memset (&nlm, 0, sizeof (nlm));
+       if (! (ifindex = if_nametoindex (ifname))) {
+               logger (LOG_ERR, "if_nametoindex: Couldn't find index for interface `%s'",
+                               ifname);
+               return -1;
+       }
+
+       nlm = xmalloc (sizeof (struct nlmr));
+       memset (nlm, 0, sizeof (struct nlmr));
 
-       nlm.hdr.nlmsg_len = NLMSG_LENGTH (sizeof (struct rtmsg));
+       nlm->hdr.nlmsg_len = NLMSG_LENGTH (sizeof (struct rtmsg));
        if (change)
-               nlm.hdr.nlmsg_flags = NLM_F_REPLACE;
+               nlm->hdr.nlmsg_flags = NLM_F_REPLACE;
        else if (! del)
-               nlm.hdr.nlmsg_flags = NLM_F_CREATE | NLM_F_EXCL;
-       nlm.hdr.nlmsg_flags |= NLM_F_REQUEST;
-       nlm.hdr.nlmsg_type = del ? RTM_DELROUTE : RTM_NEWROUTE;
-       nlm.rt.rtm_family = AF_INET;
-       nlm.rt.rtm_table = RT_TABLE_MAIN;
+               nlm->hdr.nlmsg_flags = NLM_F_CREATE | NLM_F_EXCL;
+       nlm->hdr.nlmsg_flags |= NLM_F_REQUEST;
+       nlm->hdr.nlmsg_type = del ? RTM_DELROUTE : RTM_NEWROUTE;
+       nlm->rt.rtm_family = AF_INET;
+       nlm->rt.rtm_table = RT_TABLE_MAIN;
 
        if (del)
-               nlm.rt.rtm_scope = RT_SCOPE_NOWHERE;
+               nlm->rt.rtm_scope = RT_SCOPE_NOWHERE;
        else {
-               nlm.hdr.nlmsg_flags |= NLM_F_CREATE | NLM_F_EXCL;
-               nlm.rt.rtm_protocol = RTPROT_BOOT;
+               nlm->hdr.nlmsg_flags |= NLM_F_CREATE | NLM_F_EXCL;
+               nlm->rt.rtm_protocol = RTPROT_BOOT;
                if (netmask.s_addr == INADDR_BROADCAST ||
                        gateway.s_addr == INADDR_ANY)
-                       nlm.rt.rtm_scope = RT_SCOPE_LINK;
+                       nlm->rt.rtm_scope = RT_SCOPE_LINK;
                else
-                       nlm.rt.rtm_scope = RT_SCOPE_UNIVERSE;
-               nlm.rt.rtm_type = RTN_UNICAST;
+                       nlm->rt.rtm_scope = RT_SCOPE_UNIVERSE;
+               nlm->rt.rtm_type = RTN_UNICAST;
        }
 
-       nlm.rt.rtm_dst_len = inet_ntocidr (netmask);
-       add_attr_l (&nlm.hdr, sizeof (nlm), RTA_DST, &destination.s_addr,
-                               sizeof (destination.s_addr));
+       nlm->rt.rtm_dst_len = inet_ntocidr (netmask);
+       add_attr_l (&nlm->hdr, sizeof (struct nlmr), RTA_DST,
+                               &destination.s_addr, sizeof (destination.s_addr));
        if (netmask.s_addr != INADDR_BROADCAST &&
                destination.s_addr != gateway.s_addr)
-               add_attr_l (&nlm.hdr, sizeof (nlm), RTA_GATEWAY, &gateway.s_addr,
-                                       sizeof (gateway.s_addr));
+               add_attr_l (&nlm->hdr, sizeof (struct nlmr), RTA_GATEWAY,
+                                       &gateway.s_addr, sizeof (gateway.s_addr));
 
-       if (! (ifindex = if_nametoindex (ifname))) {
-               logger (LOG_ERR, "if_nametoindex: Couldn't find index for interface `%s'",
-                               ifname);
-               return -1;
-       }
+       add_attr_32 (&nlm->hdr, sizeof (struct nlmr), RTA_OIF, ifindex);
+       add_attr_32 (&nlm->hdr, sizeof (struct nlmr), RTA_PRIORITY, metric);
 
-       add_attr_32 (&nlm.hdr, sizeof (nlm), RTA_OIF, ifindex);
-       add_attr_32 (&nlm.hdr, sizeof (nlm), RTA_PRIORITY, metric);
-
-       return send_netlink (&nlm.hdr);
+       retval = send_netlink (&nlm->hdr);
+       free (nlm);
+       return retval;
 }
 
 #else
index 832c0ab81a96e3bd5dfbb149b6fa9e50646c41e9..bb93992996c1be7c3fc307ed178fc699d9ca457b 100644 (file)
--- a/socket.c
+++ b/socket.c
@@ -39,6 +39,7 @@
 #include <errno.h>
 #include <fcntl.h>
 #include <stdio.h>
+#include <stdlib.h>
 #include <string.h>
 #include <unistd.h>
 
@@ -69,7 +70,6 @@ static uint16_t checksum (unsigned char *addr, uint16_t len)
                nleft -= 2;
        }
 
-
        if (nleft == 1) {
                uint8_t a = 0;
                memcpy (&a, p.i, 1);
@@ -234,16 +234,18 @@ int open_socket (interface_t *iface, bool arp)
 {
        int n = 0;
        int fd = -1;
-       char device[PATH_MAX];
+       char *device;
        int flags;
        struct ifreq ifr;
        int buf = 0;
        struct bpf_program p;
 
+       device = xmalloc (sizeof (char *) * PATH_MAX);
        do {
                snprintf (device, PATH_MAX, "/dev/bpf%d",  n++);
                fd = open (device, O_RDWR);
        } while (fd == -1 && errno == EBUSY);
+       free (device);
 
        if (fd == -1) {
                logger (LOG_ERR, "unable to open a BPF device");