| From bd08ae67f9a0cae2ce15be885254cad9449d4551 Mon Sep 17 00:00:00 2001 |
| From: Simon Kelley <simon@thekelleys.org.uk> |
| Date: Fri, 19 Apr 2013 10:22:06 +0100 |
| Subject: [PATCH] Allow option number zero in encapsulated DHCP options. |
| |
| |
| Signed-off-by: Gustavo Zacarias <gustavo@zacarias.com.ar> |
| --- |
| 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:<optname> 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:<optname> 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:<opt>|<optname> 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.5 |