From: Roy Marples Date: Wed, 2 Jul 2008 17:05:41 +0000 (+0000) Subject: Remove previous toggles for classid, clientid, userclass and vendor - they call ... X-Git-Tag: v4.0.2~250 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=261eb2d41fd97a4bdfb04eac99af3c693701157b;p=thirdparty%2Fdhcpcd.git Remove previous toggles for classid, clientid, userclass and vendor - they call *could* be required for DHCP. Add a string parser and process all user strings through it. --- diff --git a/client.c b/client.c index d71561c3..756c9b81 100644 --- a/client.c +++ b/client.c @@ -465,9 +465,7 @@ client_setup(struct if_state *state, const struct options *options) struct interface *iface = state->interface; struct dhcp_lease *lease = &state->lease; struct in_addr addr; -#ifdef ENABLE_CLIENTID size_t len = 0; -#endif #ifdef ENABLE_DUID unsigned char *duid = NULL; uint32_t ul; @@ -524,7 +522,6 @@ client_setup(struct if_state *state, const struct options *options) iface->net.s_addr = lease->net.s_addr; } -#ifdef ENABLE_CLIENTID if (*options->clientid) { /* Attempt to see if the ClientID is a hardware address */ if ((len = hwaddr_aton(NULL, options->clientid))) { @@ -578,7 +575,6 @@ client_setup(struct if_state *state, const struct options *options) memcpy(iface->clientid + 2, iface->hwaddr, iface->hwlen); } } -#endif return 0; } diff --git a/config.h b/config.h index e6f6a9b0..a18e3c27 100644 --- a/config.h +++ b/config.h @@ -39,24 +39,12 @@ # ifndef DISABLE_ARP # define DISABLE_ARP # endif -# ifndef DISABLE_CLASSID -# define DISABLE_CLASSID -# endif -# ifndef DISABLE_CLIENTID -# define DISABLE_CLIENTID -# endif # ifndef DISABLE_IPV4LL # define DISABLE_IPV4LL # endif # ifndef DISABLE_DUID # define DISABLE_DUID # endif -# ifndef DISABLE_USERCLASS -# define DISABLE_USERCLASS -# endif -# ifndef DISABLE_VENDOR -# define DISABLE_VENDOR -# endif #endif /* Enable ARP by default. */ @@ -64,16 +52,6 @@ # define ENABLE_ARP #endif -/* Allow dhcpcd to send a ClassID */ -#ifndef DISABLE_CLASSID -# define ENABLE_CLASSID -#endif - -/* Send a ClientID in all messages. */ -#ifndef DISABLE_CLIENTID -# define ENABLE_CLIENTID -#endif - /* Allow dhcpcd to create a DUID (LLT) and use it to make an IAID for the * ClientID. Even enabled here, we need a config directive to actually use it * so this toggle is just to remove it from dhcpcd to make the binary smaller. @@ -81,9 +59,7 @@ * hex string that represents the DUID. * See RFC 3315 for details on this. */ #ifndef DISABLE_DUID -# ifdef ENABLE_CLIENTID -# define ENABLE_DUID -# endif +# define ENABLE_DUID #endif /* IPV4LL, aka ZeroConf, aka APIPA, aka RFC 3927. @@ -103,18 +79,6 @@ */ // #define ENABLE_IPV4LL_ALWAYSROUTE -/* Allow dhcpcd to send user class options. */ -#ifndef DISABLE_USERCLASS -# define ENABLE_USERCLASS -#endif - -/* Allow dhcpcd to send encapsulated vendor options (code 43). - * Although this is enabled by default, only custom networks would really - * need it. */ -#ifndef DISABLE_VENDOR -# define ENABLE_VENDOR -#endif - /* Some systems do not have a working fork. */ /* #define THERE_IS_NO_FORK */ diff --git a/dhcp.c b/dhcp.c index 3cb9cd23..451881c2 100644 --- a/dhcp.c +++ b/dhcp.c @@ -710,7 +710,6 @@ make_message(struct dhcp_message **message, uint8_t *d, *m, *p; const char *c; uint8_t *n_params = NULL; - size_t l; time_t up = uptime() - iface->start_uptime; uint32_t ul; uint16_t sz; @@ -782,21 +781,17 @@ make_message(struct dhcp_message **message, } if (type != DHCP_DECLINE && type != DHCP_RELEASE) { -#ifdef ENABLE_USERCLASS if (options->userclass[0]) { *p++ = DHCP_USERCLASS; memcpy(p, options->userclass, options->userclass[0] + 1); p += options->userclass[0] + 1; } -#endif -#ifdef ENABLE_CLASSID if (options->classid[0]) { *p++ = DHCP_CLASSID; memcpy(p, options->classid, options->classid[0] + 1); p += options->classid[0] + 1; } -#endif } if (type == DHCP_DISCOVER || type == DHCP_REQUEST) { @@ -833,13 +828,12 @@ make_message(struct dhcp_message **message, if (options->hostname[0]) { if (options->fqdn == FQDN_DISABLE) { *p++ = DHCP_HOSTNAME; - *p++ = l = strlen(options->hostname); - memcpy(p, options->hostname, l); - p += l; + memcpy(p, options->hostname, options->hostname[0] + 1); + p += options->hostname[0] + 1; } else { /* Draft IETF DHC-FQDN option (81) */ *p++ = DHCP_FQDN; - *p++ = strlen(options->hostname) + 5; + *p++ = options->hostname[0] + 4; /* * Flags: 0000NEOS * S: 1 => Client requests Server to update @@ -853,7 +847,7 @@ make_message(struct dhcp_message **message, *p++ = (options->fqdn & 0x9) | 0x4; *p++ = 0; /* from server for PTR RR */ *p++ = 0; /* from server for A RR if S=1 */ - c = options->hostname; + c = options->hostname + 1; d = p++; while (*c) { if (*c == '.') { @@ -867,14 +861,12 @@ make_message(struct dhcp_message **message, } } -#ifdef ENABLE_VENDOR /* vendor is already encoded correctly, so just add it */ if (options->vendor[0]) { *p++ = DHCP_VENDOR; memcpy(p, options->vendor, options->vendor[0] + 1); p += options->vendor[0] + 1; } -#endif *p++ = DHCP_PARAMETERREQUESTLIST; n_params = p; diff --git a/dhcpcd.c b/dhcpcd.c index 17668472..7617d3a6 100644 --- a/dhcpcd.c +++ b/dhcpcd.c @@ -33,6 +33,7 @@ const char copyright[] = "Copyright (c) 2006-2008 Roy Marples"; #include +#include #include #include #include @@ -204,54 +205,133 @@ add_environ(struct options *options, const char *value, int uniq) return newlist[i]; } +static ssize_t +parse_string(char *buffer, ssize_t len, char *oarg) +{ + ssize_t l; + int i; + char *p, *bp = buffer; + char c[4]; + + /* If surrounded by quotes then it's a string */ + if (*oarg == '"') { + oarg++; + len = strlen(oarg); + p = oarg + len - 1; + if (*p == '"') + *p = '\0'; + } else { + l = hwaddr_aton(NULL, oarg); + if (l > 1) { + if (l > len) { + errno = ENOBUFS; + return -1; + } + hwaddr_aton((uint8_t*)buffer, oarg); + return l; + } + } + + /* Process escapes */ + p = oarg; + l = 0; + c[3] = '\0'; + while (*p) { + if (++l > len) { + errno = ENOBUFS; + return -1; + } + if (*p == '\\') { + p++; + switch(*p++) { + case '\0': + break; + case 'b': + *bp++ = '\b'; + break; + case 'n': + *bp++ = '\n'; + break; + case 'r': + *bp++ = '\r'; + break; + case 't': + *bp++ = '\t'; + break; + case 'x': + /* Grab a hex code */ + c[1] = '\0'; + for (i = 0; i < 2; i++) { + if (isxdigit((unsigned char)*p) == 0) + break; + c[i] = *p++; + } + if (c[1] != '\0') { + c[2] = '\0'; + *bp++ = strtol(c, NULL, 16); + } else + l--; + break; + case '0': + /* Grab an octal code */ + c[2] = '\0'; + for (i = 0; i < 3; i++) { + if (*p < '0' || *p > '7') + break; + c[i] = *p++; + } + if (c[2] != '\0') { + i = strtol(c, NULL, 8); + if (i > 255) + i = 255; + *bp ++= i; + } else + l--; + break; + default: + *bp++ = *p++; + } + } else + *bp++ = *p++; + } + return l; +} + static int parse_option(int opt, char *oarg, struct options *options) { int i; char *p; - size_t olen, s; - uint8_t *u; -#ifdef ENABLE_VENDOR - int j; + ssize_t s; struct in_addr addr; -#endif - - if (oarg) - olen = strlen(oarg); - else - olen = 0; switch(opt) { case 'c': strlcpy(options->script, oarg, sizeof(options->script)); break; case 'h': - if (!oarg) - *options->hostname = '\0'; - else if (olen >= MAXHOSTNAMELEN) { - logger(LOG_ERR, - "`%s' too long for HostName string, max is %d", - oarg, MAXHOSTNAMELEN); + if (oarg) + s = parse_string(options->hostname + 1, + MAXHOSTNAMELEN, oarg); + else + s = 0; + if (s == -1) { + logger(LOG_ERR, "hostname: %s", strerror(errno)); return -1; - } else - strlcpy(options->hostname, oarg, - sizeof(options->hostname)); + } + options->hostname[0] = (uint8_t)s; break; case 'i': -#ifdef ENABLE_CLASSID - if (!oarg) { - *options->classid = '\0'; - } else if (olen >= CLASSID_MAX_LEN) { - logger(LOG_ERR, - "`%s' too long for ClassID string, max is %d", - oarg, CLASSID_MAX_LEN); + if (oarg) + s = parse_string((char *)options->classid + 1, + CLASSID_MAX_LEN, oarg); + else + s = 0; + if (s == -1) { + logger(LOG_ERR, "classid: %s", strerror(errno)); return -1; - } else { - options->classid[0] = strlen(oarg); - strlcpy((char *)options->classid + 1, oarg, - sizeof(options->classid)); } -#endif + *options->classid = (uint8_t)s; break; case 'l': if (*oarg == '-') { @@ -286,7 +366,7 @@ parse_option(int opt, char *oarg, struct options *options) options->options |= DHCPCD_INFORM; options->options |= DHCPCD_PERSISTENT; options->options &= ~DHCPCD_ARP; - if (!oarg || olen == 0) { + if (!oarg || *oarg == '\0') { options->request_address.s_addr = 0; break; } else { @@ -308,7 +388,7 @@ parse_option(int opt, char *oarg, struct options *options) case 'r': if (!(options->options & DHCPCD_INFORM)) options->options |= DHCPCD_REQUEST; - if (olen > 0 && !inet_aton(oarg, &options->request_address)) { + if (*oarg && !inet_aton(oarg, &options->request_address)) { logger(LOG_ERR, "`%s' is not a valid IP address", oarg); return -1; @@ -322,21 +402,19 @@ parse_option(int opt, char *oarg, struct options *options) } break; case 'u': -#ifdef ENABLE_USERCLASS - if (options->userclass[0] + olen + 1 >= USERCLASS_MAX_LEN) { - logger(LOG_ERR, - "userclass overrun, max is %d", - USERCLASS_MAX_LEN); + s = USERCLASS_MAX_LEN - options->userclass[0] - 1; + s = parse_string((char *)options->userclass + options->userclass[0] + 2, + s, oarg); + if (s == -1) { + logger(LOG_ERR, "userclass: %s", strerror(errno)); return -1; } - u = options->userclass + options->userclass[0] + 1; - *u++ = olen; - memcpy(u, oarg, olen); - options->userclass[0] += olen + 1; -#endif + if (s != 0) { + options->userclass[options->userclass[0] + 1] = s; + options->userclass[0] += s + 1; + } break; case 'v': -#ifdef ENABLE_VENDOR p = strchr(oarg, ','); if (!p || !p[1]) { logger(LOG_ERR, "invalid vendor format"); @@ -350,50 +428,27 @@ parse_option(int opt, char *oarg, struct options *options) " 1 and 254 inclusive"); return -1; } - /* string */ - j = 0; - if (*oarg == '"') { - p = oarg + strlen(oarg) - 1; - if (*p == '"') { - oarg++; - *p = '\0'; - } + s = VENDOR_MAX_LEN - options->vendor[0] - 2; + if (inet_aton(oarg, &addr) == 1) { + if (s < 6) { + s = -1; + errno = ENOBUFS; + } else + memcpy(options->vendor + options->vendor[0] + 3, + &addr.s_addr, sizeof(addr.s_addr)); } else { - /* hex encoding */ - errno = 0; - s = hwaddr_aton(NULL, oarg); - if (s > 0) - j = 1; - else { - if (inet_aton(oarg, &addr) == 1) { - s = sizeof(addr.s_addr); - j = 2; - } - } + s = parse_string((char *)options->vendor + options->vendor[0] + 3, + s, oarg); } - if (j == 0) - s = strlen(oarg); - /* Need to include then len char */ - if (options->vendor[0] + s + 1 > VENDOR_MAX_LEN) { - logger(LOG_ERR, "vendor option is too long"); + if (s == -1) { + logger(LOG_ERR, "vendor: %s", strerror(errno)); return -1; } - u = options->vendor + options->vendor[0] + 1; - options->vendor[0] += s + 2; - *u++ = (uint8_t)i; - *u++ = (uint8_t)s; - switch(j) { - case 0: - memcpy(u, oarg, s); - break; - case 1: - hwaddr_aton(u, oarg); - break; - case 2: - memcpy(u, &addr.s_addr, s); - break; + if (s != 0) { + options->vendor[options->vendor[0] + 1] = i; + options->vendor[options->vendor[0] + 2] = s; + options->vendor[0] += s + 2; } -#endif break; case 'A': options->options &= ~DHCPCD_ARP; @@ -404,7 +459,7 @@ parse_option(int opt, char *oarg, struct options *options) /* Commas to spaces for shell */ while ((p = strchr(oarg, ','))) *p = ' '; - s = strlen("skip_hooks=") + olen + 1; + s = strlen("skip_hooks=") + strlen(oarg) + 1; p = xmalloc(sizeof(char) * s); snprintf(p, s, "skip_hooks=%s", oarg); add_environ(options, p, 0); @@ -437,27 +492,20 @@ parse_option(int opt, char *oarg, struct options *options) options->options &= ~DHCPCD_GATEWAY; break; case 'I': -#ifdef ENABLE_CLIENTID - if (oarg) { - if (olen >= CLIENTID_MAX_LEN) { - logger(LOG_ERR, "`%s' is too long for" - " ClientID, max is %d", - oarg, CLIENTID_MAX_LEN); - return -1; - } - if (strlcpy(options->clientid, oarg, - CLIENTID_MAX_LEN) == 0) - { - /* empty string disabled duid */ - options->options &= ~DHCPCD_DUID; - options->options &= ~DHCPCD_CLIENTID; - } - } else { - options->clientid[0] = '\0'; + if (oarg) + s = parse_string((char *)options->classid + 1, + CLIENTID_MAX_LEN, oarg); + else + s = 0; + if (s == -1) { + logger(LOG_ERR, "classid: %s", strerror(errno)); + return -1; + } + options->clientid[0] = (uint8_t)s; + if (s == 0) { options->options &= ~DHCPCD_DUID; options->options &= ~DHCPCD_CLIENTID; } -#endif break; case 'K': options->options &= ~DHCPCD_DAEMONISE; @@ -509,8 +557,7 @@ main(int argc, char **argv) int pid_fd = -1; int sig = 0; int retval = EXIT_FAILURE; - char *line, *option, *p, *lp, *buffer = NULL; - char lt; + char *line, *option, *p, *buffer = NULL; size_t len = 0; FILE *f; char *cf = NULL; @@ -521,20 +568,15 @@ main(int argc, char **argv) options = xzalloc(sizeof(*options)); strlcpy(options->script, SCRIPT, sizeof(options->script)); -#ifdef ENABLE_CLASSID options->classid[0] = snprintf((char *)options->classid + 1, CLASSID_MAX_LEN, "%s %s", PACKAGE, VERSION); -#endif - options->options |= DHCPCD_GATEWAY | DHCPCD_DAEMONISE; + options->options |= DHCPCD_CLIENTID | DHCPCD_GATEWAY | DHCPCD_DAEMONISE; #ifdef ENABLE_ARP options->options |= DHCPCD_ARP; #ifdef ENABLE_IPV4LL options->options |= DHCPCD_IPV4LL; #endif -#endif -#ifdef ENABLE_CLIENTID - options->options |= DHCPCD_CLIENTID; #endif options->timeout = DEFAULT_TIMEOUT; @@ -566,10 +608,11 @@ main(int argc, char **argv) } #endif - gethostname(options->hostname, sizeof(options->hostname)); - if (strcmp(options->hostname, "(none)") == 0 || - strcmp(options->hostname, "localhost") == 0) - *options->hostname = '\0'; + gethostname(options->hostname + 1, sizeof(options->hostname)); + if (strcmp(options->hostname + 1, "(none)") == 0 || + strcmp(options->hostname + 1, "localhost") == 0) + options->hostname[1] = '\0'; + *options->hostname = strlen(options->hostname + 1); while ((opt = getopt_long(argc, argv, OPTS EXTRA_OPTS, longopts, &option_index)) != -1) @@ -599,24 +642,12 @@ main(int argc, char **argv) #ifdef ENABLE_ARP " ARP" #endif -#ifdef ENABLE_CLASSID - " CLASSID" -#endif -#ifdef ENABLE_CLIENTID - " CLIENTID" -#endif #ifdef ENABLE_DUID " DUID" #endif #ifdef ENABLE_IPV4LL " IPV4LL" #endif -#ifdef ENABLE_USERCLASS - " USERCLASS" -#endif -#ifdef ENABLE_VENDOR - " VENDOR" -#endif #ifdef THERE_IS_NO_FORK " THERE_IS_NO_FORK" #endif @@ -663,38 +694,13 @@ main(int argc, char **argv) line++; } /* Trim trailing whitespace */ - lt = '\\'; if (line && *line) { p = line + strlen(line) - 1; - while (p != line && (*p == ' ' || *p == '\t')) { - /* Remember the last char trimmed */ - lt = *p; + while (p != line && + (*p == ' ' || *p == '\t') && + *(p - 1) != '\\') *p-- = '\0'; - } } - /* Remove quotes if present */ - if (line && *line == '"') { - p = line + strlen(line) - 1; - if (*p == '"') { - line++; - *p = '\0'; - } - } - /* Process escapes */ - lp = p = line; - while (p && *p) { - if (*p == '\\') - p++; - /* EOL? */ - if (*p == '\0') { - /* Restore the last char trimmed */ - *lp++ = lt; - break; - } - *lp++ = *p++; - } - if (lp) - *lp = '\0'; if (strcmp(option, "interface") == 0) { free(intf); intf = xstrdup(line); @@ -929,13 +935,11 @@ main(int argc, char **argv) logger(LOG_INFO, PACKAGE " " VERSION " starting"); } -#ifdef ENABLE_VENDOR /* Terminate the encapsulated options */ if (options->vendor[0]) { options->vendor[0]++; options->vendor[options->vendor[0]] = DHCP_END; } -#endif if (dhcp_run(options, &pid_fd) == 0) retval = EXIT_SUCCESS; diff --git a/dhcpcd.h b/dhcpcd.h index 21ddf699..4f2c841c 100644 --- a/dhcpcd.h +++ b/dhcpcd.h @@ -73,18 +73,10 @@ struct options { char interface[IF_NAMESIZE]; char hostname[MAXHOSTNAMELEN]; int fqdn; -#ifdef ENABLE_CLASSID uint8_t classid[CLASSID_MAX_LEN + 1]; -#endif -#ifdef ENABLE_CLIENTID char clientid[CLIENTID_MAX_LEN + 1]; -#endif -#ifdef ENABLE_USERCLASS uint8_t userclass[USERCLASS_MAX_LEN + 1]; -#endif -#ifdef ENABLE_VENDOR uint8_t vendor[VENDOR_MAX_LEN + 1]; -#endif uint8_t reqmask[256 / 8]; uint8_t nomask[256 / 8]; uint32_t leasetime;