]> git.ipfire.org Git - thirdparty/dhcpcd.git/commitdiff
Stop using static inflexable buffers when cleaning metas and reading files.
authorRoy Marples <roy@marples.name>
Mon, 7 Jan 2008 18:14:51 +0000 (18:14 +0000)
committerRoy Marples <roy@marples.name>
Mon, 7 Jan 2008 18:14:51 +0000 (18:14 +0000)
common.c
common.h
configure.c
info.c

index 815933d10b68274e41d61a5e31d452dde6bb5930..2330889fd7cc90fb2bf1c3d4dc77408ad582f230 100644 (file)
--- a/common.c
+++ b/common.c
 #include "common.h"
 #include "logger.h"
 
+/* Handy routine to read very long lines in text files.
+ * This means we read the whole line and avoid any nasty buffer overflows. */
+char *getline (FILE *fp)
+{
+       char *line = NULL;
+       char *p;
+       size_t len = 0;
+       size_t last = 0;
+
+       if (feof (fp))
+               return (NULL);
+
+       do {
+               len += BUFSIZ;
+               line = xrealloc (line, sizeof (char) * len);
+               p = line + last;
+               fgets (p, BUFSIZ, fp);
+               last += strlen (p);
+       } while (! feof (fp) && line[last - 1] != '\n');
+
+       /* Trim the trailing newline */
+       if (line[--last] == '\n')
+               line[last] = '\0';
+
+       return (line);
+}
+
 /* OK, this should be in dhcpcd.c
  * It's here to make dhcpcd more readable */
 #ifdef __linux__
@@ -174,6 +201,17 @@ void *xmalloc (size_t s)
        exit (EXIT_FAILURE);
 }
 
