diff options
author | Denys Vlasenko <vda.linux@googlemail.com> | 2010-03-26 08:35:24 +0100 |
---|---|---|
committer | Denys Vlasenko <vda.linux@googlemail.com> | 2010-03-26 08:35:24 +0100 |
commit | a8f6b9998727ad67db4b812270a1bbceea011dde (patch) | |
tree | fbe3633852270c9fd33674513fdb289a617697ad | |
parent | 7e6add1dfca95183bf409820066fab975979bf06 (diff) | |
download | busybox-w32-a8f6b9998727ad67db4b812270a1bbceea011dde.tar.gz busybox-w32-a8f6b9998727ad67db4b812270a1bbceea011dde.tar.bz2 busybox-w32-a8f6b9998727ad67db4b812270a1bbceea011dde.zip |
udhcp: move options.c to common.c; disable unused bool and s16 option code
function old new delta
udhcp_add_binary_option - 94 +94
udhcp_str2nip - 42 +42
len_of_option_as_string 12 10 -2
dhcp_option_lengths 12 10 -2
udhcpc_main 2859 2851 -8
read_nip 42 - -42
xmalloc_optname_optval 590 536 -54
udhcp_str2optset 443 366 -77
udhcp_add_option_string 86 - -86
------------------------------------------------------------------------------
(add/remove: 2/2 grow/shrink: 0/5 up/down: 136/-271) Total: -135 bytes
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
-rw-r--r-- | networking/udhcp/Kbuild | 4 | ||||
-rw-r--r-- | networking/udhcp/common.c | 454 | ||||
-rw-r--r-- | networking/udhcp/common.h | 14 | ||||
-rw-r--r-- | networking/udhcp/dhcpc.c | 33 | ||||
-rw-r--r-- | networking/udhcp/dhcpd.c | 2 | ||||
-rw-r--r-- | networking/udhcp/dhcpd.h | 1 | ||||
-rw-r--r-- | networking/udhcp/files.c | 212 | ||||
-rw-r--r-- | networking/udhcp/options.c | 262 |
8 files changed, 485 insertions, 497 deletions
diff --git a/networking/udhcp/Kbuild b/networking/udhcp/Kbuild index c09f9aaf0..1803903f0 100644 --- a/networking/udhcp/Kbuild +++ b/networking/udhcp/Kbuild | |||
@@ -7,8 +7,8 @@ | |||
7 | 7 | ||
8 | lib-y:= | 8 | lib-y:= |
9 | 9 | ||
10 | lib-$(CONFIG_UDHCPC) += common.o options.o packet.o signalpipe.o socket.o | 10 | lib-$(CONFIG_UDHCPC) += common.o packet.o signalpipe.o socket.o |
11 | lib-$(CONFIG_UDHCPD) += common.o options.o packet.o signalpipe.o socket.o | 11 | lib-$(CONFIG_UDHCPD) += common.o packet.o signalpipe.o socket.o |
12 | 12 | ||
13 | lib-$(CONFIG_UDHCPC) += dhcpc.o | 13 | lib-$(CONFIG_UDHCPC) += dhcpc.o |
14 | lib-$(CONFIG_UDHCPD) += dhcpd.o arpping.o files.o leases.o static_leases.o | 14 | lib-$(CONFIG_UDHCPD) += dhcpd.o arpping.o files.o leases.o static_leases.o |
diff --git a/networking/udhcp/common.c b/networking/udhcp/common.c index 4de29f258..bc458ac7a 100644 --- a/networking/udhcp/common.c +++ b/networking/udhcp/common.c | |||
@@ -1,7 +1,8 @@ | |||
1 | /* vi: set sw=4 ts=4: */ | 1 | /* vi: set sw=4 ts=4: */ |
2 | /* common.c | 2 | /* |
3 | * Rewrite by Russ Dill <Russ.Dill@asu.edu> July 2001 | ||
3 | * | 4 | * |
4 | * Licensed under GPLv2 or later, see file LICENSE in this tarball for details. | 5 | * Licensed under GPLv2, see file LICENSE in this tarball for details. |
5 | */ | 6 | */ |
6 | #include "common.h" | 7 | #include "common.h" |
7 | 8 | ||
@@ -12,3 +13,452 @@ unsigned dhcp_verbose; | |||
12 | const uint8_t MAC_BCAST_ADDR[6] ALIGN2 = { | 13 | const uint8_t MAC_BCAST_ADDR[6] ALIGN2 = { |
13 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff | 14 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff |
14 | }; | 15 | }; |
16 | |||
17 | /* Supported options are easily added here. | ||
18 | * See RFC2132 for more options. | ||
19 | * OPTION_REQ: these options are requested by udhcpc (unless -o). | ||
20 | */ | ||
21 | const struct dhcp_option dhcp_options[] = { | ||
22 | /* flags code */ | ||
23 | { OPTION_IP | OPTION_REQ, 0x01 }, /* DHCP_SUBNET */ | ||
24 | { OPTION_S32 , 0x02 }, /* DHCP_TIME_OFFSET */ | ||
25 | { OPTION_IP | OPTION_LIST | OPTION_REQ, 0x03 }, /* DHCP_ROUTER */ | ||
26 | // { OPTION_IP | OPTION_LIST , 0x04 }, /* DHCP_TIME_SERVER */ | ||
27 | // { OPTION_IP | OPTION_LIST , 0x05 }, /* DHCP_NAME_SERVER */ | ||
28 | { OPTION_IP | OPTION_LIST | OPTION_REQ, 0x06 }, /* DHCP_DNS_SERVER */ | ||
29 | // { OPTION_IP | OPTION_LIST , 0x07 }, /* DHCP_LOG_SERVER */ | ||
30 | // { OPTION_IP | OPTION_LIST , 0x08 }, /* DHCP_COOKIE_SERVER */ | ||
31 | { OPTION_IP | OPTION_LIST , 0x09 }, /* DHCP_LPR_SERVER */ | ||
32 | { OPTION_STRING | OPTION_REQ, 0x0c }, /* DHCP_HOST_NAME */ | ||
33 | { OPTION_U16 , 0x0d }, /* DHCP_BOOT_SIZE */ | ||
34 | { OPTION_STRING | OPTION_REQ, 0x0f }, /* DHCP_DOMAIN_NAME */ | ||
35 | { OPTION_IP , 0x10 }, /* DHCP_SWAP_SERVER */ | ||
36 | { OPTION_STRING , 0x11 }, /* DHCP_ROOT_PATH */ | ||
37 | { OPTION_U8 , 0x17 }, /* DHCP_IP_TTL */ | ||
38 | { OPTION_U16 , 0x1a }, /* DHCP_MTU */ | ||
39 | { OPTION_IP | OPTION_REQ, 0x1c }, /* DHCP_BROADCAST */ | ||
40 | { OPTION_STRING , 0x28 }, /* DHCP_NIS_DOMAIN */ | ||
41 | { OPTION_IP | OPTION_LIST , 0x29 }, /* DHCP_NIS_SERVER */ | ||
42 | { OPTION_IP | OPTION_LIST | OPTION_REQ, 0x2a }, /* DHCP_NTP_SERVER */ | ||
43 | { OPTION_IP | OPTION_LIST , 0x2c }, /* DHCP_WINS_SERVER */ | ||
44 | { OPTION_U32 , 0x33 }, /* DHCP_LEASE_TIME */ | ||
45 | { OPTION_IP , 0x36 }, /* DHCP_SERVER_ID */ | ||
46 | { OPTION_STRING , 0x38 }, /* DHCP_ERR_MESSAGE */ | ||
47 | //TODO: must be combined with 'sname' and 'file' handling: | ||
48 | { OPTION_STRING , 0x42 }, /* DHCP_TFTP_SERVER_NAME */ | ||
49 | { OPTION_STRING , 0x43 }, /* DHCP_BOOT_FILE */ | ||
50 | //TODO: not a string, but a set of LASCII strings: | ||
51 | // { OPTION_STRING , 0x4D }, /* DHCP_USER_CLASS */ | ||
52 | #if ENABLE_FEATURE_UDHCP_RFC3397 | ||
53 | { OPTION_STR1035 | OPTION_LIST , 0x77 }, /* DHCP_DOMAIN_SEARCH */ | ||
54 | #endif | ||
55 | { OPTION_STATIC_ROUTES , 0x79 }, /* DHCP_STATIC_ROUTES */ | ||
56 | { OPTION_STRING , 0xfc }, /* DHCP_WPAD */ | ||
57 | |||
58 | /* Options below have no match in dhcp_option_strings[], | ||
59 | * are not passed to dhcpc scripts, and cannot be specified | ||
60 | * with "option XXX YYY" syntax in dhcpd config file. | ||
61 | * These entries are only used internally by udhcp[cd] | ||
62 | * to correctly encode options into packets. | ||
63 | */ | ||
64 | |||
65 | { OPTION_IP , 0x32 }, /* DHCP_REQUESTED_IP */ | ||
66 | { OPTION_U8 , 0x35 }, /* DHCP_MESSAGE_TYPE */ | ||
67 | { OPTION_U16 , 0x39 }, /* DHCP_MAX_SIZE */ | ||
68 | { OPTION_STRING , 0x3c }, /* DHCP_VENDOR */ | ||
69 | //FIXME: handling of this option is not exactly correct: | ||
70 | { OPTION_STRING , 0x3d }, /* DHCP_CLIENT_ID */ | ||
71 | { 0, 0 } /* zeroed terminating entry */ | ||
72 | }; | ||
73 | |||
74 | /* Used for converting options from incoming packets to env variables | ||
75 | * for udhcpc stript, and for setting options for udhcpd via | ||
76 | * "opt OPTION_NAME OPTION_VALUE" directives in udhcpd.conf file. | ||
77 | */ | ||
78 | /* Must match dhcp_options[] order */ | ||
79 | const char dhcp_option_strings[] ALIGN1 = | ||
80 | "subnet" "\0" /* DHCP_SUBNET */ | ||
81 | "timezone" "\0" /* DHCP_TIME_OFFSET */ | ||
82 | "router" "\0" /* DHCP_ROUTER */ | ||
83 | // "timesrv" "\0" /* DHCP_TIME_SERVER */ | ||
84 | // "namesrv" "\0" /* DHCP_NAME_SERVER */ | ||
85 | "dns" "\0" /* DHCP_DNS_SERVER */ | ||
86 | // "logsrv" "\0" /* DHCP_LOG_SERVER */ | ||
87 | // "cookiesrv" "\0" /* DHCP_COOKIE_SERVER */ | ||
88 | "lprsrv" "\0" /* DHCP_LPR_SERVER */ | ||
89 | "hostname" "\0" /* DHCP_HOST_NAME */ | ||
90 | "bootsize" "\0" /* DHCP_BOOT_SIZE */ | ||
91 | "domain" "\0" /* DHCP_DOMAIN_NAME */ | ||
92 | "swapsrv" "\0" /* DHCP_SWAP_SERVER */ | ||
93 | "rootpath" "\0" /* DHCP_ROOT_PATH */ | ||
94 | "ipttl" "\0" /* DHCP_IP_TTL */ | ||
95 | "mtu" "\0" /* DHCP_MTU */ | ||
96 | "broadcast" "\0" /* DHCP_BROADCAST */ | ||
97 | "nisdomain" "\0" /* DHCP_NIS_DOMAIN */ | ||
98 | "nissrv" "\0" /* DHCP_NIS_SERVER */ | ||
99 | "ntpsrv" "\0" /* DHCP_NTP_SERVER */ | ||
100 | "wins" "\0" /* DHCP_WINS_SERVER */ | ||
101 | "lease" "\0" /* DHCP_LEASE_TIME */ | ||
102 | "serverid" "\0" /* DHCP_SERVER_ID */ | ||
103 | "message" "\0" /* DHCP_ERR_MESSAGE */ | ||
104 | "tftp" "\0" /* DHCP_TFTP_SERVER_NAME */ | ||
105 | "bootfile" "\0" /* DHCP_BOOT_FILE */ | ||
106 | // "userclass" "\0" /* DHCP_USER_CLASS */ | ||
107 | #if ENABLE_FEATURE_UDHCP_RFC3397 | ||
108 | "search" "\0" /* DHCP_DOMAIN_SEARCH */ | ||
109 | #endif | ||
110 | // "staticroutes" is only used to set udhcpc environment, it doesn't work | ||
111 | // in udhcpd.conf since OPTION_STATIC_ROUTES is not handled yet | ||
112 | // by "string->option" conversion code: | ||
113 | "staticroutes" "\0"/* DHCP_STATIC_ROUTES */ | ||
114 | "wpad" "\0" /* DHCP_WPAD */ | ||
115 | ; | ||
116 | |||
117 | /* Lengths of the different option types */ | ||
118 | const uint8_t dhcp_option_lengths[] ALIGN1 = { | ||
119 | [OPTION_IP] = 4, | ||
120 | [OPTION_IP_PAIR] = 8, | ||
121 | // [OPTION_BOOLEAN] = 1, | ||
122 | [OPTION_STRING] = 1, | ||
123 | #if ENABLE_FEATURE_UDHCP_RFC3397 | ||
124 | [OPTION_STR1035] = 1, | ||
125 | #endif | ||
126 | [OPTION_U8] = 1, | ||
127 | [OPTION_U16] = 2, | ||
128 | // [OPTION_S16] = 2, | ||
129 | [OPTION_U32] = 4, | ||
130 | [OPTION_S32] = 4, | ||
131 | /* Just like OPTION_STRING, we use minimum length here */ | ||
132 | [OPTION_STATIC_ROUTES] = 5, | ||
133 | }; | ||
134 | |||
135 | |||
136 | #if defined CONFIG_UDHCP_DEBUG && CONFIG_UDHCP_DEBUG >= 2 | ||
137 | static void log_option(const char *pfx, const uint8_t *opt) | ||
138 | { | ||
139 | if (dhcp_verbose >= 2) { | ||
140 | char buf[256 * 2 + 2]; | ||
141 | *bin2hex(buf, (void*) (opt + OPT_DATA), opt[OPT_LEN]) = '\0'; | ||
142 | bb_info_msg("%s: 0x%02x %s", pfx, opt[OPT_CODE], buf); | ||
143 | } | ||
144 | } | ||
145 | #else | ||
146 | # define log_option(pfx, opt) ((void)0) | ||
147 | #endif | ||
148 | |||
149 | /* get an option with bounds checking (warning, result is not aligned). */ | ||
150 | uint8_t* FAST_FUNC udhcp_get_option(struct dhcp_packet *packet, int code) | ||
151 | { | ||
152 | uint8_t *optionptr; | ||
153 | int len; | ||
154 | int rem; | ||
155 | int overload = 0; | ||
156 | enum { | ||
157 | FILE_FIELD101 = FILE_FIELD * 0x101, | ||
158 | SNAME_FIELD101 = SNAME_FIELD * 0x101, | ||
159 | }; | ||
160 | |||
161 | /* option bytes: [code][len][data1][data2]..[dataLEN] */ | ||
162 | optionptr = packet->options; | ||
163 | rem = sizeof(packet->options); | ||
164 | while (1) { | ||
165 | if (rem <= 0) { | ||
166 | bb_error_msg("bad packet, malformed option field"); | ||
167 | return NULL; | ||
168 | } | ||
169 | if (optionptr[OPT_CODE] == DHCP_PADDING) { | ||
170 | rem--; | ||
171 | optionptr++; | ||
172 | continue; | ||
173 | } | ||
174 | if (optionptr[OPT_CODE] == DHCP_END) { | ||
175 | if ((overload & FILE_FIELD101) == FILE_FIELD) { | ||
176 | /* can use packet->file, and didn't look at it yet */ | ||
177 | overload |= FILE_FIELD101; /* "we looked at it" */ | ||
178 | optionptr = packet->file; | ||
179 | rem = sizeof(packet->file); | ||
180 | continue; | ||
181 | } | ||
182 | if ((overload & SNAME_FIELD101) == SNAME_FIELD) { | ||
183 | /* can use packet->sname, and didn't look at it yet */ | ||
184 | overload |= SNAME_FIELD101; /* "we looked at it" */ | ||
185 | optionptr = packet->sname; | ||
186 | rem = sizeof(packet->sname); | ||
187 | continue; | ||
188 | } | ||
189 | break; | ||
190 | } | ||
191 | len = 2 + optionptr[OPT_LEN]; | ||
192 | rem -= len; | ||
193 | if (rem < 0) | ||
194 | continue; /* complain and return NULL */ | ||
195 | |||
196 | if (optionptr[OPT_CODE] == code) { | ||
197 | log_option("Option found", optionptr); | ||
198 | return optionptr + OPT_DATA; | ||
199 | } | ||
200 | |||
201 | if (optionptr[OPT_CODE] == DHCP_OPTION_OVERLOAD) { | ||
202 | overload |= optionptr[OPT_DATA]; | ||
203 | /* fall through */ | ||
204 | } | ||
205 | optionptr += len; | ||
206 | } | ||
207 | |||
208 | /* log3 because udhcpc uses it a lot - very noisy */ | ||
209 | log3("Option 0x%02x not found", code); | ||
210 | return NULL; | ||
211 | } | ||
212 | |||
213 | /* return the position of the 'end' option (no bounds checking) */ | ||
214 | int FAST_FUNC udhcp_end_option(uint8_t *optionptr) | ||
215 | { | ||
216 | int i = 0; | ||
217 | |||
218 | while (optionptr[i] != DHCP_END) { | ||
219 | if (optionptr[i] != DHCP_PADDING) | ||
220 | i += optionptr[i + OPT_LEN] + OPT_DATA-1; | ||
221 | i++; | ||
222 | } | ||
223 | return i; | ||
224 | } | ||
225 | |||
226 | /* Add an option (supplied in binary form) to the options. | ||
227 | * Option format: [code][len][data1][data2]..[dataLEN] | ||
228 | */ | ||
229 | void FAST_FUNC udhcp_add_binary_option(uint8_t *optionptr, uint8_t *addopt) | ||
230 | { | ||
231 | unsigned len; | ||
232 | unsigned end = udhcp_end_option(optionptr); | ||
233 | |||
234 | /* end position + option code/length + addopt length + end option */ | ||
235 | len = OPT_DATA + addopt[OPT_LEN]; | ||
236 | if (end + len + 1 >= DHCP_OPTIONS_BUFSIZE) { | ||
237 | bb_error_msg("option 0x%02x did not fit into the packet", | ||
238 | addopt[OPT_CODE]); | ||
239 | return; | ||
240 | } | ||
241 | log_option("Adding option", addopt); | ||
242 | memcpy(optionptr + end, addopt, len); | ||
243 | optionptr[end + len] = DHCP_END; | ||
244 | } | ||
245 | |||
246 | /* Add a one to four byte option to a packet */ | ||
247 | void FAST_FUNC udhcp_add_simple_option(uint8_t *optionptr, uint8_t code, uint32_t data) | ||
248 | { | ||
249 | const struct dhcp_option *dh; | ||
250 | |||
251 | for (dh = dhcp_options; dh->code; dh++) { | ||
252 | if (dh->code == code) { | ||
253 | uint8_t option[6], len; | ||
254 | |||
255 | option[OPT_CODE] = code; | ||
256 | len = dhcp_option_lengths[dh->flags & OPTION_TYPE_MASK]; | ||
257 | option[OPT_LEN] = len; | ||
258 | if (BB_BIG_ENDIAN) | ||
259 | data <<= 8 * (4 - len); | ||
260 | /* Assignment is unaligned! */ | ||
261 | move_to_unaligned32(&option[OPT_DATA], data); | ||
262 | udhcp_add_binary_option(optionptr, option); | ||
263 | return; | ||
264 | } | ||
265 | } | ||
266 | |||
267 | bb_error_msg("can't add option 0x%02x", code); | ||
268 | } | ||
269 | |||
270 | /* Find option 'code' in opt_list */ | ||
271 | struct option_set* FAST_FUNC find_option(struct option_set *opt_list, uint8_t code) | ||
272 | { | ||
273 | while (opt_list && opt_list->data[OPT_CODE] < code) | ||
274 | opt_list = opt_list->next; | ||
275 | |||
276 | if (opt_list && opt_list->data[OPT_CODE] == code) | ||
277 | return opt_list; | ||
278 | return NULL; | ||
279 | } | ||
280 | |||
281 | /* Parse string to IP in network order */ | ||
282 | int FAST_FUNC udhcp_str2nip(const char *str, void *arg) | ||
283 | { | ||
284 | len_and_sockaddr *lsa; | ||
285 | |||
286 | lsa = host_and_af2sockaddr(str, 0, AF_INET); | ||
287 | if (!lsa) | ||
288 | return 0; | ||
289 | *(uint32_t*)arg = lsa->u.sin.sin_addr.s_addr; | ||
290 | free(lsa); | ||
291 | return 1; | ||
292 | } | ||
293 | |||
294 | /* udhcp_str2optset: | ||
295 | * Parse string option representation to binary form | ||
296 | * and add it to opt_list | ||
297 | */ | ||
298 | /* helper: add an option to the opt_list */ | ||
299 | static NOINLINE void attach_option( | ||
300 | struct option_set **opt_list, | ||
301 | const struct dhcp_option *option, | ||
302 | char *buffer, | ||
303 | int length) | ||
304 | { | ||
305 | struct option_set *existing, *new, **curr; | ||
306 | #if ENABLE_FEATURE_UDHCP_RFC3397 | ||
307 | char *allocated = NULL; | ||
308 | #endif | ||
309 | |||
310 | existing = find_option(*opt_list, option->code); | ||
311 | if (!existing) { | ||
312 | log2("Attaching option %02x to list", option->code); | ||
313 | #if ENABLE_FEATURE_UDHCP_RFC3397 | ||
314 | if ((option->flags & OPTION_TYPE_MASK) == OPTION_STR1035) { | ||
315 | /* reuse buffer and length for RFC1035-formatted string */ | ||
316 | allocated = buffer = (char *)dname_enc(NULL, 0, buffer, &length); | ||
317 | } | ||
318 | #endif | ||
319 | /* make a new option */ | ||
320 | new = xmalloc(sizeof(*new)); | ||
321 | new->data = xmalloc(length + OPT_DATA); | ||
322 | new->data[OPT_CODE] = option->code; | ||
323 | new->data[OPT_LEN] = length; | ||
324 | memcpy(new->data + OPT_DATA, buffer, length); | ||
325 | |||
326 | curr = opt_list; | ||
327 | while (*curr && (*curr)->data[OPT_CODE] < option->code) | ||
328 | curr = &(*curr)->next; | ||
329 | |||
330 | new->next = *curr; | ||
331 | *curr = new; | ||
332 | goto ret; | ||
333 | } | ||
334 | |||
335 | if (option->flags & OPTION_LIST) { | ||
336 | unsigned old_len; | ||
337 | |||
338 | /* add it to an existing option */ | ||
339 | log1("Attaching option %02x to existing member of list", option->code); | ||
340 | old_len = existing->data[OPT_LEN]; | ||
341 | #if ENABLE_FEATURE_UDHCP_RFC3397 | ||
342 | if ((option->flags & OPTION_TYPE_MASK) == OPTION_STR1035) { | ||
343 | /* reuse buffer and length for RFC1035-formatted string */ | ||
344 | allocated = buffer = (char *)dname_enc(existing->data + OPT_DATA, old_len, buffer, &length); | ||
345 | } | ||
346 | #endif | ||
347 | if (old_len + length < 255) { | ||
348 | /* actually 255 is ok too, but adding a space can overlow it */ | ||
349 | |||
350 | existing->data = xrealloc(existing->data, OPT_DATA + 1 + old_len + length); | ||
351 | if ((option->flags & OPTION_TYPE_MASK) == OPTION_STRING) { | ||
352 | /* add space separator between STRING options in a list */ | ||
353 | existing->data[OPT_DATA + old_len] = ' '; | ||
354 | old_len++; | ||
355 | } | ||
356 | memcpy(existing->data + OPT_DATA + old_len, buffer, length); | ||
357 | existing->data[OPT_LEN] = old_len + length; | ||
358 | } /* else, ignore the data, we could put this in a second option in the future */ | ||
359 | } /* else, ignore the new data */ | ||
360 | |||
361 | ret: ; | ||
362 | #if ENABLE_FEATURE_UDHCP_RFC3397 | ||
363 | free(allocated); | ||
364 | #endif | ||
365 | } | ||
366 | |||
367 | int FAST_FUNC udhcp_str2optset(const char *const_str, void *arg) | ||
368 | { | ||
369 | struct option_set **opt_list = arg; | ||
370 | char *opt, *val, *endptr; | ||
371 | char *str; | ||
372 | const struct dhcp_option *option; | ||
373 | int retval, length, idx; | ||
374 | char buffer[8] ALIGNED(4); | ||
375 | uint16_t *result_u16 = (uint16_t *) buffer; | ||
376 | uint32_t *result_u32 = (uint32_t *) buffer; | ||
377 | |||
378 | /* Cheat, the only *const* str possible is "" */ | ||
379 | str = (char *) const_str; | ||
380 | opt = strtok(str, " \t="); | ||
381 | if (!opt) | ||
382 | return 0; | ||
383 | |||
384 | idx = index_in_strings(dhcp_option_strings, opt); /* NB: was strcasecmp! */ | ||
385 | if (idx < 0) | ||
386 | return 0; | ||
387 | option = &dhcp_options[idx]; | ||
388 | |||
389 | retval = 0; | ||
390 | do { | ||
391 | val = strtok(NULL, ", \t"); | ||
392 | if (!val) | ||
393 | break; | ||
394 | length = dhcp_option_lengths[option->flags & OPTION_TYPE_MASK]; | ||
395 | retval = 0; | ||
396 | opt = buffer; /* new meaning for variable opt */ | ||
397 | switch (option->flags & OPTION_TYPE_MASK) { | ||
398 | case OPTION_IP: | ||
399 | retval = udhcp_str2nip(val, buffer); | ||
400 | break; | ||
401 | case OPTION_IP_PAIR: | ||
402 | retval = udhcp_str2nip(val, buffer); | ||
403 | val = strtok(NULL, ", \t/-"); | ||
404 | if (!val) | ||
405 | retval = 0; | ||
406 | if (retval) | ||
407 | retval = udhcp_str2nip(val, buffer + 4); | ||
408 | break; | ||
409 | case OPTION_STRING: | ||
410 | #if ENABLE_FEATURE_UDHCP_RFC3397 | ||
411 | case OPTION_STR1035: | ||
412 | #endif | ||
413 | length = strnlen(val, 254); | ||
414 | if (length > 0) { | ||
415 | opt = val; | ||
416 | retval = 1; | ||
417 | } | ||
418 | break; | ||
419 | // case OPTION_BOOLEAN: { | ||
420 | // static const char noyes[] ALIGN1 = "no\0yes\0"; | ||
421 | // buffer[0] = retval = index_in_strings(noyes, val); | ||
422 | // retval++; /* 0 - bad; 1: "no" 2: "yes" */ | ||
423 | // break; | ||
424 | // } | ||
425 | case OPTION_U8: | ||
426 | buffer[0] = strtoul(val, &endptr, 0); | ||
427 | retval = (endptr[0] == '\0'); | ||
428 | break; | ||
429 | /* htonX are macros in older libc's, using temp var | ||
430 | * in code below for safety */ | ||
431 | /* TODO: use bb_strtoX? */ | ||
432 | case OPTION_U16: { | ||
433 | unsigned long tmp = strtoul(val, &endptr, 0); | ||
434 | *result_u16 = htons(tmp); | ||
435 | retval = (endptr[0] == '\0' /*&& tmp < 0x10000*/); | ||
436 | break; | ||
437 | } | ||
438 | // case OPTION_S16: { | ||
439 | // long tmp = strtol(val, &endptr, 0); | ||
440 | // *result_u16 = htons(tmp); | ||
441 | // retval = (endptr[0] == '\0'); | ||
442 | // break; | ||
443 | // } | ||
444 | case OPTION_U32: { | ||
445 | unsigned long tmp = strtoul(val, &endptr, 0); | ||
446 | *result_u32 = htonl(tmp); | ||
447 | retval = (endptr[0] == '\0'); | ||
448 | break; | ||
449 | } | ||
450 | case OPTION_S32: { | ||
451 | long tmp = strtol(val, &endptr, 0); | ||
452 | *result_u32 = htonl(tmp); | ||
453 | retval = (endptr[0] == '\0'); | ||
454 | break; | ||
455 | } | ||
456 | default: | ||
457 | break; | ||
458 | } | ||
459 | if (retval) | ||
460 | attach_option(opt_list, option, opt, length); | ||
461 | } while (retval && option->flags & OPTION_LIST); | ||
462 | |||
463 | return retval; | ||
464 | } | ||
diff --git a/networking/udhcp/common.h b/networking/udhcp/common.h index 9c3b4960b..cc0cab6e4 100644 --- a/networking/udhcp/common.h +++ b/networking/udhcp/common.h | |||
@@ -74,10 +74,10 @@ enum { | |||
74 | #if ENABLE_FEATURE_UDHCP_RFC3397 | 74 | #if ENABLE_FEATURE_UDHCP_RFC3397 |
75 | OPTION_STR1035, /* RFC1035 compressed domain name list */ | 75 | OPTION_STR1035, /* RFC1035 compressed domain name list */ |
76 | #endif | 76 | #endif |
77 | OPTION_BOOLEAN, | 77 | // OPTION_BOOLEAN, |
78 | OPTION_U8, | 78 | OPTION_U8, |
79 | OPTION_U16, | 79 | OPTION_U16, |
80 | OPTION_S16, | 80 | // OPTION_S16, |
81 | OPTION_U32, | 81 | OPTION_U32, |
82 | OPTION_S32, | 82 | OPTION_S32, |
83 | OPTION_STATIC_ROUTES, | 83 | OPTION_STATIC_ROUTES, |
@@ -172,14 +172,13 @@ extern const uint8_t dhcp_option_lengths[]; | |||
172 | 172 | ||
173 | uint8_t *udhcp_get_option(struct dhcp_packet *packet, int code) FAST_FUNC; | 173 | uint8_t *udhcp_get_option(struct dhcp_packet *packet, int code) FAST_FUNC; |
174 | int udhcp_end_option(uint8_t *optionptr) FAST_FUNC; | 174 | int udhcp_end_option(uint8_t *optionptr) FAST_FUNC; |
175 | void udhcp_add_option_string(uint8_t *optionptr, uint8_t *string) FAST_FUNC; | 175 | void udhcp_add_binary_option(uint8_t *optionptr, uint8_t *addopt) FAST_FUNC; |
176 | void udhcp_add_simple_option(uint8_t *optionptr, uint8_t code, uint32_t data) FAST_FUNC; | 176 | void udhcp_add_simple_option(uint8_t *optionptr, uint8_t code, uint32_t data) FAST_FUNC; |
177 | #if ENABLE_FEATURE_UDHCP_RFC3397 | 177 | #if ENABLE_FEATURE_UDHCP_RFC3397 |
178 | char *dname_dec(const uint8_t *cstr, int clen, const char *pre) FAST_FUNC; | 178 | char *dname_dec(const uint8_t *cstr, int clen, const char *pre) FAST_FUNC; |
179 | uint8_t *dname_enc(const uint8_t *cstr, int clen, const char *src, int *retlen) FAST_FUNC; | 179 | uint8_t *dname_enc(const uint8_t *cstr, int clen, const char *src, int *retlen) FAST_FUNC; |
180 | #endif | 180 | #endif |
181 | /* 2nd param is actually "struct option_set**" */ | 181 | struct option_set *find_option(struct option_set *opt_list, uint8_t code) FAST_FUNC; |
182 | int FAST_FUNC udhcp_str2optset(const char *const_line, void *arg); | ||
183 | 182 | ||
184 | 183 | ||
185 | // RFC 2131 Table 5: Fields and options used by DHCP clients | 184 | // RFC 2131 Table 5: Fields and options used by DHCP clients |
@@ -255,6 +254,11 @@ void udhcp_dump_packet(struct dhcp_packet *packet) FAST_FUNC; | |||
255 | 254 | ||
256 | /*** Other shared functions ***/ | 255 | /*** Other shared functions ***/ |
257 | 256 | ||
257 | /* 2nd param is "uint32_t*" */ | ||
258 | int FAST_FUNC udhcp_str2nip(const char *str, void *arg); | ||
259 | /* 2nd param is "struct option_set**" */ | ||
260 | int FAST_FUNC udhcp_str2optset(const char *str, void *arg); | ||
261 | |||
258 | uint16_t udhcp_checksum(void *addr, int count) FAST_FUNC; | 262 | uint16_t udhcp_checksum(void *addr, int count) FAST_FUNC; |
259 | 263 | ||
260 | void udhcp_init_header(struct dhcp_packet *packet, char type) FAST_FUNC; | 264 | void udhcp_init_header(struct dhcp_packet *packet, char type) FAST_FUNC; |
diff --git a/networking/udhcp/dhcpc.c b/networking/udhcp/dhcpc.c index 4565d7fd2..2c7608048 100644 --- a/networking/udhcp/dhcpc.c +++ b/networking/udhcp/dhcpc.c | |||
@@ -49,10 +49,10 @@ static const uint8_t len_of_option_as_string[] = { | |||
49 | #if ENABLE_FEATURE_UDHCP_RFC3397 | 49 | #if ENABLE_FEATURE_UDHCP_RFC3397 |
50 | [OPTION_STR1035] = 1, | 50 | [OPTION_STR1035] = 1, |
51 | #endif | 51 | #endif |
52 | [OPTION_BOOLEAN] = sizeof("yes "), | 52 | // [OPTION_BOOLEAN] = sizeof("yes "), |
53 | [OPTION_U8] = sizeof("255 "), | 53 | [OPTION_U8] = sizeof("255 "), |
54 | [OPTION_U16] = sizeof("65535 "), | 54 | [OPTION_U16] = sizeof("65535 "), |
55 | [OPTION_S16] = sizeof("-32768 "), | 55 | // [OPTION_S16] = sizeof("-32768 "), |
56 | [OPTION_U32] = sizeof("4294967295 "), | 56 | [OPTION_U32] = sizeof("4294967295 "), |
57 | [OPTION_S32] = sizeof("-2147483684 "), | 57 | [OPTION_S32] = sizeof("-2147483684 "), |
58 | }; | 58 | }; |
@@ -81,7 +81,6 @@ static NOINLINE char *xmalloc_optname_optval(uint8_t *option, const struct dhcp_ | |||
81 | unsigned upper_length; | 81 | unsigned upper_length; |
82 | int len, type, optlen; | 82 | int len, type, optlen; |
83 | uint16_t val_u16; | 83 | uint16_t val_u16; |
84 | int16_t val_s16; | ||
85 | uint32_t val_u32; | 84 | uint32_t val_u32; |
86 | int32_t val_s32; | 85 | int32_t val_s32; |
87 | char *dest, *ret; | 86 | char *dest, *ret; |
@@ -108,9 +107,9 @@ static NOINLINE char *xmalloc_optname_optval(uint8_t *option, const struct dhcp_ | |||
108 | // Should we bail out/warn if we see multi-ip option which is | 107 | // Should we bail out/warn if we see multi-ip option which is |
109 | // not allowed to be such? For example, DHCP_BROADCAST... | 108 | // not allowed to be such? For example, DHCP_BROADCAST... |
110 | break; | 109 | break; |
111 | case OPTION_BOOLEAN: | 110 | // case OPTION_BOOLEAN: |
112 | dest += sprintf(dest, *option ? "yes" : "no"); | 111 | // dest += sprintf(dest, *option ? "yes" : "no"); |
113 | break; | 112 | // break; |
114 | case OPTION_U8: | 113 | case OPTION_U8: |
115 | dest += sprintf(dest, "%u", *option); | 114 | dest += sprintf(dest, "%u", *option); |
116 | break; | 115 | break; |
@@ -118,10 +117,12 @@ static NOINLINE char *xmalloc_optname_optval(uint8_t *option, const struct dhcp_ | |||
118 | move_from_unaligned16(val_u16, option); | 117 | move_from_unaligned16(val_u16, option); |
119 | dest += sprintf(dest, "%u", ntohs(val_u16)); | 118 | dest += sprintf(dest, "%u", ntohs(val_u16)); |
120 | break; | 119 | break; |
121 | case OPTION_S16: | 120 | // case OPTION_S16: { |
122 | move_from_unaligned16(val_s16, option); | 121 | // int16_t val_s16; |
123 | dest += sprintf(dest, "%d", ntohs(val_s16)); | 122 | // move_from_unaligned16(val_s16, option); |
124 | break; | 123 | // dest += sprintf(dest, "%d", ntohs(val_s16)); |
124 | // break; | ||
125 | // } | ||
125 | case OPTION_U32: | 126 | case OPTION_U32: |
126 | move_from_unaligned32(val_u32, option); | 127 | move_from_unaligned32(val_u32, option); |
127 | dest += sprintf(dest, "%lu", (unsigned long) ntohl(val_u32)); | 128 | dest += sprintf(dest, "%lu", (unsigned long) ntohl(val_u32)); |
@@ -318,23 +319,23 @@ static void init_packet(struct dhcp_packet *packet, char type) | |||
318 | udhcp_init_header(packet, type); | 319 | udhcp_init_header(packet, type); |
319 | memcpy(packet->chaddr, client_config.client_mac, 6); | 320 | memcpy(packet->chaddr, client_config.client_mac, 6); |
320 | if (client_config.clientid) | 321 | if (client_config.clientid) |
321 | udhcp_add_option_string(packet->options, client_config.clientid); | 322 | udhcp_add_binary_option(packet->options, client_config.clientid); |
322 | if (client_config.hostname) | 323 | if (client_config.hostname) |
323 | udhcp_add_option_string(packet->options, client_config.hostname); | 324 | udhcp_add_binary_option(packet->options, client_config.hostname); |
324 | if (client_config.fqdn) | 325 | if (client_config.fqdn) |
325 | udhcp_add_option_string(packet->options, client_config.fqdn); | 326 | udhcp_add_binary_option(packet->options, client_config.fqdn); |
326 | if (type != DHCPDECLINE | 327 | if (type != DHCPDECLINE |
327 | && type != DHCPRELEASE | 328 | && type != DHCPRELEASE |
328 | && client_config.vendorclass | 329 | && client_config.vendorclass |
329 | ) { | 330 | ) { |
330 | udhcp_add_option_string(packet->options, client_config.vendorclass); | 331 | udhcp_add_binary_option(packet->options, client_config.vendorclass); |
331 | } | 332 | } |
332 | } | 333 | } |
333 | 334 | ||
334 | static void add_client_options(struct dhcp_packet *packet) | 335 | static void add_client_options(struct dhcp_packet *packet) |
335 | { | 336 | { |
336 | /* Add am "param req" option with the list of options we'd like to have | 337 | /* Add am "param req" option with the list of options we'd like to have |
337 | * from stubborn DHCP servers. Pull the data from the struct in options.c. | 338 | * from stubborn DHCP servers. Pull the data from the struct in common.c. |
338 | * No bounds checking because it goes towards the head of the packet. */ | 339 | * No bounds checking because it goes towards the head of the packet. */ |
339 | uint8_t c; | 340 | uint8_t c; |
340 | int end = udhcp_end_option(packet->options); | 341 | int end = udhcp_end_option(packet->options); |
@@ -360,7 +361,7 @@ static void add_client_options(struct dhcp_packet *packet) | |||
360 | { | 361 | { |
361 | struct option_set *curr = client_config.options; | 362 | struct option_set *curr = client_config.options; |
362 | while (curr) { | 363 | while (curr) { |
363 | udhcp_add_option_string(packet->options, curr->data); | 364 | udhcp_add_binary_option(packet->options, curr->data); |
364 | curr = curr->next; | 365 | curr = curr->next; |
365 | } | 366 | } |
366 | // if (client_config.sname) | 367 | // if (client_config.sname) |
diff --git a/networking/udhcp/dhcpd.c b/networking/udhcp/dhcpd.c index 795ac4841..32f351f52 100644 --- a/networking/udhcp/dhcpd.c +++ b/networking/udhcp/dhcpd.c | |||
@@ -105,7 +105,7 @@ static void add_server_options(struct dhcp_packet *packet) | |||
105 | 105 | ||
106 | while (curr) { | 106 | while (curr) { |
107 | if (curr->data[OPT_CODE] != DHCP_LEASE_TIME) | 107 | if (curr->data[OPT_CODE] != DHCP_LEASE_TIME) |
108 | udhcp_add_option_string(packet->options, curr->data); | 108 | udhcp_add_binary_option(packet->options, curr->data); |
109 | curr = curr->next; | 109 | curr = curr->next; |
110 | } | 110 | } |
111 | 111 | ||
diff --git a/networking/udhcp/dhcpd.h b/networking/udhcp/dhcpd.h index a4e9a58ff..f6187679d 100644 --- a/networking/udhcp/dhcpd.h +++ b/networking/udhcp/dhcpd.h | |||
@@ -123,7 +123,6 @@ void log_static_leases(struct static_lease **st_lease_pp) FAST_FUNC; | |||
123 | void read_config(const char *file) FAST_FUNC; | 123 | void read_config(const char *file) FAST_FUNC; |
124 | void write_leases(void) FAST_FUNC; | 124 | void write_leases(void) FAST_FUNC; |
125 | void read_leases(const char *file) FAST_FUNC; | 125 | void read_leases(const char *file) FAST_FUNC; |
126 | struct option_set *find_option(struct option_set *opt_list, uint8_t code) FAST_FUNC; | ||
127 | 126 | ||
128 | 127 | ||
129 | POP_SAVED_FUNCTION_VISIBILITY | 128 | POP_SAVED_FUNCTION_VISIBILITY |
diff --git a/networking/udhcp/files.c b/networking/udhcp/files.c index fddda4cba..1f25bb105 100644 --- a/networking/udhcp/files.c +++ b/networking/udhcp/files.c | |||
@@ -22,18 +22,6 @@ static inline uint64_t hton64(uint64_t v) | |||
22 | #define ntoh64(v) hton64(v) | 22 | #define ntoh64(v) hton64(v) |
23 | 23 | ||
24 | /* on these functions, make sure your datatype matches */ | 24 | /* on these functions, make sure your datatype matches */ |
25 | static int FAST_FUNC read_nip(const char *line, void *arg) | ||
26 | { | ||
27 | len_and_sockaddr *lsa; | ||
28 | |||
29 | lsa = host_and_af2sockaddr(line, 0, AF_INET); | ||
30 | if (!lsa) | ||
31 | return 0; | ||
32 | *(uint32_t*)arg = lsa->u.sin.sin_addr.s_addr; | ||
33 | free(lsa); | ||
34 | return 1; | ||
35 | } | ||
36 | |||
37 | static int FAST_FUNC read_str(const char *line, void *arg) | 25 | static int FAST_FUNC read_str(const char *line, void *arg) |
38 | { | 26 | { |
39 | char **dest = arg; | 27 | char **dest = arg; |
@@ -49,198 +37,6 @@ static int FAST_FUNC read_u32(const char *line, void *arg) | |||
49 | return errno == 0; | 37 | return errno == 0; |
50 | } | 38 | } |
51 | 39 | ||
52 | static int read_yn(const char *line, void *arg) | ||
53 | { | ||
54 | char *dest = arg; | ||
55 | |||
56 | if (strcasecmp("yes", line) == 0) { | ||
57 | *dest = 1; | ||
58 | return 1; | ||
59 | } | ||
60 | if (strcasecmp("no", line) == 0) { | ||
61 | *dest = 0; | ||
62 | return 1; | ||
63 | } | ||
64 | return 0; | ||
65 | } | ||
66 | |||
67 | /* find option 'code' in opt_list */ | ||
68 | struct option_set* FAST_FUNC find_option(struct option_set *opt_list, uint8_t code) | ||
69 | { | ||
70 | while (opt_list && opt_list->data[OPT_CODE] < code) | ||
71 | opt_list = opt_list->next; | ||
72 | |||
73 | if (opt_list && opt_list->data[OPT_CODE] == code) | ||
74 | return opt_list; | ||
75 | return NULL; | ||
76 | } | ||
77 | |||
78 | /* add an option to the opt_list */ | ||
79 | static NOINLINE void attach_option( | ||
80 | struct option_set **opt_list, | ||
81 | const struct dhcp_option *option, | ||
82 | char *buffer, | ||
83 | int length) | ||
84 | { | ||
85 | struct option_set *existing, *new, **curr; | ||
86 | #if ENABLE_FEATURE_UDHCP_RFC3397 | ||
87 | char *allocated = NULL; | ||
88 | #endif | ||
89 | |||
90 | existing = find_option(*opt_list, option->code); | ||
91 | if (!existing) { | ||
92 | log2("Attaching option %02x to list", option->code); | ||
93 | #if ENABLE_FEATURE_UDHCP_RFC3397 | ||
94 | if ((option->flags & OPTION_TYPE_MASK) == OPTION_STR1035) { | ||
95 | /* reuse buffer and length for RFC1035-formatted string */ | ||
96 | allocated = buffer = (char *)dname_enc(NULL, 0, buffer, &length); | ||
97 | } | ||
98 | #endif | ||
99 | /* make a new option */ | ||
100 | new = xmalloc(sizeof(*new)); | ||
101 | new->data = xmalloc(length + OPT_DATA); | ||
102 | new->data[OPT_CODE] = option->code; | ||
103 | new->data[OPT_LEN] = length; | ||
104 | memcpy(new->data + OPT_DATA, buffer, length); | ||
105 | |||
106 | curr = opt_list; | ||
107 | while (*curr && (*curr)->data[OPT_CODE] < option->code) | ||
108 | curr = &(*curr)->next; | ||
109 | |||
110 | new->next = *curr; | ||
111 | *curr = new; | ||
112 | goto ret; | ||
113 | } | ||
114 | |||
115 | if (option->flags & OPTION_LIST) { | ||
116 | unsigned old_len; | ||
117 | |||
118 | /* add it to an existing option */ | ||
119 | log1("Attaching option %02x to existing member of list", option->code); | ||
120 | old_len = existing->data[OPT_LEN]; | ||
121 | #if ENABLE_FEATURE_UDHCP_RFC3397 | ||
122 | if ((option->flags & OPTION_TYPE_MASK) == OPTION_STR1035) { | ||
123 | /* reuse buffer and length for RFC1035-formatted string */ | ||
124 | allocated = buffer = (char *)dname_enc(existing->data + OPT_DATA, old_len, buffer, &length); | ||
125 | } | ||
126 | #endif | ||
127 | if (old_len + length < 255) { | ||
128 | /* actually 255 is ok too, but adding a space can overlow it */ | ||
129 | |||
130 | existing->data = xrealloc(existing->data, OPT_DATA + 1 + old_len + length); | ||
131 | if ((option->flags & OPTION_TYPE_MASK) == OPTION_STRING) { | ||
132 | /* add space separator between STRING options in a list */ | ||
133 | existing->data[OPT_DATA + old_len] = ' '; | ||
134 | old_len++; | ||
135 | } | ||
136 | memcpy(existing->data + OPT_DATA + old_len, buffer, length); | ||
137 | existing->data[OPT_LEN] = old_len + length; | ||
138 | } /* else, ignore the data, we could put this in a second option in the future */ | ||
139 | } /* else, ignore the new data */ | ||
140 | |||
141 | ret: ; | ||
142 | #if ENABLE_FEATURE_UDHCP_RFC3397 | ||
143 | free(allocated); | ||
144 | #endif | ||
145 | } | ||
146 | |||
147 | /* read a dhcp option and add it to opt_list */ | ||
148 | int FAST_FUNC udhcp_str2optset(const char *const_line, void *arg) | ||
149 | { | ||
150 | struct option_set **opt_list = arg; | ||
151 | char *opt, *val, *endptr; | ||
152 | char *line; | ||
153 | const struct dhcp_option *option; | ||
154 | int retval, length, idx; | ||
155 | char buffer[8] ALIGNED(4); | ||
156 | uint16_t *result_u16 = (uint16_t *) buffer; | ||
157 | uint32_t *result_u32 = (uint32_t *) buffer; | ||
158 | |||
159 | /* Cheat, the only *const* line possible is "" */ | ||
160 | line = (char *) const_line; | ||
161 | opt = strtok(line, " \t="); | ||
162 | if (!opt) | ||
163 | return 0; | ||
164 | |||
165 | idx = index_in_strings(dhcp_option_strings, opt); /* NB: was strcasecmp! */ | ||
166 | if (idx < 0) | ||
167 | return 0; | ||
168 | option = &dhcp_options[idx]; | ||
169 | |||
170 | retval = 0; | ||
171 | do { | ||
172 | val = strtok(NULL, ", \t"); | ||
173 | if (!val) | ||
174 | break; | ||
175 | length = dhcp_option_lengths[option->flags & OPTION_TYPE_MASK]; | ||
176 | retval = 0; | ||
177 | opt = buffer; /* new meaning for variable opt */ | ||
178 | switch (option->flags & OPTION_TYPE_MASK) { | ||
179 | case OPTION_IP: | ||
180 | retval = read_nip(val, buffer); | ||
181 | break; | ||
182 | case OPTION_IP_PAIR: | ||
183 | retval = read_nip(val, buffer); | ||
184 | val = strtok(NULL, ", \t/-"); | ||
185 | if (!val) | ||
186 | retval = 0; | ||
187 | if (retval) | ||
188 | retval = read_nip(val, buffer + 4); | ||
189 | break; | ||
190 | case OPTION_STRING: | ||
191 | #if ENABLE_FEATURE_UDHCP_RFC3397 | ||
192 | case OPTION_STR1035: | ||
193 | #endif | ||
194 | length = strnlen(val, 254); | ||
195 | if (length > 0) { | ||
196 | opt = val; | ||
197 | retval = 1; | ||
198 | } | ||
199 | break; | ||
200 | case OPTION_BOOLEAN: | ||
201 | retval = read_yn(val, buffer); | ||
202 | break; | ||
203 | case OPTION_U8: | ||
204 | buffer[0] = strtoul(val, &endptr, 0); | ||
205 | retval = (endptr[0] == '\0'); | ||
206 | break; | ||
207 | /* htonX are macros in older libc's, using temp var | ||
208 | * in code below for safety */ | ||
209 | /* TODO: use bb_strtoX? */ | ||
210 | case OPTION_U16: { | ||
211 | unsigned long tmp = strtoul(val, &endptr, 0); | ||
212 | *result_u16 = htons(tmp); | ||
213 | retval = (endptr[0] == '\0' /*&& tmp < 0x10000*/); | ||
214 | break; | ||
215 | } | ||
216 | case OPTION_S16: { | ||
217 | long tmp = strtol(val, &endptr, 0); | ||
218 | *result_u16 = htons(tmp); | ||
219 | retval = (endptr[0] == '\0'); | ||
220 | break; | ||
221 | } | ||
222 | case OPTION_U32: { | ||
223 | unsigned long tmp = strtoul(val, &endptr, 0); | ||
224 | *result_u32 = htonl(tmp); | ||
225 | retval = (endptr[0] == '\0'); | ||
226 | break; | ||
227 | } | ||
228 | case OPTION_S32: { | ||
229 | long tmp = strtol(val, &endptr, 0); | ||
230 | *result_u32 = htonl(tmp); | ||
231 | retval = (endptr[0] == '\0'); | ||
232 | break; | ||
233 | } | ||
234 | default: | ||
235 | break; | ||
236 | } | ||
237 | if (retval) | ||
238 | attach_option(opt_list, option, opt, length); | ||
239 | } while (retval && option->flags & OPTION_LIST); | ||
240 | |||
241 | return retval; | ||
242 | } | ||
243 | |||
244 | static int FAST_FUNC read_staticlease(const char *const_line, void *arg) | 40 | static int FAST_FUNC read_staticlease(const char *const_line, void *arg) |
245 | { | 41 | { |
246 | char *line; | 42 | char *line; |
@@ -257,7 +53,7 @@ static int FAST_FUNC read_staticlease(const char *const_line, void *arg) | |||
257 | 53 | ||
258 | /* Read ip */ | 54 | /* Read ip */ |
259 | ip_string = strtok_r(NULL, " \t", &line); | 55 | ip_string = strtok_r(NULL, " \t", &line); |
260 | if (!ip_string || !read_nip(ip_string, &nip)) | 56 | if (!ip_string || !udhcp_str2nip(ip_string, &nip)) |
261 | return 0; | 57 | return 0; |
262 | 58 | ||
263 | add_static_lease(arg, (uint8_t*) &mac_bytes, nip); | 59 | add_static_lease(arg, (uint8_t*) &mac_bytes, nip); |
@@ -277,8 +73,8 @@ struct config_keyword { | |||
277 | 73 | ||
278 | static const struct config_keyword keywords[] = { | 74 | static const struct config_keyword keywords[] = { |
279 | /* keyword handler variable address default */ | 75 | /* keyword handler variable address default */ |
280 | {"start", read_nip, &(server_config.start_ip), "192.168.0.20"}, | 76 | {"start", udhcp_str2nip, &(server_config.start_ip), "192.168.0.20"}, |
281 | {"end", read_nip, &(server_config.end_ip), "192.168.0.254"}, | 77 | {"end", udhcp_str2nip, &(server_config.end_ip), "192.168.0.254"}, |
282 | {"interface", read_str, &(server_config.interface), "eth0"}, | 78 | {"interface", read_str, &(server_config.interface), "eth0"}, |
283 | /* Avoid "max_leases value not sane" warning by setting default | 79 | /* Avoid "max_leases value not sane" warning by setting default |
284 | * to default_end_ip - default_start_ip + 1: */ | 80 | * to default_end_ip - default_start_ip + 1: */ |
@@ -290,7 +86,7 @@ static const struct config_keyword keywords[] = { | |||
290 | {"min_lease", read_u32, &(server_config.min_lease_sec),"60"}, | 86 | {"min_lease", read_u32, &(server_config.min_lease_sec),"60"}, |
291 | {"lease_file", read_str, &(server_config.lease_file), LEASES_FILE}, | 87 | {"lease_file", read_str, &(server_config.lease_file), LEASES_FILE}, |
292 | {"pidfile", read_str, &(server_config.pidfile), "/var/run/udhcpd.pid"}, | 88 | {"pidfile", read_str, &(server_config.pidfile), "/var/run/udhcpd.pid"}, |
293 | {"siaddr", read_nip, &(server_config.siaddr_nip), "0.0.0.0"}, | 89 | {"siaddr", udhcp_str2nip, &(server_config.siaddr_nip), "0.0.0.0"}, |
294 | /* keywords with no defaults must be last! */ | 90 | /* keywords with no defaults must be last! */ |
295 | {"option", udhcp_str2optset, &(server_config.options), ""}, | 91 | {"option", udhcp_str2optset, &(server_config.options), ""}, |
296 | {"opt", udhcp_str2optset, &(server_config.options), ""}, | 92 | {"opt", udhcp_str2optset, &(server_config.options), ""}, |
diff --git a/networking/udhcp/options.c b/networking/udhcp/options.c deleted file mode 100644 index af3c217e8..000000000 --- a/networking/udhcp/options.c +++ /dev/null | |||
@@ -1,262 +0,0 @@ | |||
1 | /* vi: set sw=4 ts=4: */ | ||
2 | /* | ||
3 | * options.c -- DHCP server option packet tools | ||
4 | * Rewrite by Russ Dill <Russ.Dill@asu.edu> July 2001 | ||
5 | * | ||
6 | * Licensed under GPLv2, see file LICENSE in this tarball for details. | ||
7 | */ | ||
8 | |||
9 | #include "common.h" | ||
10 | |||
11 | |||
12 | /* Supported options are easily added here. | ||
13 | * See RFC2132 for more options. | ||
14 | * OPTION_REQ: these options are requested by udhcpc (unless -o). | ||
15 | */ | ||
16 | const struct dhcp_option dhcp_options[] = { | ||
17 | /* flags code */ | ||
18 | { OPTION_IP | OPTION_REQ, 0x01 }, /* DHCP_SUBNET */ | ||
19 | { OPTION_S32 , 0x02 }, /* DHCP_TIME_OFFSET */ | ||
20 | { OPTION_IP | OPTION_LIST | OPTION_REQ, 0x03 }, /* DHCP_ROUTER */ | ||
21 | // { OPTION_IP | OPTION_LIST , 0x04 }, /* DHCP_TIME_SERVER */ | ||
22 | // { OPTION_IP | OPTION_LIST , 0x05 }, /* DHCP_NAME_SERVER */ | ||
23 | { OPTION_IP | OPTION_LIST | OPTION_REQ, 0x06 }, /* DHCP_DNS_SERVER */ | ||
24 | // { OPTION_IP | OPTION_LIST , 0x07 }, /* DHCP_LOG_SERVER */ | ||
25 | // { OPTION_IP | OPTION_LIST , 0x08 }, /* DHCP_COOKIE_SERVER */ | ||
26 | { OPTION_IP | OPTION_LIST , 0x09 }, /* DHCP_LPR_SERVER */ | ||
27 | { OPTION_STRING | OPTION_REQ, 0x0c }, /* DHCP_HOST_NAME */ | ||
28 | { OPTION_U16 , 0x0d }, /* DHCP_BOOT_SIZE */ | ||
29 | { OPTION_STRING | OPTION_REQ, 0x0f }, /* DHCP_DOMAIN_NAME */ | ||
30 | { OPTION_IP , 0x10 }, /* DHCP_SWAP_SERVER */ | ||
31 | { OPTION_STRING , 0x11 }, /* DHCP_ROOT_PATH */ | ||
32 | { OPTION_U8 , 0x17 }, /* DHCP_IP_TTL */ | ||
33 | { OPTION_U16 , 0x1a }, /* DHCP_MTU */ | ||
34 | { OPTION_IP | OPTION_REQ, 0x1c }, /* DHCP_BROADCAST */ | ||
35 | { OPTION_STRING , 0x28 }, /* DHCP_NIS_DOMAIN */ | ||
36 | { OPTION_IP | OPTION_LIST , 0x29 }, /* DHCP_NIS_SERVER */ | ||
37 | { OPTION_IP | OPTION_LIST | OPTION_REQ, 0x2a }, /* DHCP_NTP_SERVER */ | ||
38 | { OPTION_IP | OPTION_LIST , 0x2c }, /* DHCP_WINS_SERVER */ | ||
39 | { OPTION_U32 , 0x33 }, /* DHCP_LEASE_TIME */ | ||
40 | { OPTION_IP , 0x36 }, /* DHCP_SERVER_ID */ | ||
41 | { OPTION_STRING , 0x38 }, /* DHCP_ERR_MESSAGE */ | ||
42 | //TODO: must be combined with 'sname' and 'file' handling: | ||
43 | { OPTION_STRING , 0x42 }, /* DHCP_TFTP_SERVER_NAME */ | ||
44 | { OPTION_STRING , 0x43 }, /* DHCP_BOOT_FILE */ | ||
45 | //TODO: not a string, but a set of LASCII strings: | ||
46 | // { OPTION_STRING , 0x4D }, /* DHCP_USER_CLASS */ | ||
47 | #if ENABLE_FEATURE_UDHCP_RFC3397 | ||
48 | { OPTION_STR1035 | OPTION_LIST , 0x77 }, /* DHCP_DOMAIN_SEARCH */ | ||
49 | #endif | ||
50 | { OPTION_STATIC_ROUTES , 0x79 }, /* DHCP_STATIC_ROUTES */ | ||
51 | { OPTION_STRING , 0xfc }, /* DHCP_WPAD */ | ||
52 | |||
53 | /* Options below have no match in dhcp_option_strings[], | ||
54 | * are not passed to dhcpc scripts, and cannot be specified | ||
55 | * with "option XXX YYY" syntax in dhcpd config file. | ||
56 | * These entries are only used internally by udhcp[cd] | ||
57 | * to correctly encode options into packets. | ||
58 | */ | ||
59 | |||
60 | { OPTION_IP , 0x32 }, /* DHCP_REQUESTED_IP */ | ||
61 | { OPTION_U8 , 0x35 }, /* DHCP_MESSAGE_TYPE */ | ||
62 | { OPTION_U16 , 0x39 }, /* DHCP_MAX_SIZE */ | ||
63 | { OPTION_STRING , 0x3c }, /* DHCP_VENDOR */ | ||
64 | //FIXME: handling of this option is not exactly correct: | ||
65 | { OPTION_STRING , 0x3d }, /* DHCP_CLIENT_ID */ | ||
66 | { 0, 0 } /* zeroed terminating entry */ | ||
67 | }; | ||
68 | |||
69 | /* Used for converting options from incoming packets to env variables | ||
70 | * for udhcpc stript, and for setting options for udhcpd via | ||
71 | * "opt OPTION_NAME OPTION_VALUE" directives in udhcpd.conf file. | ||
72 | */ | ||
73 | /* Must match dhcp_options[] order */ | ||
74 | const char dhcp_option_strings[] ALIGN1 = | ||
75 | "subnet" "\0" /* DHCP_SUBNET */ | ||
76 | "timezone" "\0" /* DHCP_TIME_OFFSET */ | ||
77 | "router" "\0" /* DHCP_ROUTER */ | ||
78 | // "timesrv" "\0" /* DHCP_TIME_SERVER */ | ||
79 | // "namesrv" "\0" /* DHCP_NAME_SERVER */ | ||
80 | "dns" "\0" /* DHCP_DNS_SERVER */ | ||
81 | // "logsrv" "\0" /* DHCP_LOG_SERVER */ | ||
82 | // "cookiesrv" "\0" /* DHCP_COOKIE_SERVER */ | ||
83 | "lprsrv" "\0" /* DHCP_LPR_SERVER */ | ||
84 | "hostname" "\0" /* DHCP_HOST_NAME */ | ||
85 | "bootsize" "\0" /* DHCP_BOOT_SIZE */ | ||
86 | "domain" "\0" /* DHCP_DOMAIN_NAME */ | ||
87 | "swapsrv" "\0" /* DHCP_SWAP_SERVER */ | ||
88 | "rootpath" "\0" /* DHCP_ROOT_PATH */ | ||
89 | "ipttl" "\0" /* DHCP_IP_TTL */ | ||
90 | "mtu" "\0" /* DHCP_MTU */ | ||
91 | "broadcast" "\0" /* DHCP_BROADCAST */ | ||
92 | "nisdomain" "\0" /* DHCP_NIS_DOMAIN */ | ||
93 | "nissrv" "\0" /* DHCP_NIS_SERVER */ | ||
94 | "ntpsrv" "\0" /* DHCP_NTP_SERVER */ | ||
95 | "wins" "\0" /* DHCP_WINS_SERVER */ | ||
96 | "lease" "\0" /* DHCP_LEASE_TIME */ | ||
97 | "serverid" "\0" /* DHCP_SERVER_ID */ | ||
98 | "message" "\0" /* DHCP_ERR_MESSAGE */ | ||
99 | "tftp" "\0" /* DHCP_TFTP_SERVER_NAME */ | ||
100 | "bootfile" "\0" /* DHCP_BOOT_FILE */ | ||
101 | // "userclass" "\0" /* DHCP_USER_CLASS */ | ||
102 | #if ENABLE_FEATURE_UDHCP_RFC3397 | ||
103 | "search" "\0" /* DHCP_DOMAIN_SEARCH */ | ||
104 | #endif | ||
105 | // "staticroutes" is only used to set udhcpc environment, it doesn't work | ||
106 | // in udhcpd.conf since OPTION_STATIC_ROUTES is not handled yet | ||
107 | // by "string->option" conversion code: | ||
108 | "staticroutes" "\0"/* DHCP_STATIC_ROUTES */ | ||
109 | "wpad" "\0" /* DHCP_WPAD */ | ||
110 | ; | ||
111 | |||
112 | /* Lengths of the different option types */ | ||
113 | const uint8_t dhcp_option_lengths[] ALIGN1 = { | ||
114 | [OPTION_IP] = 4, | ||
115 | [OPTION_IP_PAIR] = 8, | ||
116 | [OPTION_BOOLEAN] = 1, | ||
117 | [OPTION_STRING] = 1, | ||
118 | #if ENABLE_FEATURE_UDHCP_RFC3397 | ||
119 | [OPTION_STR1035] = 1, | ||
120 | #endif | ||
121 | [OPTION_U8] = 1, | ||
122 | [OPTION_U16] = 2, | ||
123 | [OPTION_S16] = 2, | ||
124 | [OPTION_U32] = 4, | ||
125 | [OPTION_S32] = 4, | ||
126 | /* Just like OPTION_STRING, we use minimum length here */ | ||
127 | [OPTION_STATIC_ROUTES] = 5, | ||
128 | }; | ||
129 | |||
130 | |||
131 | #if defined CONFIG_UDHCP_DEBUG && CONFIG_UDHCP_DEBUG >= 2 | ||
132 | static void log_option(const char *pfx, const uint8_t *opt) | ||
133 | { | ||
134 | if (dhcp_verbose >= 2) { | ||
135 | char buf[256 * 2 + 2]; | ||
136 | *bin2hex(buf, (void*) (opt + OPT_DATA), opt[OPT_LEN]) = '\0'; | ||
137 | bb_info_msg("%s: 0x%02x %s", pfx, opt[OPT_CODE], buf); | ||
138 | } | ||
139 | } | ||
140 | #else | ||
141 | # define log_option(pfx, opt) ((void)0) | ||
142 | #endif | ||
143 | |||
144 | /* get an option with bounds checking (warning, result is not aligned). */ | ||
145 | uint8_t* FAST_FUNC udhcp_get_option(struct dhcp_packet *packet, int code) | ||
146 | { | ||
147 | uint8_t *optionptr; | ||
148 | int len; | ||
149 | int rem; | ||
150 | int overload = 0; | ||
151 | enum { | ||
152 | FILE_FIELD101 = FILE_FIELD * 0x101, | ||
153 | SNAME_FIELD101 = SNAME_FIELD * 0x101, | ||
154 | }; | ||
155 | |||
156 | /* option bytes: [code][len][data1][data2]..[dataLEN] */ | ||
157 | optionptr = packet->options; | ||
158 | rem = sizeof(packet->options); | ||
159 | while (1) { | ||
160 | if (rem <= 0) { | ||
161 | bb_error_msg("bad packet, malformed option field"); | ||
162 | return NULL; | ||
163 | } | ||
164 | if (optionptr[OPT_CODE] == DHCP_PADDING) { | ||
165 | rem--; | ||
166 | optionptr++; | ||
167 | continue; | ||
168 | } | ||
169 | if (optionptr[OPT_CODE] == DHCP_END) { | ||
170 | if ((overload & FILE_FIELD101) == FILE_FIELD) { | ||
171 | /* can use packet->file, and didn't look at it yet */ | ||
172 | overload |= FILE_FIELD101; /* "we looked at it" */ | ||
173 | optionptr = packet->file; | ||
174 | rem = sizeof(packet->file); | ||
175 | continue; | ||
176 | } | ||
177 | if ((overload & SNAME_FIELD101) == SNAME_FIELD) { | ||
178 | /* can use packet->sname, and didn't look at it yet */ | ||
179 | overload |= SNAME_FIELD101; /* "we looked at it" */ | ||
180 | optionptr = packet->sname; | ||
181 | rem = sizeof(packet->sname); | ||
182 | continue; | ||
183 | } | ||
184 | break; | ||
185 | } | ||
186 | len = 2 + optionptr[OPT_LEN]; | ||
187 | rem -= len; | ||
188 | if (rem < 0) | ||
189 | continue; /* complain and return NULL */ | ||
190 | |||
191 | if (optionptr[OPT_CODE] == code) { | ||
192 | log_option("Option found", optionptr); | ||
193 | return optionptr + OPT_DATA; | ||
194 | } | ||
195 | |||
196 | if (optionptr[OPT_CODE] == DHCP_OPTION_OVERLOAD) { | ||
197 | overload |= optionptr[OPT_DATA]; | ||
198 | /* fall through */ | ||
199 | } | ||
200 | optionptr += len; | ||
201 | } | ||
202 | |||
203 | /* log3 because udhcpc uses it a lot - very noisy */ | ||
204 | log3("Option 0x%02x not found", code); | ||
205 | return NULL; | ||
206 | } | ||
207 | |||
208 | /* return the position of the 'end' option (no bounds checking) */ | ||
209 | int FAST_FUNC udhcp_end_option(uint8_t *optionptr) | ||
210 | { | ||
211 | int i = 0; | ||
212 | |||
213 | while (optionptr[i] != DHCP_END) { | ||
214 | if (optionptr[i] != DHCP_PADDING) | ||
215 | i += optionptr[i + OPT_LEN] + OPT_DATA-1; | ||
216 | i++; | ||
217 | } | ||
218 | return i; | ||
219 | } | ||
220 | |||
221 | /* add an option string to the options */ | ||
222 | /* option bytes: [code][len][data1][data2]..[dataLEN] */ | ||
223 | void FAST_FUNC udhcp_add_option_string(uint8_t *optionptr, uint8_t *string) | ||
224 | { | ||
225 | unsigned len; | ||
226 | unsigned end = udhcp_end_option(optionptr); | ||
227 | |||
228 | /* end position + string length + option code/length + end option */ | ||
229 | if (end + string[OPT_LEN] + 2 + 1 >= DHCP_OPTIONS_BUFSIZE) { | ||
230 | bb_error_msg("option 0x%02x did not fit into the packet", | ||
231 | string[OPT_CODE]); | ||
232 | return; | ||
233 | } | ||
234 | log_option("Adding option", string); | ||
235 | len = OPT_DATA + string[OPT_LEN]; | ||
236 | memcpy(optionptr + end, string, len); | ||
237 | optionptr[end + len] = DHCP_END; | ||
238 | } | ||
239 | |||
240 | /* add a one to four byte option to a packet */ | ||
241 | void FAST_FUNC udhcp_add_simple_option(uint8_t *optionptr, uint8_t code, uint32_t data) | ||
242 | { | ||
243 | const struct dhcp_option *dh; | ||
244 | |||
245 | for (dh = dhcp_options; dh->code; dh++) { | ||
246 | if (dh->code == code) { | ||
247 | uint8_t option[6], len; | ||
248 | |||
249 | option[OPT_CODE] = code; | ||
250 | len = dhcp_option_lengths[dh->flags & OPTION_TYPE_MASK]; | ||
251 | option[OPT_LEN] = len; | ||
252 | if (BB_BIG_ENDIAN) | ||
253 | data <<= 8 * (4 - len); | ||
254 | /* Assignment is unaligned! */ | ||
255 | move_to_unaligned32(&option[OPT_DATA], data); | ||
256 | udhcp_add_option_string(optionptr, option); | ||
257 | return; | ||
258 | } | ||
259 | } | ||
260 | |||
261 | bb_error_msg("can't add option 0x%02x", code); | ||
262 | } | ||