odhcp6c: add support for user string options
authorHans Dedecker <dedeckeh@gmail.com>
Fri, 8 Jun 2018 14:29:50 +0000 (16:29 +0200)
committerHans Dedecker <dedeckeh@gmail.com>
Mon, 11 Jun 2018 13:27:18 +0000 (15:27 +0200)
Support user defined options having a string as option value.
The option value is detected as a string if it starts and ends with
either a double or single quote.

Signed-off-by: Hans Dedecker <dedeckeh@gmail.com>
src/odhcp6c.c
src/odhcp6c.h

index 48e3dee1cea2c9545e03583e9dab5578698d20bf..2fb8abf0ae1391766953aa2fb216f331df702801 100644 (file)
@@ -560,6 +560,7 @@ static int usage(void)
        "                       -x dns:2001:2001::1,2001:2001::2 - option 23\n"
        "                       -x 15:office - option 15 (userclass)\n"
        "                       -x 0x1f4:ABBA - option 500\n"
+       "                       -x 202:'\"file\"' - option 202\n"
        "       -c <clientid>   Override client-ID (base-16 encoded 16-bit type + value)\n"
        "       -i <iface-id>   Use a custom interface identifier for RA handling\n"
        "       -r <options>    Options to be requested (comma-separated)\n"
@@ -969,6 +970,40 @@ static int parse_opt_u8(const char *src, uint8_t **dst)
        return script_unhexlify(*dst, len, src);
 }
 
+static int parse_opt_string(const char *src, uint8_t **dst, const bool array)
+{
+       int i_len = strlen(src);
+       int o_len = 0;
+       char *sep = get_sep_pos(src, ARRAY_SEP);
+
+       if (sep && !array)
+               return -1;
+
+       do {
+               if (sep) {
+                       *sep = 0;
+                       sep++;
+               }
+
+               int len = strlen(src);
+
+               *dst = realloc(*dst, o_len + len);
+               if (!*dst)
+                       return -1;
+
+               memcpy(&((*dst)[o_len]), src, len);
+
+               o_len += len;
+               i_len -= strlen(src) + (sep ? 1 : 0);
+               src = sep;
+
+               if (sep)
+                       sep = get_sep_pos(src, ARRAY_SEP);
+       } while (i_len);
+
+       return o_len;
+}
+
 static int parse_opt_dns_string(const char *src, uint8_t **dst, const bool array)
 {
        int i_len = strlen(src);
@@ -1091,6 +1126,10 @@ static int parse_opt_data(const char *data, uint8_t **dst, const unsigned int ty
                ret = parse_opt_u8(data, dst);
                break;
 
+       case OPT_STR:
+               ret = parse_opt_string(data, dst, array);
+               break;
+
        case OPT_DNS_STR:
                ret = parse_opt_dns_string(data, dst, array);
                break;
@@ -1151,6 +1190,16 @@ static int parse_opt(const char *opt)
 
                type = dopt->flags & OPT_MASK_SIZE;
                array = ((dopt->flags & OPT_ARRAY) == OPT_ARRAY) ? true : false;
+       } else if (data[0] == '"' || data[0] == '\'') {
+               char *end = strrchr(data + 1, data[0]);
+
+               if (end && (end == (data + strlen(data) - 1))) {
+                       /* Raw option is specified as a string */
+                       type = OPT_STR;
+                       data++;
+                       *end = '\0';
+               }
+
        }
 
        payload_len = parse_opt_data(data, &payload, type, array);
index 3abe7b7528801aac091f78a416604b420b7d280a..97809f1543672a8c6359cea20386560037c849a9 100644 (file)
@@ -325,6 +325,7 @@ struct odhcp6c_request_prefix {
 enum odhcp6c_opt_flags {
        OPT_U8 = 0,
        OPT_IP6,
+       OPT_STR,
        OPT_DNS_STR,
        OPT_USER_CLASS,
        OPT_MASK_SIZE = 0x0F,