+void *xrealloc (void *ptr, size_t s)
+{
+       void *value = realloc (ptr, s);
+
+       if (value)
+               return (value);
+
+       logger (LOG_ERR, "memory exhausted");
+       exit (EXIT_FAILURE);
+}
+
 char *xstrdup (const char *str)
 {
        char *value;
index 727eb1788845f4af781330315b1e096407b3b5fa..a4a0a1aef563be21a22949e0ac198be3e56ac4fa 100644 (file)
--- a/common.h
+++ b/common.h
@@ -30,6 +30,7 @@
 
 /* string.h pulls in features.h so the below define checks work */
 #include <sys/time.h>
+#include <stdio.h>
 #include <string.h>
 
 /* Only GLIBC doesn't support strlcpy */
@@ -44,9 +45,11 @@ void srandomdev (void);
 #endif
 
 void close_fds (void);
+char *getline (FILE *fp);
 int get_time (struct timeval *tp);
 long uptime (void);
 void writepid (int fd, pid_t pid);
+void *xrealloc (void *ptr, size_t size);
 void *xmalloc (size_t size);
 char *xstrdup (const char *str);
 
index c2d27d4ff6c7d8571aee05683166874377380993..44551fdd9cbba1e8d378919793cad26026f3e4b8 100644 (file)
@@ -209,13 +209,12 @@ 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;
+       char *line;
        int tomatch = 0;
        char *token;
        bool ntp = false;
@@ -231,16 +230,18 @@ static int _make_ntp (const char *file, const char *ifname, const dhcp_t *dhcp)
                        return -1;
                }
        } else {
-               buffer = xmalloc (sizeof (char) * BUFFERSIZE);
-               memset (buffer, 0, BUFFERSIZE);
-               while (fgets (buffer, BUFFERSIZE, f)) {
-                       a = buffer;
+               while ((line = getline (f))) {
+                       a = line;
                        token = strsep (&a, " ");
-                       if (! token || strcmp (token, "server") != 0)
+                       if (! token || strcmp (token, "server") != 0) {
+                               free (line);
                                continue;
+                       }
 
-                       if ((token = strsep (&a, " \n")) == NULL)
+                       if ((token = strsep (&a, " \n")) == NULL) {
+                               free (line);
                                continue;
+                       }
 
                        for (address = dhcp->ntpservers; address; address = address->next)
                                if (strcmp (token, inet_ntoa (address->address)) == 0) {
@@ -248,10 +249,11 @@ static int _make_ntp (const char *file, const char *ifname, const dhcp_t *dhcp)
                                        break;
                                }
 
-                       if (tomatch == 0)
+                       if (tomatch == 0) {
+                               free (line);
                                break;
+                       }
                }
-               free (buffer);
                fclose (f);
 
                /* File has the same name servers that we do, so no need to restart ntp */
diff --git a/info.c b/info.c
index 4da29395f2077264004fdce81d0100468124d7f0..0a9766cdd977e8f4c0d3fb9f587359e65aeda3c3 100644 (file)
--- a/info.c
+++ b/info.c
 #include "info.h"
 
 #ifdef ENABLE_INFO
-#define BUFFERSIZE 1024
 
+/* Create a malloced string of cstr, changing ' to '\''
+ * so the contents work in a shell */
 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[BUFFERSIZE]; 
-       char *b = buffer;
+       const char *p = cstr;
+       char *new;
+       char *n;
+       size_t len;
 
-       memset (buffer, 0, sizeof (buffer));
-       if (cstr == NULL || strlen (cstr) == 0)
-               return b;
+       if (cstr == NULL || (len = strlen (cstr)) == 0)
+               return (xstrdup (""));
 
+       n = new = xmalloc (sizeof (char) * len + 1);
        do
-               if (*cstr == 39) {
-                       *b++ = '\'';
-                       *b++ = '\\';
-                       *b++ = '\'';
-                       *b++ = '\'';
+               if (*p == '\'') {
+                       size_t pos = n - new;
+                       len += 3;
+                       new = xrealloc (new, sizeof (char) * len + 1);
+                       n = new + pos;
+                       *n++ = '\'';
+                       *n++ = '\\';
+                       *n++ = '\'';
+                       *n++ = '\'';
                } else
-                       *b++ = *cstr;
-       while (*cstr++);
+                       *n++ = *p;
+       while (*p++);
 
-       *b++ = 0;
-       b = buffer;
+       /* Terminate the sucker */
+       *n++ = '\0';
 
-       return b;
+       return (new);
+}
+
+static void print_clean (FILE *f, const char *name, const char *value) {
+       char *clean;
+
+       if (! value)
+               return;
+
+       clean = cleanmetas (value);
+       fprintf (f, "%s='%s'\n", name, clean);
+       free (clean);
 }
 
 bool write_info(const interface_t *iface, const dhcp_t *dhcp,
@@ -129,14 +145,9 @@ bool write_info(const interface_t *iface, const dhcp_t *dhcp,
                fprintf (f, "'\n");
        }
 
-       if (dhcp->hostname)
-               fprintf (f, "HOSTNAME='%s'\n", cleanmetas (dhcp->hostname));
-
-       if (dhcp->dnsdomain)
-               fprintf (f, "DNSDOMAIN='%s'\n", cleanmetas (dhcp->dnsdomain));
-
-       if (dhcp->dnssearch)
-               fprintf (f, "DNSSEARCH='%s'\n", cleanmetas (dhcp->dnssearch));
+       print_clean (f, "HOSTNAME", dhcp->hostname);
+       print_clean (f, "DNSDOMAIN", dhcp->dnsdomain);
+       print_clean (f, "DNSSEARCH", dhcp->dnssearch);
 
        if (dhcp->dnsservers) {
                fprintf (f, "DNSSERVERS='");
@@ -152,7 +163,7 @@ bool write_info(const interface_t *iface, const dhcp_t *dhcp,
                fprintf (f, "FQDNFLAGS='%u'\n", dhcp->fqdn->flags);
                fprintf (f, "FQDNRCODE1='%u'\n", dhcp->fqdn->r1);
                fprintf (f, "FQDNRCODE2='%u'\n", dhcp->fqdn->r2);
-               fprintf (f, "FQDNHOSTNAME='%s'\n", dhcp->fqdn->name);
+               print_clean (f, "FQDNHOSTNAME", dhcp->fqdn->name);
        }
 
        if (dhcp->ntpservers) {
@@ -165,9 +176,7 @@ bool write_info(const interface_t *iface, const dhcp_t *dhcp,
                fprintf (f, "'\n");
        }
 
-       if (dhcp->nisdomain)
-               fprintf (f, "NISDOMAIN='%s'\n", cleanmetas (dhcp->nisdomain));
-
+       print_clean (f, "NISDOMAIN", dhcp->nisdomain);
        if (dhcp->nisservers) {
                fprintf (f, "NISSERVERS='");
                for (address = dhcp->nisservers; address; address = address->next) {
@@ -178,16 +187,14 @@ bool write_info(const interface_t *iface, const dhcp_t *dhcp,
                fprintf (f, "'\n");
        }
 
-       if (dhcp->rootpath)
-               fprintf (f, "ROOTPATH='%s'\n", cleanmetas (dhcp->rootpath));
-
-       if (dhcp->sipservers)
-               fprintf (f, "SIPSERVERS='%s'\n", cleanmetas (dhcp->sipservers));
+       print_clean (f, "ROOTPATH", dhcp->rootpath);
+       print_clean (f, "SIPSERVERS", dhcp->sipservers);
 
        if (dhcp->serveraddress.s_addr)
                fprintf (f, "DHCPSID='%s'\n", inet_ntoa (dhcp->serveraddress));
        if (dhcp->servername[0])
-               fprintf (f, "DHCPSNAME='%s'\n", cleanmetas (dhcp->servername));
+               print_clean (f, "DHCPSNAME", dhcp->servername);
+
        if (! options->doinform && dhcp->address.s_addr) {
                if (! options->test)
                        fprintf (f, "LEASEDFROM='%u'\n", dhcp->leasedfrom);
@@ -195,10 +202,13 @@ bool write_info(const interface_t *iface, const dhcp_t *dhcp,
                fprintf (f, "RENEWALTIME='%u'\n", dhcp->renewaltime);
                fprintf (f, "REBINDTIME='%u'\n", dhcp->rebindtime);
        }
-       fprintf (f, "INTERFACE='%s'\n", iface->name);
-       fprintf (f, "CLASSID='%s'\n", cleanmetas (options->classid));
-       if (options->clientid_len > 0)
-               fprintf (f, "CLIENTID='00:%s'\n", cleanmetas (options->clientid));
+       print_clean (f, "INTERFACE", iface->name);
+       print_clean (f, "CLASSID", options->classid);
+       if (options->clientid_len > 0) {
+               char *clean = cleanmetas (options->clientid);
+               fprintf (f, "CLIENTID='00:%s'\n", clean);
+               free (clean);
+       }
 #ifdef ENABLE_DUID
        else if (iface->duid_length > 0 && options->clientid_len != -1) {
                unsigned char *duid;
@@ -327,7 +337,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;
+       char *line;
        char *var;
        char *value;
        char *p;
@@ -346,10 +356,8 @@ bool read_info (const interface_t *iface, dhcp_t *dhcp)
 
        dhcp->frominfo = true;
 
-       buffer = xmalloc (sizeof (char) * BUFFERSIZE);
-       memset (buffer, 0, BUFFERSIZE);
-       while ((fgets (buffer, BUFFERSIZE, fp))) {
-               var = buffer;
+       while ((line = getline (fp))) {
+               var = line;
 
                /* Strip leading spaces/tabs */
                while ((*var == ' ') || (*var == '\t'))
@@ -360,14 +368,13 @@ bool read_info (const interface_t *iface, dhcp_t *dhcp)
                if (*p == '\n')
                        *p = 0;
 
-
                /* Skip comments */
                if (*var == '#')
-                       continue;
+                       goto next;
                
                /* If we don't have an equals sign then skip it */
                if (! (p = strchr (var, '=')))
-                       continue;
+                       goto next;      
 
                /* Terminate the = so we have two strings */
                *p = 0;
@@ -382,7 +389,7 @@ bool read_info (const interface_t *iface, dhcp_t *dhcp)
 
                /* Don't process null vars or values */
                if (! *var || ! *value)
-                       continue;
+                       goto next;
 
                if (strcmp (var, "IPADDR") == 0)
                        parse_address (&dhcp->address, value, "IPADDR");
@@ -404,7 +411,7 @@ bool read_info (const interface_t *iface, dhcp_t *dhcp)
                                if (! dest || ! net || ! gate) {
                                        logger (LOG_ERR, "read_info ROUTES `%s,%s,%s': invalid route",
                                                        dest, net, gate);
-                                       continue;
+                                       goto next;
                                }
 
                                /* See if we can create a route */
@@ -414,19 +421,19 @@ bool read_info (const interface_t *iface, dhcp_t *dhcp)
                                        logger (LOG_ERR, "read_info ROUTES `%s': not a valid destination address",
                                                        dest);
                                        free (route);
-                                       continue;
+                                       goto next;
                                }
                                if (inet_aton (dest, &route->netmask) == 0) {
                                        logger (LOG_ERR, "read_info ROUTES `%s': not a valid netmask address",
                                                        net);
                                        free (route);
-                                       continue;
+                                       goto next;
                                }
                                if (inet_aton (dest, &route->gateway) == 0) {
                                        logger (LOG_ERR, "read_info ROUTES `%s': not a valid gateway address",
                                                        gate);
                                        free (route);
-                                       continue;
+                                       goto next;
                                }
 
                                /* OK, now add our route */
@@ -482,10 +489,12 @@ bool read_info (const interface_t *iface, dhcp_t *dhcp)
                        parse_uint (&dhcp->renewaltime, value, "RENEWALTIME");
                else if (strcmp (var, "REBINDTIME") == 0)
                        parse_uint (&dhcp->rebindtime, value, "REBINDTIME");
+
+next:
+               free (line);
        }
 
        fclose (fp);
-       free (buffer);
        return (true);
 }