1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
|
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
|