diff options
-rw-r--r-- | networking/udhcp/common.c | 63 | ||||
-rw-r--r-- | networking/udhcp/common.h | 11 | ||||
-rw-r--r-- | networking/udhcp/d6_dhcpc.c | 58 | ||||
-rw-r--r-- | networking/udhcp/dhcpc.c | 56 | ||||
-rw-r--r-- | networking/udhcp/dhcpc.h | 4 |
5 files changed, 115 insertions, 77 deletions
diff --git a/networking/udhcp/common.c b/networking/udhcp/common.c index f2d6907ad..684d76b2b 100644 --- a/networking/udhcp/common.c +++ b/networking/udhcp/common.c | |||
@@ -420,6 +420,43 @@ int FAST_FUNC udhcp_str2nip(const char *str, void *arg) | |||
420 | return 1; | 420 | return 1; |
421 | } | 421 | } |
422 | 422 | ||
423 | void* FAST_FUNC udhcp_insert_new_option( | ||
424 | struct option_set **opt_list, | ||
425 | unsigned code, | ||
426 | const void *buffer, | ||
427 | unsigned length, | ||
428 | bool dhcpv6) | ||
429 | { | ||
430 | IF_NOT_UDHCPC6(bool dhcpv6 = 0;) | ||
431 | struct option_set *new, **curr; | ||
432 | |||
433 | log2("attaching option %02x to list", code); | ||
434 | new = xmalloc(sizeof(*new)); | ||
435 | if (!dhcpv6) { | ||
436 | new->data = xmalloc(length + OPT_DATA); | ||
437 | new->data[OPT_CODE] = code; | ||
438 | new->data[OPT_LEN] = length; | ||
439 | memcpy(new->data + OPT_DATA, buffer, length); | ||
440 | } else { | ||
441 | new->data = xmalloc(length + D6_OPT_DATA); | ||
442 | new->data[D6_OPT_CODE] = code >> 8; | ||
443 | new->data[D6_OPT_CODE + 1] = code & 0xff; | ||
444 | new->data[D6_OPT_LEN] = length >> 8; | ||
445 | new->data[D6_OPT_LEN + 1] = length & 0xff; | ||
446 | memcpy(new->data + D6_OPT_DATA, buffer, length); | ||
447 | } | ||
448 | |||
449 | curr = opt_list; | ||
450 | //FIXME: DHCP6 codes > 255!! | ||
451 | while (*curr && (*curr)->data[OPT_CODE] < code) | ||
452 | curr = &(*curr)->next; | ||
453 | |||
454 | new->next = *curr; | ||
455 | *curr = new; | ||
456 | |||
457 | return new->data; | ||
458 | } | ||
459 | |||
423 | /* udhcp_str2optset: | 460 | /* udhcp_str2optset: |
424 | * Parse string option representation to binary form and add it to opt_list. | 461 | * Parse string option representation to binary form and add it to opt_list. |
425 | * Called to parse "udhcpc -x OPTNAME:OPTVAL" | 462 | * Called to parse "udhcpc -x OPTNAME:OPTVAL" |
@@ -459,32 +496,8 @@ static NOINLINE void attach_option( | |||
459 | 496 | ||
460 | existing = udhcp_find_option(*opt_list, optflag->code); | 497 | existing = udhcp_find_option(*opt_list, optflag->code); |
461 | if (!existing) { | 498 | if (!existing) { |
462 | struct option_set *new, **curr; | ||
463 | |||
464 | /* make a new option */ | 499 | /* make a new option */ |
465 | log2("attaching option %02x to list", optflag->code); | 500 | udhcp_insert_new_option(opt_list, optflag->code, buffer, length, dhcpv6); |
466 | new = xmalloc(sizeof(*new)); | ||
467 | if (!dhcpv6) { | ||
468 | new->data = xmalloc(length + OPT_DATA); | ||
469 | new->data[OPT_CODE] = optflag->code; | ||
470 | new->data[OPT_LEN] = length; | ||
471 | memcpy(new->data + OPT_DATA, buffer, length); | ||
472 | } else { | ||
473 | new->data = xmalloc(length + D6_OPT_DATA); | ||
474 | new->data[D6_OPT_CODE] = optflag->code >> 8; | ||
475 | new->data[D6_OPT_CODE + 1] = optflag->code & 0xff; | ||
476 | new->data[D6_OPT_LEN] = length >> 8; | ||
477 | new->data[D6_OPT_LEN + 1] = length & 0xff; | ||
478 | memcpy(new->data + D6_OPT_DATA, buffer, | ||
479 | length); | ||
480 | } | ||
481 | |||
482 | curr = opt_list; | ||
483 | while (*curr && (*curr)->data[OPT_CODE] < optflag->code) | ||
484 | curr = &(*curr)->next; | ||
485 | |||
486 | new->next = *curr; | ||
487 | *curr = new; | ||
488 | goto ret; | 501 | goto ret; |
489 | } | 502 | } |
490 | 503 | ||
diff --git a/networking/udhcp/common.h b/networking/udhcp/common.h index cc0abd269..e5af62874 100644 --- a/networking/udhcp/common.h +++ b/networking/udhcp/common.h | |||
@@ -319,6 +319,17 @@ void udhcp_dump_packet(struct dhcp_packet *packet) FAST_FUNC; | |||
319 | 319 | ||
320 | /* 2nd param is "uint32_t*" */ | 320 | /* 2nd param is "uint32_t*" */ |
321 | int FAST_FUNC udhcp_str2nip(const char *str, void *arg); | 321 | int FAST_FUNC udhcp_str2nip(const char *str, void *arg); |
322 | |||
323 | #if !ENABLE_UDHCPC6 | ||
324 | #define udhcp_insert_new_option(opt_list, code, buffer, length, dhcpv6) \ | ||
325 | udhcp_insert_new_option(opt_list, code, buffer, length) | ||
326 | #endif | ||
327 | void* FAST_FUNC udhcp_insert_new_option(struct option_set **opt_list, | ||
328 | unsigned code, | ||
329 | const void *buffer, | ||
330 | unsigned length, | ||
331 | bool dhcpv6); | ||
332 | |||
322 | /* 2nd param is "struct option_set**" */ | 333 | /* 2nd param is "struct option_set**" */ |
323 | #if !ENABLE_UDHCPC6 | 334 | #if !ENABLE_UDHCPC6 |
324 | #define udhcp_str2optset(str, arg, optflags, option_strings, dhcpv6) \ | 335 | #define udhcp_str2optset(str, arg, optflags, option_strings, dhcpv6) \ |
diff --git a/networking/udhcp/d6_dhcpc.c b/networking/udhcp/d6_dhcpc.c index 5bca4a824..c4bedb259 100644 --- a/networking/udhcp/d6_dhcpc.c +++ b/networking/udhcp/d6_dhcpc.c | |||
@@ -482,7 +482,6 @@ static ALWAYS_INLINE uint32_t random_xid(void) | |||
482 | static uint8_t *init_d6_packet(struct d6_packet *packet, char type, uint32_t xid) | 482 | static uint8_t *init_d6_packet(struct d6_packet *packet, char type, uint32_t xid) |
483 | { | 483 | { |
484 | uint8_t *ptr; | 484 | uint8_t *ptr; |
485 | struct d6_option *clientid; | ||
486 | unsigned secs; | 485 | unsigned secs; |
487 | 486 | ||
488 | memset(packet, 0, sizeof(*packet)); | 487 | memset(packet, 0, sizeof(*packet)); |
@@ -503,9 +502,7 @@ static uint8_t *init_d6_packet(struct d6_packet *packet, char type, uint32_t xid | |||
503 | *((uint16_t*)ptr) = (secs < 0xffff) ? htons(secs) : 0xffff; | 502 | *((uint16_t*)ptr) = (secs < 0xffff) ? htons(secs) : 0xffff; |
504 | ptr += 2; | 503 | ptr += 2; |
505 | 504 | ||
506 | /* add CLIENTID option */ | 505 | return ptr; |
507 | clientid = (void*)client_data.clientid; | ||
508 | return mempcpy(ptr, clientid, clientid->len + 2+2); | ||
509 | } | 506 | } |
510 | 507 | ||
511 | static uint8_t *add_d6_client_options(uint8_t *ptr) | 508 | static uint8_t *add_d6_client_options(uint8_t *ptr) |
@@ -593,10 +590,10 @@ static NOINLINE int send_d6_info_request(uint32_t xid) | |||
593 | struct d6_packet packet; | 590 | struct d6_packet packet; |
594 | uint8_t *opt_ptr; | 591 | uint8_t *opt_ptr; |
595 | 592 | ||
596 | /* Fill in: msg type, client id */ | 593 | /* Fill in: msg type */ |
597 | opt_ptr = init_d6_packet(&packet, D6_MSG_INFORMATION_REQUEST, xid); | 594 | opt_ptr = init_d6_packet(&packet, D6_MSG_INFORMATION_REQUEST, xid); |
598 | 595 | ||
599 | /* Add options: | 596 | /* Add options: client-id, |
600 | * "param req" option according to -O, options specified with -x | 597 | * "param req" option according to -O, options specified with -x |
601 | */ | 598 | */ |
602 | opt_ptr = add_d6_client_options(opt_ptr); | 599 | opt_ptr = add_d6_client_options(opt_ptr); |
@@ -693,7 +690,7 @@ static NOINLINE int send_d6_discover(uint32_t xid, struct in6_addr *requested_ip | |||
693 | uint8_t *opt_ptr; | 690 | uint8_t *opt_ptr; |
694 | unsigned len; | 691 | unsigned len; |
695 | 692 | ||
696 | /* Fill in: msg type, client id */ | 693 | /* Fill in: msg type */ |
697 | opt_ptr = init_d6_packet(&packet, D6_MSG_SOLICIT, xid); | 694 | opt_ptr = init_d6_packet(&packet, D6_MSG_SOLICIT, xid); |
698 | 695 | ||
699 | /* Create new IA_NA, optionally with included IAADDR with requested IP */ | 696 | /* Create new IA_NA, optionally with included IAADDR with requested IP */ |
@@ -726,7 +723,7 @@ static NOINLINE int send_d6_discover(uint32_t xid, struct in6_addr *requested_ip | |||
726 | opt_ptr = mempcpy(opt_ptr, client6_data.ia_pd, len); | 723 | opt_ptr = mempcpy(opt_ptr, client6_data.ia_pd, len); |
727 | } | 724 | } |
728 | 725 | ||
729 | /* Add options: | 726 | /* Add options: client-id, |
730 | * "param req" option according to -O, options specified with -x | 727 | * "param req" option according to -O, options specified with -x |
731 | */ | 728 | */ |
732 | opt_ptr = add_d6_client_options(opt_ptr); | 729 | opt_ptr = add_d6_client_options(opt_ptr); |
@@ -771,7 +768,7 @@ static NOINLINE int send_d6_select(uint32_t xid) | |||
771 | struct d6_packet packet; | 768 | struct d6_packet packet; |
772 | uint8_t *opt_ptr; | 769 | uint8_t *opt_ptr; |
773 | 770 | ||
774 | /* Fill in: msg type, client id */ | 771 | /* Fill in: msg type */ |
775 | opt_ptr = init_d6_packet(&packet, D6_MSG_REQUEST, xid); | 772 | opt_ptr = init_d6_packet(&packet, D6_MSG_REQUEST, xid); |
776 | 773 | ||
777 | /* server id */ | 774 | /* server id */ |
@@ -783,7 +780,7 @@ static NOINLINE int send_d6_select(uint32_t xid) | |||
783 | if (client6_data.ia_pd) | 780 | if (client6_data.ia_pd) |
784 | opt_ptr = mempcpy(opt_ptr, client6_data.ia_pd, client6_data.ia_pd->len + 2+2); | 781 | opt_ptr = mempcpy(opt_ptr, client6_data.ia_pd, client6_data.ia_pd->len + 2+2); |
785 | 782 | ||
786 | /* Add options: | 783 | /* Add options: client-id, |
787 | * "param req" option according to -O, options specified with -x | 784 | * "param req" option according to -O, options specified with -x |
788 | */ | 785 | */ |
789 | opt_ptr = add_d6_client_options(opt_ptr); | 786 | opt_ptr = add_d6_client_options(opt_ptr); |
@@ -844,7 +841,7 @@ static NOINLINE int send_d6_renew(uint32_t xid, struct in6_addr *server_ipv6, st | |||
844 | struct d6_packet packet; | 841 | struct d6_packet packet; |
845 | uint8_t *opt_ptr; | 842 | uint8_t *opt_ptr; |
846 | 843 | ||
847 | /* Fill in: msg type, client id */ | 844 | /* Fill in: msg type */ |
848 | opt_ptr = init_d6_packet(&packet, DHCPREQUEST, xid); | 845 | opt_ptr = init_d6_packet(&packet, DHCPREQUEST, xid); |
849 | 846 | ||
850 | /* server id */ | 847 | /* server id */ |
@@ -856,7 +853,7 @@ static NOINLINE int send_d6_renew(uint32_t xid, struct in6_addr *server_ipv6, st | |||
856 | if (client6_data.ia_pd) | 853 | if (client6_data.ia_pd) |
857 | opt_ptr = mempcpy(opt_ptr, client6_data.ia_pd, client6_data.ia_pd->len + 2+2); | 854 | opt_ptr = mempcpy(opt_ptr, client6_data.ia_pd, client6_data.ia_pd->len + 2+2); |
858 | 855 | ||
859 | /* Add options: | 856 | /* Add options: client-id, |
860 | * "param req" option according to -O, options specified with -x | 857 | * "param req" option according to -O, options specified with -x |
861 | */ | 858 | */ |
862 | opt_ptr = add_d6_client_options(opt_ptr); | 859 | opt_ptr = add_d6_client_options(opt_ptr); |
@@ -878,6 +875,7 @@ int send_d6_release(struct in6_addr *server_ipv6, struct in6_addr *our_cur_ipv6) | |||
878 | { | 875 | { |
879 | struct d6_packet packet; | 876 | struct d6_packet packet; |
880 | uint8_t *opt_ptr; | 877 | uint8_t *opt_ptr; |
878 | struct option_set *ci; | ||
881 | 879 | ||
882 | /* Fill in: msg type, client id */ | 880 | /* Fill in: msg type, client id */ |
883 | opt_ptr = init_d6_packet(&packet, D6_MSG_RELEASE, random_xid()); | 881 | opt_ptr = init_d6_packet(&packet, D6_MSG_RELEASE, random_xid()); |
@@ -889,6 +887,10 @@ int send_d6_release(struct in6_addr *server_ipv6, struct in6_addr *our_cur_ipv6) | |||
889 | /* IA PD */ | 887 | /* IA PD */ |
890 | if (client6_data.ia_pd) | 888 | if (client6_data.ia_pd) |
891 | opt_ptr = mempcpy(opt_ptr, client6_data.ia_pd, client6_data.ia_pd->len + 2+2); | 889 | opt_ptr = mempcpy(opt_ptr, client6_data.ia_pd, client6_data.ia_pd->len + 2+2); |
890 | /* Client-id */ | ||
891 | ci = udhcp_find_option(client_data.options, D6_OPT_CLIENTID); | ||
892 | if (ci) | ||
893 | opt_ptr = mempcpy(opt_ptr, ci->data, D6_OPT_DATA + 2+2 + 6); | ||
892 | 894 | ||
893 | bb_info_msg("sending %s", "release"); | 895 | bb_info_msg("sending %s", "release"); |
894 | return d6_send_kernel_packet_from_client_data_ifindex( | 896 | return d6_send_kernel_packet_from_client_data_ifindex( |
@@ -1184,7 +1186,7 @@ int udhcpc6_main(int argc UNUSED_PARAM, char **argv) | |||
1184 | { | 1186 | { |
1185 | const char *str_r; | 1187 | const char *str_r; |
1186 | IF_FEATURE_UDHCP_PORT(char *str_P;) | 1188 | IF_FEATURE_UDHCP_PORT(char *str_P;) |
1187 | void *clientid_mac_ptr; | 1189 | uint8_t *clientid_mac_ptr; |
1188 | llist_t *list_O = NULL; | 1190 | llist_t *list_O = NULL; |
1189 | llist_t *list_x = NULL; | 1191 | llist_t *list_x = NULL; |
1190 | int tryagain_timeout = 20; | 1192 | int tryagain_timeout = 20; |
@@ -1284,22 +1286,19 @@ int udhcpc6_main(int argc UNUSED_PARAM, char **argv) | |||
1284 | if (d6_read_interface(client_data.interface, | 1286 | if (d6_read_interface(client_data.interface, |
1285 | &client_data.ifindex, | 1287 | &client_data.ifindex, |
1286 | &client6_data.ll_ip6, | 1288 | &client6_data.ll_ip6, |
1287 | client_data.client_mac) | 1289 | client_data_client_mac) |
1288 | ) { | 1290 | ) { |
1289 | return 1; | 1291 | return 1; |
1290 | } | 1292 | } |
1291 | 1293 | ||
1292 | /* Create client ID based on mac, set clientid_mac_ptr */ | 1294 | clientid_mac_ptr = NULL; |
1293 | { | 1295 | if (!udhcp_find_option(client_data.options, D6_OPT_CLIENTID)) { |
1294 | struct d6_option *clientid; | 1296 | /* not set, set the default client ID */ |
1295 | clientid = xzalloc(2+2+2+2+6); | 1297 | client_data.clientid[1] = 3; /* DUID-LL */ |
1296 | clientid->code = D6_OPT_CLIENTID; | 1298 | client_data.clientid[3] = 1; /* ethernet */ |
1297 | clientid->len = 2+2+6; | 1299 | clientid_mac_ptr = udhcp_insert_new_option(&client_data.options, D6_OPT_CLIENTID, |
1298 | clientid->data[1] = 3; /* DUID-LL */ | 1300 | client_data.clientid, 2+2 + 6, /*dhcp6:*/ 1); |
1299 | clientid->data[3] = 1; /* ethernet */ | 1301 | clientid_mac_ptr += 2+2 + 2+2; /* skip option code, len, DUID-LL, ethernet */ |
1300 | clientid_mac_ptr = clientid->data + 2+2; | ||
1301 | memcpy(clientid_mac_ptr, client_data.client_mac, 6); | ||
1302 | client_data.clientid = (void*)clientid; | ||
1303 | } | 1302 | } |
1304 | 1303 | ||
1305 | #if !BB_MMU | 1304 | #if !BB_MMU |
@@ -1386,12 +1385,13 @@ int udhcpc6_main(int argc UNUSED_PARAM, char **argv) | |||
1386 | if (d6_read_interface(client_data.interface, | 1385 | if (d6_read_interface(client_data.interface, |
1387 | &client_data.ifindex, | 1386 | &client_data.ifindex, |
1388 | &client6_data.ll_ip6, | 1387 | &client6_data.ll_ip6, |
1389 | client_data.client_mac) | 1388 | client_data_client_mac) |
1390 | ) { | 1389 | ) { |
1391 | goto ret0; /* iface is gone? */ | 1390 | goto ret0; /* iface is gone? */ |
1392 | } | 1391 | } |
1393 | 1392 | ||
1394 | memcpy(clientid_mac_ptr, client_data.client_mac, 6); | 1393 | if (clientid_mac_ptr) |
1394 | memcpy(clientid_mac_ptr, client_data_client_mac, 6); | ||
1395 | 1395 | ||
1396 | switch (client_data.state) { | 1396 | switch (client_data.state) { |
1397 | case INIT_SELECTING: | 1397 | case INIT_SELECTING: |
@@ -1505,7 +1505,9 @@ int udhcpc6_main(int argc UNUSED_PARAM, char **argv) | |||
1505 | continue; | 1505 | continue; |
1506 | /* case RELEASED: */ | 1506 | /* case RELEASED: */ |
1507 | } | 1507 | } |
1508 | /* yah, I know, *you* say it would never happen */ | 1508 | /* RELEASED state (when we got SIGUSR2) ends up here. |
1509 | * (wait for SIGUSR1 to re-init, or for TERM, etc) | ||
1510 | */ | ||
1509 | timeout = INT_MAX; | 1511 | timeout = INT_MAX; |
1510 | continue; /* back to main loop */ | 1512 | continue; /* back to main loop */ |
1511 | } /* if poll timed out */ | 1513 | } /* if poll timed out */ |
diff --git a/networking/udhcp/dhcpc.c b/networking/udhcp/dhcpc.c index ea06405ba..a06eeaa16 100644 --- a/networking/udhcp/dhcpc.c +++ b/networking/udhcp/dhcpc.c | |||
@@ -612,9 +612,7 @@ static void init_packet(struct dhcp_packet *packet, char type) | |||
612 | secs = client_data.last_secs - client_data.first_secs; | 612 | secs = client_data.last_secs - client_data.first_secs; |
613 | packet->secs = (secs < 0xffff) ? htons(secs) : 0xffff; | 613 | packet->secs = (secs < 0xffff) ? htons(secs) : 0xffff; |
614 | 614 | ||
615 | memcpy(packet->chaddr, client_data.client_mac, 6); | 615 | memcpy(packet->chaddr, client_data_client_mac, 6); |
616 | if (client_data.clientid) | ||
617 | udhcp_add_binary_option(packet, client_data.clientid); | ||
618 | } | 616 | } |
619 | 617 | ||
620 | static void add_client_options(struct dhcp_packet *packet) | 618 | static void add_client_options(struct dhcp_packet *packet) |
@@ -715,7 +713,7 @@ static NOINLINE int send_discover(uint32_t xid, uint32_t requested) | |||
715 | 713 | ||
716 | /* Fill in: op, htype, hlen, cookie, chaddr fields, | 714 | /* Fill in: op, htype, hlen, cookie, chaddr fields, |
717 | * random xid field (we override it below), | 715 | * random xid field (we override it below), |
718 | * client-id option (unless -C), message type option: | 716 | * message type option: |
719 | */ | 717 | */ |
720 | init_packet(&packet, DHCPDISCOVER); | 718 | init_packet(&packet, DHCPDISCOVER); |
721 | 719 | ||
@@ -724,7 +722,7 @@ static NOINLINE int send_discover(uint32_t xid, uint32_t requested) | |||
724 | udhcp_add_simple_option(&packet, DHCP_REQUESTED_IP, requested); | 722 | udhcp_add_simple_option(&packet, DHCP_REQUESTED_IP, requested); |
725 | 723 | ||
726 | /* Add options: maxsize, | 724 | /* Add options: maxsize, |
727 | * optionally: hostname, fqdn, vendorclass, | 725 | * optionally: hostname, fqdn, vendorclass, client-id, |
728 | * "param req" option according to -O, options specified with -x | 726 | * "param req" option according to -O, options specified with -x |
729 | */ | 727 | */ |
730 | add_client_options(&packet); | 728 | add_client_options(&packet); |
@@ -758,7 +756,7 @@ static NOINLINE int send_select(uint32_t xid, uint32_t server, uint32_t requeste | |||
758 | */ | 756 | */ |
759 | /* Fill in: op, htype, hlen, cookie, chaddr fields, | 757 | /* Fill in: op, htype, hlen, cookie, chaddr fields, |
760 | * random xid field (we override it below), | 758 | * random xid field (we override it below), |
761 | * client-id option (unless -C), message type option: | 759 | * message type option: |
762 | */ | 760 | */ |
763 | init_packet(&packet, DHCPREQUEST); | 761 | init_packet(&packet, DHCPREQUEST); |
764 | 762 | ||
@@ -768,7 +766,7 @@ static NOINLINE int send_select(uint32_t xid, uint32_t server, uint32_t requeste | |||
768 | udhcp_add_simple_option(&packet, DHCP_SERVER_ID, server); | 766 | udhcp_add_simple_option(&packet, DHCP_SERVER_ID, server); |
769 | 767 | ||
770 | /* Add options: maxsize, | 768 | /* Add options: maxsize, |
771 | * optionally: hostname, fqdn, vendorclass, | 769 | * optionally: hostname, fqdn, vendorclass, client-id, |
772 | * "param req" option according to -O, and options specified with -x | 770 | * "param req" option according to -O, and options specified with -x |
773 | */ | 771 | */ |
774 | add_client_options(&packet); | 772 | add_client_options(&packet); |
@@ -805,7 +803,7 @@ static NOINLINE int send_renew(uint32_t xid, uint32_t server, uint32_t ciaddr) | |||
805 | */ | 803 | */ |
806 | /* Fill in: op, htype, hlen, cookie, chaddr fields, | 804 | /* Fill in: op, htype, hlen, cookie, chaddr fields, |
807 | * random xid field (we override it below), | 805 | * random xid field (we override it below), |
808 | * client-id option (unless -C), message type option: | 806 | * message type option: |
809 | */ | 807 | */ |
810 | init_packet(&packet, DHCPREQUEST); | 808 | init_packet(&packet, DHCPREQUEST); |
811 | 809 | ||
@@ -813,7 +811,7 @@ static NOINLINE int send_renew(uint32_t xid, uint32_t server, uint32_t ciaddr) | |||
813 | packet.ciaddr = ciaddr; | 811 | packet.ciaddr = ciaddr; |
814 | 812 | ||
815 | /* Add options: maxsize, | 813 | /* Add options: maxsize, |
816 | * optionally: hostname, fqdn, vendorclass, | 814 | * optionally: hostname, fqdn, vendorclass, client-id, |
817 | * "param req" option according to -O, and options specified with -x | 815 | * "param req" option according to -O, and options specified with -x |
818 | */ | 816 | */ |
819 | add_client_options(&packet); | 817 | add_client_options(&packet); |
@@ -837,7 +835,7 @@ static NOINLINE int send_decline(/*uint32_t xid,*/ uint32_t server, uint32_t req | |||
837 | struct dhcp_packet packet; | 835 | struct dhcp_packet packet; |
838 | 836 | ||
839 | /* Fill in: op, htype, hlen, cookie, chaddr, random xid fields, | 837 | /* Fill in: op, htype, hlen, cookie, chaddr, random xid fields, |
840 | * client-id option (unless -C), message type option: | 838 | * message type option: |
841 | */ | 839 | */ |
842 | init_packet(&packet, DHCPDECLINE); | 840 | init_packet(&packet, DHCPDECLINE); |
843 | 841 | ||
@@ -854,6 +852,8 @@ static NOINLINE int send_decline(/*uint32_t xid,*/ uint32_t server, uint32_t req | |||
854 | 852 | ||
855 | udhcp_add_simple_option(&packet, DHCP_SERVER_ID, server); | 853 | udhcp_add_simple_option(&packet, DHCP_SERVER_ID, server); |
856 | 854 | ||
855 | //TODO: add client-id opt? | ||
856 | |||
857 | bb_simple_info_msg("broadcasting decline"); | 857 | bb_simple_info_msg("broadcasting decline"); |
858 | return raw_bcast_from_client_data_ifindex(&packet, INADDR_ANY); | 858 | return raw_bcast_from_client_data_ifindex(&packet, INADDR_ANY); |
859 | } | 859 | } |
@@ -865,9 +865,10 @@ ALWAYS_INLINE /* one caller, help compiler to use this fact */ | |||
865 | int send_release(uint32_t server, uint32_t ciaddr) | 865 | int send_release(uint32_t server, uint32_t ciaddr) |
866 | { | 866 | { |
867 | struct dhcp_packet packet; | 867 | struct dhcp_packet packet; |
868 | struct option_set *ci; | ||
868 | 869 | ||
869 | /* Fill in: op, htype, hlen, cookie, chaddr, random xid fields, | 870 | /* Fill in: op, htype, hlen, cookie, chaddr, random xid fields, |
870 | * client-id option (unless -C), message type option: | 871 | * message type option: |
871 | */ | 872 | */ |
872 | init_packet(&packet, DHCPRELEASE); | 873 | init_packet(&packet, DHCPRELEASE); |
873 | 874 | ||
@@ -876,6 +877,14 @@ int send_release(uint32_t server, uint32_t ciaddr) | |||
876 | 877 | ||
877 | udhcp_add_simple_option(&packet, DHCP_SERVER_ID, server); | 878 | udhcp_add_simple_option(&packet, DHCP_SERVER_ID, server); |
878 | 879 | ||
880 | /* RFC 2131 section 3.1.6: | ||
881 | * If the client used a 'client identifier' when it obtained the lease, | ||
882 | * it MUST use the same 'client identifier' in the DHCPRELEASE message. | ||
883 | */ | ||
884 | ci = udhcp_find_option(client_data.options, DHCP_CLIENT_ID); | ||
885 | if (ci) | ||
886 | udhcp_add_binary_option(&packet, ci->data); | ||
887 | |||
879 | bb_info_msg("sending %s", "release"); | 888 | bb_info_msg("sending %s", "release"); |
880 | /* Note: normally we unicast here since "server" is not zero. | 889 | /* Note: normally we unicast here since "server" is not zero. |
881 | * However, there _are_ people who run "address-less" DHCP servers, | 890 | * However, there _are_ people who run "address-less" DHCP servers, |
@@ -1230,7 +1239,7 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv) | |||
1230 | const char *str_V, *str_h, *str_F, *str_r; | 1239 | const char *str_V, *str_h, *str_F, *str_r; |
1231 | IF_FEATURE_UDHCPC_ARPING(const char *str_a = "2000";) | 1240 | IF_FEATURE_UDHCPC_ARPING(const char *str_a = "2000";) |
1232 | IF_FEATURE_UDHCP_PORT(char *str_P;) | 1241 | IF_FEATURE_UDHCP_PORT(char *str_P;) |
1233 | void *clientid_mac_ptr; | 1242 | uint8_t *clientid_mac_ptr; |
1234 | llist_t *list_O = NULL; | 1243 | llist_t *list_O = NULL; |
1235 | llist_t *list_x = NULL; | 1244 | llist_t *list_x = NULL; |
1236 | int tryagain_timeout = 20; | 1245 | int tryagain_timeout = 20; |
@@ -1339,7 +1348,7 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv) | |||
1339 | if (udhcp_read_interface(client_data.interface, | 1348 | if (udhcp_read_interface(client_data.interface, |
1340 | &client_data.ifindex, | 1349 | &client_data.ifindex, |
1341 | NULL, | 1350 | NULL, |
1342 | client_data.client_mac) | 1351 | client_data_client_mac) |
1343 | ) { | 1352 | ) { |
1344 | return 1; | 1353 | return 1; |
1345 | } | 1354 | } |
@@ -1347,10 +1356,11 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv) | |||
1347 | clientid_mac_ptr = NULL; | 1356 | clientid_mac_ptr = NULL; |
1348 | if (!(opt & OPT_C) && !udhcp_find_option(client_data.options, DHCP_CLIENT_ID)) { | 1357 | if (!(opt & OPT_C) && !udhcp_find_option(client_data.options, DHCP_CLIENT_ID)) { |
1349 | /* not suppressed and not set, set the default client ID */ | 1358 | /* not suppressed and not set, set the default client ID */ |
1350 | client_data.clientid = alloc_dhcp_option(DHCP_CLIENT_ID, "", 7); | 1359 | client_data_client_mac[-1] = 1; /* type: ethernet */ |
1351 | client_data.clientid[OPT_DATA] = 1; /* type: ethernet */ | 1360 | clientid_mac_ptr = udhcp_insert_new_option( |
1352 | clientid_mac_ptr = client_data.clientid + OPT_DATA+1; | 1361 | &client_data.options, DHCP_CLIENT_ID, |
1353 | memcpy(clientid_mac_ptr, client_data.client_mac, 6); | 1362 | client_data_client_mac - 1, 1 + 6, /*dhcp6:*/ 0); |
1363 | clientid_mac_ptr += 3; /* skip option code, len, ethernet */ | ||
1354 | } | 1364 | } |
1355 | if (str_V[0] != '\0') { | 1365 | if (str_V[0] != '\0') { |
1356 | // can drop -V, str_V, client_data.vendorclass, | 1366 | // can drop -V, str_V, client_data.vendorclass, |
@@ -1447,12 +1457,12 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv) | |||
1447 | if (udhcp_read_interface(client_data.interface, | 1457 | if (udhcp_read_interface(client_data.interface, |
1448 | &client_data.ifindex, | 1458 | &client_data.ifindex, |
1449 | NULL, | 1459 | NULL, |
1450 | client_data.client_mac) | 1460 | client_data_client_mac) |
1451 | ) { | 1461 | ) { |
1452 | goto ret0; /* iface is gone? */ | 1462 | goto ret0; /* iface is gone? */ |
1453 | } | 1463 | } |
1454 | if (clientid_mac_ptr) | 1464 | if (clientid_mac_ptr) |
1455 | memcpy(clientid_mac_ptr, client_data.client_mac, 6); | 1465 | memcpy(clientid_mac_ptr, client_data_client_mac, 6); |
1456 | 1466 | ||
1457 | switch (client_data.state) { | 1467 | switch (client_data.state) { |
1458 | case INIT_SELECTING: | 1468 | case INIT_SELECTING: |
@@ -1569,7 +1579,9 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv) | |||
1569 | continue; | 1579 | continue; |
1570 | /* case RELEASED: */ | 1580 | /* case RELEASED: */ |
1571 | } | 1581 | } |
1572 | /* yah, I know, *you* say it would never happen */ | 1582 | /* RELEASED state (when we got SIGUSR2) ends up here. |
1583 | * (wait for SIGUSR1 to re-init, or for TERM, etc) | ||
1584 | */ | ||
1573 | timeout = INT_MAX; | 1585 | timeout = INT_MAX; |
1574 | continue; /* back to main loop */ | 1586 | continue; /* back to main loop */ |
1575 | } /* if poll timed out */ | 1587 | } /* if poll timed out */ |
@@ -1645,7 +1657,7 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv) | |||
1645 | 1657 | ||
1646 | /* Ignore packets that aren't for us */ | 1658 | /* Ignore packets that aren't for us */ |
1647 | if (packet.hlen != 6 | 1659 | if (packet.hlen != 6 |
1648 | || memcmp(packet.chaddr, client_data.client_mac, 6) != 0 | 1660 | || memcmp(packet.chaddr, client_data_client_mac, 6) != 0 |
1649 | ) { | 1661 | ) { |
1650 | //FIXME: need to also check that last 10 bytes are zero | 1662 | //FIXME: need to also check that last 10 bytes are zero |
1651 | log1("chaddr does not match%s", ", ignoring packet"); // log2? | 1663 | log1("chaddr does not match%s", ", ignoring packet"); // log2? |
@@ -1757,7 +1769,7 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv) | |||
1757 | if (!arpping(requested_ip, | 1769 | if (!arpping(requested_ip, |
1758 | NULL, | 1770 | NULL, |
1759 | (uint32_t) 0, | 1771 | (uint32_t) 0, |
1760 | client_data.client_mac, | 1772 | client_data_client_mac, |
1761 | client_data.interface, | 1773 | client_data.interface, |
1762 | arpping_ms) | 1774 | arpping_ms) |
1763 | ) { | 1775 | ) { |
diff --git a/networking/udhcp/dhcpc.h b/networking/udhcp/dhcpc.h index 7ad01ea8f..a4cc188b6 100644 --- a/networking/udhcp/dhcpc.h +++ b/networking/udhcp/dhcpc.h | |||
@@ -8,7 +8,8 @@ | |||
8 | PUSH_AND_SET_FUNCTION_VISIBILITY_TO_HIDDEN | 8 | PUSH_AND_SET_FUNCTION_VISIBILITY_TO_HIDDEN |
9 | 9 | ||
10 | struct client_data_t { | 10 | struct client_data_t { |
11 | uint8_t client_mac[6]; /* Our mac address */ | 11 | uint8_t clientid[2+2 + 6]; /* Our mac address (prefixed by padding used for client-id) */ |
12 | #define client_data_client_mac (client_data.clientid + 2+2) | ||
12 | IF_FEATURE_UDHCP_PORT(uint16_t port;) | 13 | IF_FEATURE_UDHCP_PORT(uint16_t port;) |
13 | int ifindex; /* Index number of the interface to use */ | 14 | int ifindex; /* Index number of the interface to use */ |
14 | uint8_t opt_mask[256 / 8]; /* Bitmask of options to send (-O option) */ | 15 | uint8_t opt_mask[256 / 8]; /* Bitmask of options to send (-O option) */ |
@@ -17,7 +18,6 @@ struct client_data_t { | |||
17 | char *pidfile; /* Optionally store the process ID */ | 18 | char *pidfile; /* Optionally store the process ID */ |
18 | const char *script; /* User script to run at dhcp events */ | 19 | const char *script; /* User script to run at dhcp events */ |
19 | struct option_set *options; /* list of DHCP options to send to server */ | 20 | struct option_set *options; /* list of DHCP options to send to server */ |
20 | uint8_t *clientid; /* Optional client id to use */ | ||
21 | uint8_t *vendorclass; /* Optional vendor class-id to use */ | 21 | uint8_t *vendorclass; /* Optional vendor class-id to use */ |
22 | uint8_t *hostname; /* Optional hostname to use */ | 22 | uint8_t *hostname; /* Optional hostname to use */ |
23 | uint8_t *fqdn; /* Optional fully qualified domain name to use */ | 23 | uint8_t *fqdn; /* Optional fully qualified domain name to use */ |