]> git.ipfire.org Git - thirdparty/dhcpcd.git/commitdiff
Allow string and binhex types to have lengths.
authorRoy Marples <roy@marples.name>
Sun, 1 Dec 2013 17:43:49 +0000 (17:43 +0000)
committerRoy Marples <roy@marples.name>
Sun, 1 Dec 2013 17:43:49 +0000 (17:43 +0000)
This is useful when you embed two strings in the same option.

dhcp-common.c
dhcp-common.h
dhcpcd.conf.5.in
if-options.c

index 71b367bb7460758142b2e020a9eedbbbc9226c1f..0f5aec4526f09c1c1d9edab37083101150bc41fc 100644 (file)
@@ -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;
index 24314c0635f563650fbb278849d149ea96881379..eca79e61d88f8956257889813ee4c86fd8197420 100644 (file)
@@ -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
index 373b2016f8be60a06a7b1526783a010bc99db930..0309d61222d98a5f2917d92c4a1f29cde2a28940 100644 (file)
@@ -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)
index 8f59d1b5af7bff5e3a726703521f4d7b56eaf4be..eb68fa50b9550da0a0457c23d9fc903e6fd7579a 100644 (file)
@@ -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)