diff options
Diffstat (limited to 'networking/udhcp/dhcpc.c')
-rw-r--r-- | networking/udhcp/dhcpc.c | 131 |
1 files changed, 60 insertions, 71 deletions
diff --git a/networking/udhcp/dhcpc.c b/networking/udhcp/dhcpc.c index 4e3d8ca5e..331f13a8c 100644 --- a/networking/udhcp/dhcpc.c +++ b/networking/udhcp/dhcpc.c | |||
@@ -605,7 +605,7 @@ static void init_packet(struct dhcp_packet *packet, char type) | |||
605 | /* Fill in: op, htype, hlen, cookie fields; message type option: */ | 605 | /* Fill in: op, htype, hlen, cookie fields; message type option: */ |
606 | udhcp_init_header(packet, type); | 606 | udhcp_init_header(packet, type); |
607 | 607 | ||
608 | packet->xid = random_xid(); | 608 | packet->xid = client_data.xid; |
609 | 609 | ||
610 | client_data.last_secs = monotonic_sec(); | 610 | client_data.last_secs = monotonic_sec(); |
611 | if (client_data.first_secs == 0) | 611 | if (client_data.first_secs == 0) |
@@ -663,6 +663,24 @@ static void add_client_options(struct dhcp_packet *packet) | |||
663 | // ...add (DHCP_VENDOR, "udhcp "BB_VER) opt... | 663 | // ...add (DHCP_VENDOR, "udhcp "BB_VER) opt... |
664 | } | 664 | } |
665 | 665 | ||
666 | static void add_serverid_and_clientid_options(struct dhcp_packet *packet, uint32_t server) | ||
667 | { | ||
668 | struct option_set *ci; | ||
669 | |||
670 | udhcp_add_simple_option(packet, DHCP_SERVER_ID, server); | ||
671 | |||
672 | /* RFC 2131 section 2: | ||
673 | * If the client uses a 'client identifier' in one message, | ||
674 | * it MUST use that same identifier in all subsequent messages. | ||
675 | * section 3.1.6: | ||
676 | * If the client used a 'client identifier' when it obtained the lease, | ||
677 | * it MUST use the same 'client identifier' in the DHCPRELEASE message. | ||
678 | */ | ||
679 | ci = udhcp_find_option(client_data.options, DHCP_CLIENT_ID); | ||
680 | if (ci) | ||
681 | udhcp_add_binary_option(packet, ci->data); | ||
682 | } | ||
683 | |||
666 | /* RFC 2131 | 684 | /* RFC 2131 |
667 | * 4.4.4 Use of broadcast and unicast | 685 | * 4.4.4 Use of broadcast and unicast |
668 | * | 686 | * |
@@ -701,17 +719,15 @@ static int bcast_or_ucast(struct dhcp_packet *packet, uint32_t ciaddr, uint32_t | |||
701 | 719 | ||
702 | /* Broadcast a DHCP discover packet to the network, with an optionally requested IP */ | 720 | /* Broadcast a DHCP discover packet to the network, with an optionally requested IP */ |
703 | /* NOINLINE: limit stack usage in caller */ | 721 | /* NOINLINE: limit stack usage in caller */ |
704 | static NOINLINE int send_discover(uint32_t xid, uint32_t requested) | 722 | static NOINLINE int send_discover(uint32_t requested) |
705 | { | 723 | { |
706 | struct dhcp_packet packet; | 724 | struct dhcp_packet packet; |
707 | 725 | ||
708 | /* Fill in: op, htype, hlen, cookie, chaddr fields, | 726 | /* Fill in: op, htype, hlen, cookie, chaddr fields, |
709 | * random xid field (we override it below), | 727 | * xid field, message type option: |
710 | * message type option: | ||
711 | */ | 728 | */ |
712 | init_packet(&packet, DHCPDISCOVER); | 729 | init_packet(&packet, DHCPDISCOVER); |
713 | 730 | ||
714 | packet.xid = xid; | ||
715 | if (requested) | 731 | if (requested) |
716 | udhcp_add_simple_option(&packet, DHCP_REQUESTED_IP, requested); | 732 | udhcp_add_simple_option(&packet, DHCP_REQUESTED_IP, requested); |
717 | 733 | ||
@@ -729,7 +745,7 @@ static NOINLINE int send_discover(uint32_t xid, uint32_t requested) | |||
729 | * "The client _broadcasts_ a DHCPREQUEST message..." | 745 | * "The client _broadcasts_ a DHCPREQUEST message..." |
730 | */ | 746 | */ |
731 | /* NOINLINE: limit stack usage in caller */ | 747 | /* NOINLINE: limit stack usage in caller */ |
732 | static NOINLINE int send_select(uint32_t xid, uint32_t server, uint32_t requested) | 748 | static NOINLINE int send_select(uint32_t server, uint32_t requested) |
733 | { | 749 | { |
734 | struct dhcp_packet packet; | 750 | struct dhcp_packet packet; |
735 | struct in_addr temp_addr; | 751 | struct in_addr temp_addr; |
@@ -748,18 +764,16 @@ static NOINLINE int send_select(uint32_t xid, uint32_t server, uint32_t requeste | |||
748 | * include that list in all subsequent messages. | 764 | * include that list in all subsequent messages. |
749 | */ | 765 | */ |
750 | /* Fill in: op, htype, hlen, cookie, chaddr fields, | 766 | /* Fill in: op, htype, hlen, cookie, chaddr fields, |
751 | * random xid field (we override it below), | 767 | * xid field, message type option: |
752 | * message type option: | ||
753 | */ | 768 | */ |
754 | init_packet(&packet, DHCPREQUEST); | 769 | init_packet(&packet, DHCPREQUEST); |
755 | 770 | ||
756 | packet.xid = xid; | ||
757 | udhcp_add_simple_option(&packet, DHCP_REQUESTED_IP, requested); | 771 | udhcp_add_simple_option(&packet, DHCP_REQUESTED_IP, requested); |
758 | 772 | ||
759 | udhcp_add_simple_option(&packet, DHCP_SERVER_ID, server); | 773 | udhcp_add_simple_option(&packet, DHCP_SERVER_ID, server); |
760 | 774 | ||
761 | /* Add options: maxsize, | 775 | /* Add options: maxsize, |
762 | * "param req" option according to -O, and options specified with -x | 776 | * "param req" option according to -O, options specified with -x |
763 | */ | 777 | */ |
764 | add_client_options(&packet); | 778 | add_client_options(&packet); |
765 | 779 | ||
@@ -775,7 +789,7 @@ static NOINLINE int send_select(uint32_t xid, uint32_t server, uint32_t requeste | |||
775 | 789 | ||
776 | /* Unicast or broadcast a DHCP renew message */ | 790 | /* Unicast or broadcast a DHCP renew message */ |
777 | /* NOINLINE: limit stack usage in caller */ | 791 | /* NOINLINE: limit stack usage in caller */ |
778 | static NOINLINE int send_renew(uint32_t xid, uint32_t server, uint32_t ciaddr) | 792 | static NOINLINE int send_renew(uint32_t server, uint32_t ciaddr) |
779 | { | 793 | { |
780 | struct dhcp_packet packet; | 794 | struct dhcp_packet packet; |
781 | 795 | ||
@@ -794,16 +808,14 @@ static NOINLINE int send_renew(uint32_t xid, uint32_t server, uint32_t ciaddr) | |||
794 | * replying to the client. | 808 | * replying to the client. |
795 | */ | 809 | */ |
796 | /* Fill in: op, htype, hlen, cookie, chaddr fields, | 810 | /* Fill in: op, htype, hlen, cookie, chaddr fields, |
797 | * random xid field (we override it below), | 811 | * xid field, message type option: |
798 | * message type option: | ||
799 | */ | 812 | */ |
800 | init_packet(&packet, DHCPREQUEST); | 813 | init_packet(&packet, DHCPREQUEST); |
801 | 814 | ||
802 | packet.xid = xid; | ||
803 | packet.ciaddr = ciaddr; | 815 | packet.ciaddr = ciaddr; |
804 | 816 | ||
805 | /* Add options: maxsize, | 817 | /* Add options: maxsize, |
806 | * "param req" option according to -O, and options specified with -x | 818 | * "param req" option according to -O, options specified with -x |
807 | */ | 819 | */ |
808 | add_client_options(&packet); | 820 | add_client_options(&packet); |
809 | 821 | ||
@@ -821,7 +833,7 @@ static NOINLINE int send_renew(uint32_t xid, uint32_t server, uint32_t ciaddr) | |||
821 | #if ENABLE_FEATURE_UDHCPC_ARPING | 833 | #if ENABLE_FEATURE_UDHCPC_ARPING |
822 | /* Broadcast a DHCP decline message */ | 834 | /* Broadcast a DHCP decline message */ |
823 | /* NOINLINE: limit stack usage in caller */ | 835 | /* NOINLINE: limit stack usage in caller */ |
824 | static NOINLINE int send_decline(/*uint32_t xid,*/ uint32_t server, uint32_t requested) | 836 | static NOINLINE int send_decline(uint32_t server, uint32_t requested) |
825 | { | 837 | { |
826 | struct dhcp_packet packet; | 838 | struct dhcp_packet packet; |
827 | 839 | ||
@@ -830,20 +842,10 @@ static NOINLINE int send_decline(/*uint32_t xid,*/ uint32_t server, uint32_t req | |||
830 | */ | 842 | */ |
831 | init_packet(&packet, DHCPDECLINE); | 843 | init_packet(&packet, DHCPDECLINE); |
832 | 844 | ||
833 | #if 0 | ||
834 | /* RFC 2131 says DHCPDECLINE's xid is randomly selected by client, | ||
835 | * but in case the server is buggy and wants DHCPDECLINE's xid | ||
836 | * to match the xid which started entire handshake, | ||
837 | * we use the same xid we used in initial DHCPDISCOVER: | ||
838 | */ | ||
839 | packet.xid = xid; | ||
840 | #endif | ||
841 | /* DHCPDECLINE uses "requested ip", not ciaddr, to store offered IP */ | 845 | /* DHCPDECLINE uses "requested ip", not ciaddr, to store offered IP */ |
842 | udhcp_add_simple_option(&packet, DHCP_REQUESTED_IP, requested); | 846 | udhcp_add_simple_option(&packet, DHCP_REQUESTED_IP, requested); |
843 | 847 | ||
844 | udhcp_add_simple_option(&packet, DHCP_SERVER_ID, server); | 848 | add_serverid_and_clientid_options(&packet, server); |
845 | |||
846 | //TODO: add client-id opt? | ||
847 | 849 | ||
848 | bb_simple_info_msg("broadcasting decline"); | 850 | bb_simple_info_msg("broadcasting decline"); |
849 | return raw_bcast_from_client_data_ifindex(&packet, INADDR_ANY); | 851 | return raw_bcast_from_client_data_ifindex(&packet, INADDR_ANY); |
@@ -856,7 +858,6 @@ ALWAYS_INLINE /* one caller, help compiler to use this fact */ | |||
856 | int send_release(uint32_t server, uint32_t ciaddr) | 858 | int send_release(uint32_t server, uint32_t ciaddr) |
857 | { | 859 | { |
858 | struct dhcp_packet packet; | 860 | struct dhcp_packet packet; |
859 | struct option_set *ci; | ||
860 | 861 | ||
861 | /* Fill in: op, htype, hlen, cookie, chaddr, random xid fields, | 862 | /* Fill in: op, htype, hlen, cookie, chaddr, random xid fields, |
862 | * message type option: | 863 | * message type option: |
@@ -866,15 +867,7 @@ int send_release(uint32_t server, uint32_t ciaddr) | |||
866 | /* DHCPRELEASE uses ciaddr, not "requested ip", to store IP being released */ | 867 | /* DHCPRELEASE uses ciaddr, not "requested ip", to store IP being released */ |
867 | packet.ciaddr = ciaddr; | 868 | packet.ciaddr = ciaddr; |
868 | 869 | ||
869 | udhcp_add_simple_option(&packet, DHCP_SERVER_ID, server); | 870 | add_serverid_and_clientid_options(&packet, server); |
870 | |||
871 | /* RFC 2131 section 3.1.6: | ||
872 | * If the client used a 'client identifier' when it obtained the lease, | ||
873 | * it MUST use the same 'client identifier' in the DHCPRELEASE message. | ||
874 | */ | ||
875 | ci = udhcp_find_option(client_data.options, DHCP_CLIENT_ID); | ||
876 | if (ci) | ||
877 | udhcp_add_binary_option(&packet, ci->data); | ||
878 | 871 | ||
879 | bb_info_msg("sending %s", "release"); | 872 | bb_info_msg("sending %s", "release"); |
880 | /* Note: normally we unicast here since "server" is not zero. | 873 | /* Note: normally we unicast here since "server" is not zero. |
@@ -1120,7 +1113,7 @@ static void change_listen_mode(int new_mode) | |||
1120 | /* else LISTEN_NONE: client_data.sockfd stays closed */ | 1113 | /* else LISTEN_NONE: client_data.sockfd stays closed */ |
1121 | } | 1114 | } |
1122 | 1115 | ||
1123 | static void perform_release(uint32_t server_addr, uint32_t requested_ip) | 1116 | static void perform_release(uint32_t server_id, uint32_t requested_ip) |
1124 | { | 1117 | { |
1125 | char buffer[sizeof("255.255.255.255")]; | 1118 | char buffer[sizeof("255.255.255.255")]; |
1126 | struct in_addr temp_addr; | 1119 | struct in_addr temp_addr; |
@@ -1133,12 +1126,13 @@ static void perform_release(uint32_t server_addr, uint32_t requested_ip) | |||
1133 | || client_data.state == REBINDING | 1126 | || client_data.state == REBINDING |
1134 | || client_data.state == RENEW_REQUESTED | 1127 | || client_data.state == RENEW_REQUESTED |
1135 | ) { | 1128 | ) { |
1136 | temp_addr.s_addr = server_addr; | 1129 | temp_addr.s_addr = server_id; |
1137 | strcpy(buffer, inet_ntoa(temp_addr)); | 1130 | strcpy(buffer, inet_ntoa(temp_addr)); |
1138 | temp_addr.s_addr = requested_ip; | 1131 | temp_addr.s_addr = requested_ip; |
1139 | bb_info_msg("unicasting a release of %s to %s", | 1132 | bb_info_msg("unicasting a release of %s to %s", |
1140 | inet_ntoa(temp_addr), buffer); | 1133 | inet_ntoa(temp_addr), buffer); |
1141 | send_release(server_addr, requested_ip); /* unicast */ | 1134 | client_data.xid = random_xid(); //TODO: can omit? |
1135 | send_release(server_id, requested_ip); /* unicast */ | ||
1142 | } | 1136 | } |
1143 | bb_simple_info_msg("entering released state"); | 1137 | bb_simple_info_msg("entering released state"); |
1144 | /* | 1138 | /* |
@@ -1167,7 +1161,7 @@ static void client_background(void) | |||
1167 | //usage:# define IF_UDHCP_VERBOSE(...) | 1161 | //usage:# define IF_UDHCP_VERBOSE(...) |
1168 | //usage:#endif | 1162 | //usage:#endif |
1169 | //usage:#define udhcpc_trivial_usage | 1163 | //usage:#define udhcpc_trivial_usage |
1170 | //usage: "[-fbq"IF_UDHCP_VERBOSE("v")"RB]"IF_FEATURE_UDHCPC_ARPING(" [-a[MSEC]]")" [-t N] [-T SEC] [-A SEC/-n]\n" | 1164 | //usage: "[-fbq"IF_UDHCP_VERBOSE("v")"RB]"IF_FEATURE_UDHCPC_ARPING(" [-a[MSEC]]")" [-t N] [-T SEC] [-A SEC|-n]\n" |
1171 | //usage: " [-i IFACE]"IF_FEATURE_UDHCP_PORT(" [-P PORT]")" [-s PROG] [-p PIDFILE]\n" | 1165 | //usage: " [-i IFACE]"IF_FEATURE_UDHCP_PORT(" [-P PORT]")" [-s PROG] [-p PIDFILE]\n" |
1172 | //usage: " [-oC] [-r IP] [-V VENDOR] [-F NAME] [-x OPT:VAL]... [-O OPT]..." | 1166 | //usage: " [-oC] [-r IP] [-V VENDOR] [-F NAME] [-x OPT:VAL]... [-O OPT]..." |
1173 | //usage:#define udhcpc_full_usage "\n" | 1167 | //usage:#define udhcpc_full_usage "\n" |
@@ -1224,9 +1218,8 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv) | |||
1224 | int tryagain_timeout = 20; | 1218 | int tryagain_timeout = 20; |
1225 | int discover_timeout = 3; | 1219 | int discover_timeout = 3; |
1226 | int discover_retries = 3; | 1220 | int discover_retries = 3; |
1227 | uint32_t server_addr = server_addr; /* for compiler */ | 1221 | uint32_t server_id = server_id; /* for compiler */ |
1228 | uint32_t requested_ip = 0; | 1222 | uint32_t requested_ip = 0; |
1229 | uint32_t xid = xid; /* for compiler */ | ||
1230 | int packet_num; | 1223 | int packet_num; |
1231 | int timeout; /* must be signed */ | 1224 | int timeout; /* must be signed */ |
1232 | int lease_remaining; /* must be signed */ | 1225 | int lease_remaining; /* must be signed */ |
@@ -1291,7 +1284,8 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv) | |||
1291 | memcpy(p + OPT_DATA + 3, str_F, len); /* do not store NUL byte */ | 1284 | memcpy(p + OPT_DATA + 3, str_F, len); /* do not store NUL byte */ |
1292 | } | 1285 | } |
1293 | if (opt & OPT_r) | 1286 | if (opt & OPT_r) |
1294 | requested_ip = inet_addr(str_r); | 1287 | if (!inet_aton(str_r, (void*)&requested_ip)) |
1288 | bb_show_usage(); | ||
1295 | #if ENABLE_FEATURE_UDHCP_PORT | 1289 | #if ENABLE_FEATURE_UDHCP_PORT |
1296 | if (opt & OPT_P) { | 1290 | if (opt & OPT_P) { |
1297 | CLIENT_PORT = xatou16(str_P); | 1291 | CLIENT_PORT = xatou16(str_P); |
@@ -1451,10 +1445,10 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv) | |||
1451 | if (!discover_retries || packet_num < discover_retries) { | 1445 | if (!discover_retries || packet_num < discover_retries) { |
1452 | if (packet_num == 0) { | 1446 | if (packet_num == 0) { |
1453 | change_listen_mode(LISTEN_RAW); | 1447 | change_listen_mode(LISTEN_RAW); |
1454 | xid = random_xid(); | 1448 | client_data.xid = random_xid(); |
1455 | } | 1449 | } |
1456 | /* broadcast */ | 1450 | /* broadcast */ |
1457 | send_discover(xid, requested_ip); | 1451 | send_discover(requested_ip); |
1458 | timeout = discover_timeout; | 1452 | timeout = discover_timeout; |
1459 | packet_num++; | 1453 | packet_num++; |
1460 | continue; | 1454 | continue; |
@@ -1488,7 +1482,7 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv) | |||
1488 | case REQUESTING: | 1482 | case REQUESTING: |
1489 | if (packet_num < 3) { | 1483 | if (packet_num < 3) { |
1490 | /* send broadcast select packet */ | 1484 | /* send broadcast select packet */ |
1491 | send_select(xid, server_addr, requested_ip); | 1485 | send_select(server_id, requested_ip); |
1492 | timeout = discover_timeout; | 1486 | timeout = discover_timeout; |
1493 | packet_num++; | 1487 | packet_num++; |
1494 | continue; | 1488 | continue; |
@@ -1519,7 +1513,7 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv) | |||
1519 | * Anyway, it does recover by eventually failing through | 1513 | * Anyway, it does recover by eventually failing through |
1520 | * into INIT_SELECTING state. | 1514 | * into INIT_SELECTING state. |
1521 | */ | 1515 | */ |
1522 | if (send_renew(xid, server_addr, requested_ip) >= 0) { | 1516 | if (send_renew(server_id, requested_ip) >= 0) { |
1523 | timeout = discover_timeout; | 1517 | timeout = discover_timeout; |
1524 | packet_num++; | 1518 | packet_num++; |
1525 | continue; | 1519 | continue; |
@@ -1548,7 +1542,7 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv) | |||
1548 | * try to find DHCP server using broadcast */ | 1542 | * try to find DHCP server using broadcast */ |
1549 | if (lease_remaining > 0 && packet_num < 3) { | 1543 | if (lease_remaining > 0 && packet_num < 3) { |
1550 | /* send a broadcast renew request */ | 1544 | /* send a broadcast renew request */ |
1551 | send_renew(xid, 0 /*INADDR_ANY*/, requested_ip); | 1545 | send_renew(0 /*INADDR_ANY*/, requested_ip); |
1552 | timeout = discover_timeout; | 1546 | timeout = discover_timeout; |
1553 | packet_num++; | 1547 | packet_num++; |
1554 | continue; | 1548 | continue; |
@@ -1610,7 +1604,7 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv) | |||
1610 | timeout = 0; | 1604 | timeout = 0; |
1611 | continue; | 1605 | continue; |
1612 | case SIGUSR2: | 1606 | case SIGUSR2: |
1613 | perform_release(server_addr, requested_ip); | 1607 | perform_release(server_id, requested_ip); |
1614 | /* ^^^ switches to LISTEN_NONE */ | 1608 | /* ^^^ switches to LISTEN_NONE */ |
1615 | timeout = INT_MAX; | 1609 | timeout = INT_MAX; |
1616 | continue; | 1610 | continue; |
@@ -1641,9 +1635,9 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv) | |||
1641 | continue; | 1635 | continue; |
1642 | } | 1636 | } |
1643 | 1637 | ||
1644 | if (packet.xid != xid) { | 1638 | if (packet.xid != client_data.xid) { |
1645 | log1("xid %x (our is %x)%s", | 1639 | log1("xid %x (our is %x)%s", |
1646 | (unsigned)packet.xid, (unsigned)xid, | 1640 | (unsigned)packet.xid, (unsigned)client_data.xid, |
1647 | ", ignoring packet" | 1641 | ", ignoring packet" |
1648 | ); | 1642 | ); |
1649 | continue; | 1643 | continue; |
@@ -1695,13 +1689,13 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv) | |||
1695 | * They either supply DHCP_SERVER_ID of 0.0.0.0 or don't supply it at all. | 1689 | * They either supply DHCP_SERVER_ID of 0.0.0.0 or don't supply it at all. |
1696 | * They say ISC DHCP client supports this case. | 1690 | * They say ISC DHCP client supports this case. |
1697 | */ | 1691 | */ |
1698 | server_addr = 0; | 1692 | server_id = 0; |
1699 | temp = udhcp_get_option32(&packet, DHCP_SERVER_ID); | 1693 | temp = udhcp_get_option32(&packet, DHCP_SERVER_ID); |
1700 | if (!temp) { | 1694 | if (!temp) { |
1701 | bb_simple_info_msg("no server ID, using 0.0.0.0"); | 1695 | bb_simple_info_msg("no server ID, using 0.0.0.0"); |
1702 | } else { | 1696 | } else { |
1703 | /* it IS unaligned sometimes, don't "optimize" */ | 1697 | /* it IS unaligned sometimes, don't "optimize" */ |
1704 | move_from_unaligned32(server_addr, temp); | 1698 | move_from_unaligned32(server_id, temp); |
1705 | } | 1699 | } |
1706 | /*xid = packet.xid; - already is */ | 1700 | /*xid = packet.xid; - already is */ |
1707 | temp_addr.s_addr = requested_ip = packet.yiaddr; | 1701 | temp_addr.s_addr = requested_ip = packet.yiaddr; |
@@ -1725,7 +1719,7 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv) | |||
1725 | 1719 | ||
1726 | change_listen_mode(LISTEN_NONE); | 1720 | change_listen_mode(LISTEN_NONE); |
1727 | 1721 | ||
1728 | temp_addr.s_addr = server_addr; | 1722 | temp_addr.s_addr = server_id; |
1729 | strcpy(server_str, inet_ntoa(temp_addr)); | 1723 | strcpy(server_str, inet_ntoa(temp_addr)); |
1730 | temp_addr.s_addr = packet.yiaddr; | 1724 | temp_addr.s_addr = packet.yiaddr; |
1731 | 1725 | ||
@@ -1772,7 +1766,8 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv) | |||
1772 | ) { | 1766 | ) { |
1773 | bb_simple_info_msg("offered address is in use " | 1767 | bb_simple_info_msg("offered address is in use " |
1774 | "(got ARP reply), declining"); | 1768 | "(got ARP reply), declining"); |
1775 | send_decline(/*xid,*/ server_addr, packet.yiaddr); | 1769 | client_data.xid = random_xid(); //TODO: can omit? |
1770 | send_decline(server_id, packet.yiaddr); | ||
1776 | 1771 | ||
1777 | if (client_data.state != REQUESTING) | 1772 | if (client_data.state != REQUESTING) |
1778 | d4_run_script_deconfig(); | 1773 | d4_run_script_deconfig(); |
@@ -1807,7 +1802,7 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv) | |||
1807 | timeout = (unsigned)lease_remaining / 2; | 1802 | timeout = (unsigned)lease_remaining / 2; |
1808 | client_data.state = BOUND; | 1803 | client_data.state = BOUND; |
1809 | /* make future renew packets use different xid */ | 1804 | /* make future renew packets use different xid */ |
1810 | /* xid = random_xid(); ...but why bother? */ | 1805 | /* client_data.xid = random_xid(); ...but why bother? */ |
1811 | packet_num = 0; | 1806 | packet_num = 0; |
1812 | continue; /* back to main loop */ | 1807 | continue; /* back to main loop */ |
1813 | } | 1808 | } |
@@ -1816,20 +1811,14 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv) | |||
1816 | * "wrong" server can reply first, with a NAK. | 1811 | * "wrong" server can reply first, with a NAK. |
1817 | * Do not interpret it as a NAK from "our" server. | 1812 | * Do not interpret it as a NAK from "our" server. |
1818 | */ | 1813 | */ |
1819 | if (server_addr != 0) { | 1814 | uint32_t svid = 0; /* we treat no server id as 0.0.0.0 */ |
1820 | uint32_t svid; | 1815 | uint8_t *temp = udhcp_get_option32(&packet, DHCP_SERVER_ID); |
1821 | uint8_t *temp; | 1816 | if (temp) |
1822 | |||
1823 | temp = udhcp_get_option32(&packet, DHCP_SERVER_ID); | ||
1824 | if (!temp) { | ||
1825 | non_matching_svid: | ||
1826 | log1("received DHCP NAK with wrong" | ||
1827 | " server ID%s", ", ignoring packet"); | ||
1828 | continue; | ||
1829 | } | ||
1830 | move_from_unaligned32(svid, temp); | 1817 | move_from_unaligned32(svid, temp); |
1831 | if (svid != server_addr) | 1818 | if (svid != server_id) { |
1832 | goto non_matching_svid; | 1819 | log1("received DHCP NAK with wrong" |
1820 | " server ID%s", ", ignoring packet"); | ||
1821 | continue; | ||
1833 | } | 1822 | } |
1834 | /* return to init state */ | 1823 | /* return to init state */ |
1835 | change_listen_mode(LISTEN_NONE); | 1824 | change_listen_mode(LISTEN_NONE); |
@@ -1853,7 +1842,7 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv) | |||
1853 | 1842 | ||
1854 | ret0: | 1843 | ret0: |
1855 | if (opt & OPT_R) /* release on quit */ | 1844 | if (opt & OPT_R) /* release on quit */ |
1856 | perform_release(server_addr, requested_ip); | 1845 | perform_release(server_id, requested_ip); |
1857 | retval = 0; | 1846 | retval = 0; |
1858 | ret: | 1847 | ret: |
1859 | /*if (client_data.pidfile) - remove_pidfile has its own check */ | 1848 | /*if (client_data.pidfile) - remove_pidfile has its own check */ |