aboutsummaryrefslogtreecommitdiff
path: root/networking/udhcp/dhcpc.c
diff options
context:
space:
mode:
Diffstat (limited to 'networking/udhcp/dhcpc.c')
-rw-r--r--networking/udhcp/dhcpc.c220
1 files changed, 170 insertions, 50 deletions
diff --git a/networking/udhcp/dhcpc.c b/networking/udhcp/dhcpc.c
index 4d755e6b8..3d4c397ff 100644
--- a/networking/udhcp/dhcpc.c
+++ b/networking/udhcp/dhcpc.c
@@ -100,6 +100,7 @@ static const uint8_t len_of_option_as_string[] = {
100 [OPTION_IP ] = sizeof("255.255.255.255 "), 100 [OPTION_IP ] = sizeof("255.255.255.255 "),
101 [OPTION_IP_PAIR ] = sizeof("255.255.255.255 ") * 2, 101 [OPTION_IP_PAIR ] = sizeof("255.255.255.255 ") * 2,
102 [OPTION_STATIC_ROUTES ] = sizeof("255.255.255.255/32 255.255.255.255 "), 102 [OPTION_STATIC_ROUTES ] = sizeof("255.255.255.255/32 255.255.255.255 "),
103 [OPTION_6RD ] = sizeof("32 128 ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff 255.255.255.255 "),
103 [OPTION_STRING ] = 1, 104 [OPTION_STRING ] = 1,
104#if ENABLE_FEATURE_UDHCP_RFC3397 105#if ENABLE_FEATURE_UDHCP_RFC3397
105 [OPTION_DNS_STRING ] = 1, /* unused */ 106 [OPTION_DNS_STRING ] = 1, /* unused */
@@ -123,6 +124,24 @@ static int sprint_nip(char *dest, const char *pre, const uint8_t *ip)
123 return sprintf(dest, "%s%u.%u.%u.%u", pre, ip[0], ip[1], ip[2], ip[3]); 124 return sprintf(dest, "%s%u.%u.%u.%u", pre, ip[0], ip[1], ip[2], ip[3]);
124} 125}
125 126
127static int sprint_nip6(char *dest, /*const char *pre,*/ const uint8_t *ip)
128{
129 char hexstrbuf[16 * 2];
130 bin2hex(hexstrbuf, (void*)ip, 16);
131 return sprintf(dest, /* "%s" */
132 "%.4s:%.4s:%.4s:%.4s:%.4s:%.4s:%.4s:%.4s",
133 /* pre, */
134 hexstrbuf + 0 * 4,
135 hexstrbuf + 1 * 4,
136 hexstrbuf + 2 * 4,
137 hexstrbuf + 3 * 4,
138 hexstrbuf + 4 * 4,
139 hexstrbuf + 5 * 4,
140 hexstrbuf + 6 * 4,
141 hexstrbuf + 7 * 4
142 );
143}
144
126/* really simple implementation, just count the bits */ 145/* really simple implementation, just count the bits */
127static int mton(uint32_t mask) 146static int mton(uint32_t mask)
128{ 147{
@@ -142,27 +161,25 @@ static NOINLINE char *xmalloc_optname_optval(uint8_t *option, const struct dhcp_
142 int len, type, optlen; 161 int len, type, optlen;
143 char *dest, *ret; 162 char *dest, *ret;
144 163
145 /* option points to OPT_DATA, need to go back and get OPT_LEN */ 164 /* option points to OPT_DATA, need to go back to get OPT_LEN */
146 len = option[OPT_LEN - OPT_DATA]; 165 len = option[-OPT_DATA + OPT_LEN];
147 166
148 type = optflag->flags & OPTION_TYPE_MASK; 167 type = optflag->flags & OPTION_TYPE_MASK;
149 optlen = dhcp_option_lengths[type]; 168 optlen = dhcp_option_lengths[type];
150 upper_length = len_of_option_as_string[type] * ((unsigned)len / (unsigned)optlen); 169 upper_length = len_of_option_as_string[type]
170 * ((unsigned)(len + optlen - 1) / (unsigned)optlen);
151 171
152 dest = ret = xmalloc(upper_length + strlen(opt_name) + 2); 172 dest = ret = xmalloc(upper_length + strlen(opt_name) + 2);
153 dest += sprintf(ret, "%s=", opt_name); 173 dest += sprintf(ret, "%s=", opt_name);
154 174
155 while (len >= optlen) { 175 while (len >= optlen) {
156 unsigned ip_ofs = 0;
157
158 switch (type) { 176 switch (type) {
177 case OPTION_IP:
159 case OPTION_IP_PAIR: 178 case OPTION_IP_PAIR:
160 dest += sprint_nip(dest, "", option); 179 dest += sprint_nip(dest, "", option);
161 *dest++ = '/'; 180 if (type == OPTION_IP)
162 ip_ofs = 4; 181 break;
163 /* fall through */ 182 dest += sprint_nip(dest, "/", option + 4);
164 case OPTION_IP:
165 dest += sprint_nip(dest, "", option + ip_ofs);
166 break; 183 break;
167// case OPTION_BOOLEAN: 184// case OPTION_BOOLEAN:
168// dest += sprintf(dest, *option ? "yes" : "no"); 185// dest += sprintf(dest, *option ? "yes" : "no");
@@ -184,10 +201,14 @@ static NOINLINE char *xmalloc_optname_optval(uint8_t *option, const struct dhcp_
184 dest += sprintf(dest, type == OPTION_U32 ? "%lu" : "%ld", (unsigned long) ntohl(val_u32)); 201 dest += sprintf(dest, type == OPTION_U32 ? "%lu" : "%ld", (unsigned long) ntohl(val_u32));
185 break; 202 break;
186 } 203 }
204 /* Note: options which use 'return' instead of 'break'
205 * (for example, OPTION_STRING) skip the code which handles
206 * the case of list of options.
207 */
187 case OPTION_STRING: 208 case OPTION_STRING:
188 memcpy(dest, option, len); 209 memcpy(dest, option, len);
189 dest[len] = '\0'; 210 dest[len] = '\0';
190 return ret; /* Short circuit this case */ 211 return ret;
191 case OPTION_STATIC_ROUTES: { 212 case OPTION_STATIC_ROUTES: {
192 /* Option binary format: 213 /* Option binary format:
193 * mask [one byte, 0..32] 214 * mask [one byte, 0..32]
@@ -232,6 +253,53 @@ static NOINLINE char *xmalloc_optname_optval(uint8_t *option, const struct dhcp_
232 253
233 return ret; 254 return ret;
234 } 255 }
256 case OPTION_6RD:
257 /* Option binary format (see RFC 5969):
258 * 0 1 2 3
259 * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
260 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
261 * | OPTION_6RD | option-length | IPv4MaskLen | 6rdPrefixLen |
262 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
263 * | 6rdPrefix |
264 * ... (16 octets) ...
265 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
266 * ... 6rdBRIPv4Address(es) ...
267 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
268 * We convert it to a string
269 * "IPv4MaskLen 6rdPrefixLen 6rdPrefix 6rdBRIPv4Address..."
270 *
271 * Sanity check: ensure that our length is at least 22 bytes, that
272 * IPv4MaskLen <= 32,
273 * 6rdPrefixLen <= 128,
274 * 6rdPrefixLen + (32 - IPv4MaskLen) <= 128
275 * (2nd condition need no check - it follows from 1st and 3rd).
276 * Else, return envvar with empty value ("optname=")
277 */
278 if (len >= (1 + 1 + 16 + 4)
279 && option[0] <= 32
280 && (option[1] + 32 - option[0]) <= 128
281 ) {
282 /* IPv4MaskLen */
283 dest += sprintf(dest, "%u ", *option++);
284 /* 6rdPrefixLen */
285 dest += sprintf(dest, "%u ", *option++);
286 /* 6rdPrefix */
287 dest += sprint_nip6(dest, /* "", */ option);
288 option += 16;
289 len -= 1 + 1 + 16 + 4;
290 /* "+ 4" above corresponds to the length of IPv4 addr
291 * we consume in the loop below */
292 while (1) {
293 /* 6rdBRIPv4Address(es) */
294 dest += sprint_nip(dest, " ", option);
295 option += 4;
296 len -= 4; /* do we have yet another 4+ bytes? */
297 if (len < 0)
298 break; /* no */
299 }
300 }
301
302 return ret;
235#if ENABLE_FEATURE_UDHCP_RFC3397 303#if ENABLE_FEATURE_UDHCP_RFC3397
236 case OPTION_DNS_STRING: 304 case OPTION_DNS_STRING:
237 /* unpack option into dest; use ret for prefix (i.e., "optname=") */ 305 /* unpack option into dest; use ret for prefix (i.e., "optname=") */
@@ -271,16 +339,21 @@ static NOINLINE char *xmalloc_optname_optval(uint8_t *option, const struct dhcp_
271 return ret; 339 return ret;
272#endif 340#endif
273 } /* switch */ 341 } /* switch */
342
343 /* If we are here, try to format any remaining data
344 * in the option as another, similarly-formatted option
345 */
274 option += optlen; 346 option += optlen;
275 len -= optlen; 347 len -= optlen;
276// TODO: it can be a list only if (optflag->flags & OPTION_LIST). 348// TODO: it can be a list only if (optflag->flags & OPTION_LIST).
277// Should we bail out/warn if we see multi-ip option which is 349// Should we bail out/warn if we see multi-ip option which is
278// not allowed to be such (for example, DHCP_BROADCAST)? - 350// not allowed to be such (for example, DHCP_BROADCAST)? -
279 if (len <= 0 /* || !(optflag->flags & OPTION_LIST) */) 351 if (len < optlen /* || !(optflag->flags & OPTION_LIST) */)
280 break; 352 break;
281 *dest++ = ' '; 353 *dest++ = ' ';
282 *dest = '\0'; 354 *dest = '\0';
283 } 355 } /* while */
356
284 return ret; 357 return ret;
285} 358}
286 359
@@ -320,7 +393,7 @@ static char **fill_envp(struct dhcp_packet *packet)
320 if (i == DHCP_OPTION_OVERLOAD) 393 if (i == DHCP_OPTION_OVERLOAD)
321 overload = *temp; 394 overload = *temp;
322 else if (i == DHCP_SUBNET) 395 else if (i == DHCP_SUBNET)
323 envc++; /* for mton */ 396 envc++; /* for $mask */
324 envc++; 397 envc++;
325 /*if (i != DHCP_MESSAGE_TYPE)*/ 398 /*if (i != DHCP_MESSAGE_TYPE)*/
326 FOUND_OPTS(i) |= BMASK(i); 399 FOUND_OPTS(i) |= BMASK(i);
@@ -335,10 +408,42 @@ static char **fill_envp(struct dhcp_packet *packet)
335 if (!packet) 408 if (!packet)
336 return envp; 409 return envp;
337 410
411 /* Export BOOTP fields. Fields we don't (yet?) export:
412 * uint8_t op; // always BOOTREPLY
413 * uint8_t htype; // hardware address type. 1 = 10mb ethernet
414 * uint8_t hlen; // hardware address length
415 * uint8_t hops; // used by relay agents only
416 * uint32_t xid;
417 * uint16_t secs; // elapsed since client began acquisition/renewal
418 * uint16_t flags; // only one flag so far: bcast. Never set by server
419 * uint32_t ciaddr; // client IP (usually == yiaddr. can it be different
420 * // if during renew server wants to give us differn IP?)
421 * uint32_t gateway_nip; // relay agent IP address
422 * uint8_t chaddr[16]; // link-layer client hardware address (MAC)
423 * TODO: export gateway_nip as $giaddr?
424 */
425 /* Most important one: yiaddr as $ip */
338 *curr = xmalloc(sizeof("ip=255.255.255.255")); 426 *curr = xmalloc(sizeof("ip=255.255.255.255"));
339 sprint_nip(*curr, "ip=", (uint8_t *) &packet->yiaddr); 427 sprint_nip(*curr, "ip=", (uint8_t *) &packet->yiaddr);
340 putenv(*curr++); 428 putenv(*curr++);
429 if (packet->siaddr_nip) {
430 /* IP address of next server to use in bootstrap */
431 *curr = xmalloc(sizeof("siaddr=255.255.255.255"));
432 sprint_nip(*curr, "siaddr=", (uint8_t *) &packet->siaddr_nip);
433 putenv(*curr++);
434 }
435 if (!(overload & FILE_FIELD) && packet->file[0]) {
436 /* watch out for invalid packets */
437 *curr = xasprintf("boot_file=%."DHCP_PKT_FILE_LEN_STR"s", packet->file);
438 putenv(*curr++);
439 }
440 if (!(overload & SNAME_FIELD) && packet->sname[0]) {
441 /* watch out for invalid packets */
442 *curr = xasprintf("sname=%."DHCP_PKT_SNAME_LEN_STR"s", packet->sname);
443 putenv(*curr++);
444 }
341 445
446 /* Export known DHCP options */
342 opt_name = dhcp_option_strings; 447 opt_name = dhcp_option_strings;
343 i = 0; 448 i = 0;
344 while (*opt_name) { 449 while (*opt_name) {
@@ -355,29 +460,14 @@ static char **fill_envp(struct dhcp_packet *packet)
355 /* Subnet option: make things like "$ip/$mask" possible */ 460 /* Subnet option: make things like "$ip/$mask" possible */
356 uint32_t subnet; 461 uint32_t subnet;
357 move_from_unaligned32(subnet, temp); 462 move_from_unaligned32(subnet, temp);
358 *curr = xasprintf("mask=%d", mton(subnet)); 463 *curr = xasprintf("mask=%u", mton(subnet));
359 putenv(*curr++); 464 putenv(*curr++);
360 } 465 }
361 next: 466 next:
362 opt_name += strlen(opt_name) + 1; 467 opt_name += strlen(opt_name) + 1;
363 i++; 468 i++;
364 } 469 }
365 if (packet->siaddr_nip) { 470 /* Export unknown options */
366 *curr = xmalloc(sizeof("siaddr=255.255.255.255"));
367 sprint_nip(*curr, "siaddr=", (uint8_t *) &packet->siaddr_nip);
368 putenv(*curr++);
369 }
370 if (!(overload & FILE_FIELD) && packet->file[0]) {
371 /* watch out for invalid packets */
372 *curr = xasprintf("boot_file=%."DHCP_PKT_FILE_LEN_STR"s", packet->file);
373 putenv(*curr++);
374 }
375 if (!(overload & SNAME_FIELD) && packet->sname[0]) {
376 /* watch out for invalid packets */
377 *curr = xasprintf("sname=%."DHCP_PKT_SNAME_LEN_STR"s", packet->sname);
378 putenv(*curr++);
379 }
380 /* Handle unknown options */
381 for (i = 0; i < 256;) { 471 for (i = 0; i < 256;) {
382 BITMAP bitmap = FOUND_OPTS(i); 472 BITMAP bitmap = FOUND_OPTS(i);
383 if (!bitmap) { 473 if (!bitmap) {
@@ -394,11 +484,12 @@ static char **fill_envp(struct dhcp_packet *packet)
394 len = temp[-OPT_DATA + OPT_LEN]; 484 len = temp[-OPT_DATA + OPT_LEN];
395 *curr = xmalloc(sizeof("optNNN=") + 1 + len*2); 485 *curr = xmalloc(sizeof("optNNN=") + 1 + len*2);
396 ofs = sprintf(*curr, "opt%u=", i); 486 ofs = sprintf(*curr, "opt%u=", i);
397 bin2hex(*curr + ofs, (void*) temp, len)[0] = '\0'; 487 *bin2hex(*curr + ofs, (void*) temp, len) = '\0';
398 putenv(*curr++); 488 putenv(*curr++);
399 } 489 }
400 i++; 490 i++;
401 } 491 }
492
402 return envp; 493 return envp;
403} 494}
404 495
@@ -726,7 +817,8 @@ static NOINLINE int udhcp_recv_raw_packet(struct dhcp_packet *dhcp_pkt, int fd)
726 bytes = ntohs(packet.ip.tot_len); 817 bytes = ntohs(packet.ip.tot_len);
727 818
728 /* make sure its the right packet for us, and that it passes sanity checks */ 819 /* make sure its the right packet for us, and that it passes sanity checks */
729 if (packet.ip.protocol != IPPROTO_UDP || packet.ip.version != IPVERSION 820 if (packet.ip.protocol != IPPROTO_UDP
821 || packet.ip.version != IPVERSION
730 || packet.ip.ihl != (sizeof(packet.ip) >> 2) 822 || packet.ip.ihl != (sizeof(packet.ip) >> 2)
731 || packet.udp.dest != htons(CLIENT_PORT) 823 || packet.udp.dest != htons(CLIENT_PORT)
732 /* || bytes > (int) sizeof(packet) - can't happen */ 824 /* || bytes > (int) sizeof(packet) - can't happen */
@@ -739,7 +831,7 @@ static NOINLINE int udhcp_recv_raw_packet(struct dhcp_packet *dhcp_pkt, int fd)
739 /* verify IP checksum */ 831 /* verify IP checksum */
740 check = packet.ip.check; 832 check = packet.ip.check;
741 packet.ip.check = 0; 833 packet.ip.check = 0;
742 if (check != udhcp_checksum(&packet.ip, sizeof(packet.ip))) { 834 if (check != inet_cksum((uint16_t *)&packet.ip, sizeof(packet.ip))) {
743 log1("Bad IP header checksum, ignoring"); 835 log1("Bad IP header checksum, ignoring");
744 return -2; 836 return -2;
745 } 837 }
@@ -750,20 +842,22 @@ static NOINLINE int udhcp_recv_raw_packet(struct dhcp_packet *dhcp_pkt, int fd)
750 packet.ip.tot_len = packet.udp.len; /* yes, this is needed */ 842 packet.ip.tot_len = packet.udp.len; /* yes, this is needed */
751 check = packet.udp.check; 843 check = packet.udp.check;
752 packet.udp.check = 0; 844 packet.udp.check = 0;
753 if (check && check != udhcp_checksum(&packet, bytes)) { 845 if (check && check != inet_cksum((uint16_t *)&packet, bytes)) {
754 log1("Packet with bad UDP checksum received, ignoring"); 846 log1("Packet with bad UDP checksum received, ignoring");
755 return -2; 847 return -2;
756 } 848 }
757 849
758 memcpy(dhcp_pkt, &packet.data, bytes - (sizeof(packet.ip) + sizeof(packet.udp))); 850 if (packet.data.cookie != htonl(DHCP_MAGIC)) {
759
760 if (dhcp_pkt->cookie != htonl(DHCP_MAGIC)) {
761 bb_info_msg("Packet with bad magic, ignoring"); 851 bb_info_msg("Packet with bad magic, ignoring");
762 return -2; 852 return -2;
763 } 853 }
854
764 log1("Got valid DHCP packet"); 855 log1("Got valid DHCP packet");
765 udhcp_dump_packet(dhcp_pkt); 856 udhcp_dump_packet(&packet.data);
766 return bytes - (sizeof(packet.ip) + sizeof(packet.udp)); 857
858 bytes -= sizeof(packet.ip) + sizeof(packet.udp);
859 memcpy(dhcp_pkt, &packet.data, bytes);
860 return bytes;
767} 861}
768 862
769 863
@@ -1077,11 +1171,7 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv)
1077 1171
1078 /* Parse command line */ 1172 /* Parse command line */
1079 /* O,x: list; -T,-t,-A take numeric param */ 1173 /* O,x: list; -T,-t,-A take numeric param */
1080 opt_complementary = "O::x::T+:t+:A+" 1174 opt_complementary = "O::x::T+:t+:A+" IF_UDHCP_VERBOSE(":vv") ;
1081#if defined CONFIG_UDHCP_DEBUG && CONFIG_UDHCP_DEBUG >= 1
1082 ":vv"
1083#endif
1084 ;
1085 IF_LONG_OPTS(applet_long_options = udhcpc_longopts;) 1175 IF_LONG_OPTS(applet_long_options = udhcpc_longopts;)
1086 opt = getopt32(argv, "CV:H:h:F:i:np:qRr:s:T:t:SA:O:ox:fB" 1176 opt = getopt32(argv, "CV:H:h:F:i:np:qRr:s:T:t:SA:O:ox:fB"
1087 USE_FOR_MMU("b") 1177 USE_FOR_MMU("b")
@@ -1095,9 +1185,7 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv)
1095 , &list_O 1185 , &list_O
1096 , &list_x 1186 , &list_x
1097 IF_FEATURE_UDHCP_PORT(, &str_P) 1187 IF_FEATURE_UDHCP_PORT(, &str_P)
1098#if defined CONFIG_UDHCP_DEBUG && CONFIG_UDHCP_DEBUG >= 1 1188 IF_UDHCP_VERBOSE(, &dhcp_verbose)
1099 , &dhcp_verbose
1100#endif
1101 ); 1189 );
1102 if (opt & (OPT_h|OPT_H)) 1190 if (opt & (OPT_h|OPT_H))
1103 client_config.hostname = alloc_dhcp_option(DHCP_HOST_NAME, str_h, 0); 1191 client_config.hostname = alloc_dhcp_option(DHCP_HOST_NAME, str_h, 0);
@@ -1361,9 +1449,23 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv)
1361 switch (udhcp_sp_read(&rfds)) { 1449 switch (udhcp_sp_read(&rfds)) {
1362 case SIGUSR1: 1450 case SIGUSR1:
1363 client_config.first_secs = 0; /* make secs field count from 0 */ 1451 client_config.first_secs = 0; /* make secs field count from 0 */
1452 already_waited_sec = 0;
1364 perform_renew(); 1453 perform_renew();
1365 if (state == RENEW_REQUESTED) 1454 if (state == RENEW_REQUESTED) {
1455 /* We might be either on the same network
1456 * (in which case renew might work),
1457 * or we might be on a completely different one
1458 * (in which case renew won't ever succeed).
1459 * For the second case, must make sure timeout
1460 * is not too big, or else we can send
1461 * futile renew requests for hours.
1462 * (Ab)use -A TIMEOUT value (usually 20 sec)
1463 * as a cap on the timeout.
1464 */
1465 if (timeout > tryagain_timeout)
1466 timeout = tryagain_timeout;
1366 goto case_RENEW_REQUESTED; 1467 goto case_RENEW_REQUESTED;
1468 }
1367 /* Start things over */ 1469 /* Start things over */
1368 packet_num = 0; 1470 packet_num = 0;
1369 /* Kill any timeouts, user wants this to hurry along */ 1471 /* Kill any timeouts, user wants this to hurry along */
@@ -1431,7 +1533,25 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv)
1431 case INIT_SELECTING: 1533 case INIT_SELECTING:
1432 /* Must be a DHCPOFFER to one of our xid's */ 1534 /* Must be a DHCPOFFER to one of our xid's */
1433 if (*message == DHCPOFFER) { 1535 if (*message == DHCPOFFER) {
1434 /* TODO: why we don't just fetch server's IP from IP header? */ 1536/* What exactly is server's IP? There are several values.
1537 * Example DHCP offer captured with tchdump:
1538 *
1539 * 10.34.25.254:67 > 10.34.25.202:68 // IP header's src
1540 * BOOTP fields:
1541 * Your-IP 10.34.25.202
1542 * Server-IP 10.34.32.125 // "next server" IP
1543 * Gateway-IP 10.34.25.254 // relay's address (if DHCP relays are in use)
1544 * DHCP options:
1545 * DHCP-Message Option 53, length 1: Offer
1546 * Server-ID Option 54, length 4: 10.34.255.7 // "server ID"
1547 * Default-Gateway Option 3, length 4: 10.34.25.254 // router
1548 *
1549 * We think that real server IP (one to use in renew/release)
1550 * is one in Server-ID option. But I am not 100% sure.
1551 * IP header's src and Gateway-IP (same in this example)
1552 * might work too.
1553 * "Next server" and router are definitely wrong ones to use, though...
1554 */
1435 temp = udhcp_get_option(&packet, DHCP_SERVER_ID); 1555 temp = udhcp_get_option(&packet, DHCP_SERVER_ID);
1436 if (!temp) { 1556 if (!temp) {
1437 bb_error_msg("no server ID, ignoring packet"); 1557 bb_error_msg("no server ID, ignoring packet");