From: Roy Marples Date: Sun, 1 Dec 2013 17:43:49 +0000 (+0000) Subject: Allow string and binhex types to have lengths. X-Git-Tag: v6.2.0~26 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=b21cd9069369eb20294dfa8f8a6fb71c010aef1a;p=thirdparty%2Fdhcpcd.git Allow string and binhex types to have lengths. This is useful when you embed two strings in the same option. --- diff --git a/dhcp-common.c b/dhcp-common.c index 71b367bb..0f5aec45 100644 --- a/dhcp-common.c +++ b/dhcp-common.c @@ -288,28 +288,36 @@ print_string(char *s, ssize_t len, int dl, const uint8_t *data) } static size_t -dhcp_optlen(int type, size_t dl) +dhcp_optlen(const struct dhcp_opt *opt, size_t dl) { size_t sz; if (dl == 0) return 0; - if (type == 0 || type & (STRING | RFC3442 | RFC5969)) + if (opt->type == 0 || + opt->type & (STRING | BINHEX | RFC3442 | RFC5969)) + { + if (opt->len) { + if ((size_t)opt->len > dl) + return 0; + return opt->len; + } return dl; + } - if ((type & (ADDRIPV4 | ARRAY)) == (ADDRIPV4 | ARRAY)) { + if ((opt->type & (ADDRIPV4 | ARRAY)) == (ADDRIPV4 | ARRAY)) { if (dl < sizeof(uint32_t)) return 0; return dl - (dl % sizeof(uint32_t)); } sz = 0; - if (type & (UINT32 | ADDRIPV4)) + if (opt->type & (UINT32 | ADDRIPV4)) sz = sizeof(uint32_t); - else if (type & UINT16) + else if (opt->type & UINT16) sz = sizeof(uint16_t); - else if (type & UINT8) + else if (opt->type & UINT8) sz = sizeof(uint8_t); else /* If we don't know the size, assume it's valid */ @@ -503,6 +511,8 @@ dhcp_envoption1(char **env, const char *prefix, const char *famprefix, size_t e; char *v, *val; + if (opt->len && opt->len < ol) + ol = opt->len; len = print_option(NULL, 0, opt->type, ol, od, ifname); if (len < 0) return 0; @@ -543,7 +553,7 @@ dhcp_envoption(char **env, const char *prefix, const char *famprefix, n = 0; for (i = 0; i < opt->embopts_len; i++) { eopt = &opt->embopts[i]; - e = dhcp_optlen(eopt->type, ol); + e = dhcp_optlen(eopt, ol); if (e == 0) /* Report error? */ return 0; diff --git a/dhcp-common.h b/dhcp-common.h index 24314c06..eca79e61 100644 --- a/dhcp-common.h +++ b/dhcp-common.h @@ -64,6 +64,7 @@ struct dhcp_opt { uint16_t option; int type; + int len; /* This union allows us to define a global static list of * variable names which we don't free and a list of user defined diff --git a/dhcpcd.conf.5.in b/dhcpcd.conf.5.in index 373b2016..0309d612 100644 --- a/dhcpcd.conf.5.in +++ b/dhcpcd.conf.5.in @@ -22,7 +22,7 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.Dd November 27, 2013 +.Dd December 1, 2013 .Dt DHCPCD.CONF 5 .Os .Sh NAME @@ -515,14 +515,16 @@ The length is determined by the .Ar type . .El .Ss Types to define -If a length is unspecified by the type, it consumes the rest of the option -data. +The type directly affects the length of data consumed inside the option. +Any remaining data is normally discarded. +Lengths can be specified for string and binhex types, but this is generally +with other data embedded afterwards in the same option. .Bl -tag -width indent .It Ic ipaddress An IPv4 address, 4 bytes .It Ic ip6address An IPv6 address, 16 bytes -.It Ic string +.It Ic string Op : Ic length A shell escaped string (binary data escaped as octal) .It Ic byte A byte @@ -538,7 +540,7 @@ An unsigned 32bit integer, 4 bytes A fixed value (1) to indicate that the option is present, 0 bytes .It Ic domain A RFC 3397 encoded string -.It Ic binhex +.It Ic binhex Op : Ic length Binary data expressed as hexadecimal .It Ic embed Contains embedded options (implies encap as well) diff --git a/if-options.c b/if-options.c index 8f59d1b5..eb68fa50 100644 --- a/if-options.c +++ b/if-options.c @@ -527,7 +527,7 @@ strskipwhite(const char *s) static int parse_option(struct if_options *ifo, int opt, const char *arg) { - int i, t; + int i, l, t; char *p = NULL, *fp, *np, **nconf; ssize_t s; struct in_addr addr, addr2; @@ -1246,6 +1246,14 @@ parse_option(struct if_options *ifo, int opt, const char *arg) fp = strwhite(arg); if (fp) *fp++ = '\0'; + np = strchr(arg, ':'); + /* length */ + if (np) { + *np++ = '\0'; + if ((l = atoint(np)) == -1) + return -1; + } else + l = 0; t = 0; if (strcasecmp(arg, "request") == 0) { t |= REQUEST; @@ -1312,6 +1320,11 @@ parse_option(struct if_options *ifo, int opt, const char *arg) syslog(LOG_ERR, "unknown type: %s", arg); return -1; } + if (l && !(t & (STRING | BINHEX))) { + syslog(LOG_WARNING, + "ignoring length for type `%s'", arg); + l = 0; + } /* variable */ if (fp) { arg = strskipwhite(fp); @@ -1359,6 +1372,10 @@ parse_option(struct if_options *ifo, int opt, const char *arg) free_dhcp_opt_embenc(ndop); ndop->option = i; /* could have been 0 */ ndop->type = t; + if (t & (STRING | BINHEX)) + ndop->len = l; + else + ndop->len = 0; ndop->v.dvar = np; /* Save the define for embed and encap options */ if (opt == O_DEFINE || opt == O_DEFINE6)