From bd08ae67f9a0cae2ce15be885254cad9449d4551 Mon Sep 17 00:00:00 2001 From: Simon Kelley Date: Fri, 19 Apr 2013 10:22:06 +0100 Subject: [PATCH] Allow option number zero in encapsulated DHCP options. --- src/dhcp-common.c | 6 +++--- src/dnsmasq.h | 4 ++-- src/option.c | 33 ++++++++++++++++++++------------- 3 files changed, 25 insertions(+), 18 deletions(-) diff --git a/src/dhcp-common.c b/src/dhcp-common.c index f4fd088..8de4268 100644 --- a/src/dhcp-common.c +++ b/src/dhcp-common.c @@ -512,7 +512,7 @@ void display_opts6(void) } #endif -u16 lookup_dhcp_opt(int prot, char *name) +int lookup_dhcp_opt(int prot, char *name) { const struct opttab_t *t; int i; @@ -528,10 +528,10 @@ u16 lookup_dhcp_opt(int prot, char *name) if (strcasecmp(t[i].name, name) == 0) return t[i].val; - return 0; + return -1; } -u16 lookup_dhcp_len(int prot, u16 val) +int lookup_dhcp_len(int prot, int val) { const struct opttab_t *t; int i; diff --git a/src/dnsmasq.h b/src/dnsmasq.h index 69ae7a7..41e2798 100644 --- a/src/dnsmasq.h +++ b/src/dnsmasq.h @@ -1216,8 +1216,8 @@ void log_tags(struct dhcp_netid *netid, u32 xid); int match_bytes(struct dhcp_opt *o, unsigned char *p, int len); void dhcp_update_configs(struct dhcp_config *configs); void display_opts(void); -u16 lookup_dhcp_opt(int prot, char *name); -u16 lookup_dhcp_len(int prot, u16 val); +int lookup_dhcp_opt(int prot, char *name); +int lookup_dhcp_len(int prot, int val); char *option_string(int prot, unsigned int opt, unsigned char *val, int opt_len, char *buf, int buf_len); #ifdef HAVE_LINUX_NETWORK diff --git a/src/option.c b/src/option.c index b2596ec..2a61017 100644 --- a/src/option.c +++ b/src/option.c @@ -750,6 +750,7 @@ static int parse_dhcp_opt(char *errstr, char *arg, int flags) struct dhcp_netid *np = NULL; u16 opt_len = 0; int is6 = 0; + int option_ok = 0; new->len = 0; new->flags = flags; @@ -769,16 +770,19 @@ static int parse_dhcp_opt(char *errstr, char *arg, int flags) { new->opt = atoi(arg); opt_len = 0; + option_ok = 1; break; } if (strstr(arg, "option:") == arg) { - new->opt = lookup_dhcp_opt(AF_INET, arg+7); - opt_len = lookup_dhcp_len(AF_INET, new->opt); - /* option: must follow tag and vendor string. */ - if ((opt_len & OT_INTERNAL) && flags != DHOPT_MATCH) - new->opt = 0; + if ((new->opt = lookup_dhcp_opt(AF_INET, arg+7)) != -1) + { + opt_len = lookup_dhcp_len(AF_INET, new->opt); + /* option: must follow tag and vendor string. */ + if (!(opt_len & OT_INTERNAL) || flags == DHOPT_MATCH) + option_ok = 1; + } break; } #ifdef HAVE_DHCP6 @@ -792,13 +796,16 @@ static int parse_dhcp_opt(char *errstr, char *arg, int flags) { new->opt = atoi(arg+8); opt_len = 0; + option_ok = 1; } else { - new->opt = lookup_dhcp_opt(AF_INET6, arg+8); - opt_len = lookup_dhcp_len(AF_INET6, new->opt); - if ((opt_len & OT_INTERNAL) && flags != DHOPT_MATCH) - new->opt = 0; + if ((new->opt = lookup_dhcp_opt(AF_INET6, arg+8)) != -1) + { + opt_len = lookup_dhcp_len(AF_INET6, new->opt); + if (!(opt_len & OT_INTERNAL) || flags == DHOPT_MATCH) + option_ok = 1; + } } /* option6:| must follow tag and vendor string. */ is6 = 1; @@ -821,7 +828,7 @@ static int parse_dhcp_opt(char *errstr, char *arg, int flags) new->flags |= DHOPT_RFC3925; if (flags == DHOPT_MATCH) { - new->opt = 1; /* avoid error below */ + option_ok = 1; break; } } @@ -848,16 +855,16 @@ static int parse_dhcp_opt(char *errstr, char *arg, int flags) if (opt_len == 0 && !(new->flags & DHOPT_RFC3925)) - opt_len = lookup_dhcp_len(AF_INET6 ,new->opt); + opt_len = lookup_dhcp_len(AF_INET6, new->opt); } else #endif if (opt_len == 0 && !(new->flags & (DHOPT_VENDOR | DHOPT_ENCAPSULATE | DHOPT_RFC3925))) - opt_len = lookup_dhcp_len(AF_INET ,new->opt); + opt_len = lookup_dhcp_len(AF_INET, new->opt); /* option may be missing with rfc3925 match */ - if (new->opt == 0) + if (!option_ok) ret_err(_("bad dhcp-option")); if (comma) -- 1.8.1.4