diff options
Diffstat (limited to 'networking/udhcp/dhcpc.c')
-rw-r--r-- | networking/udhcp/dhcpc.c | 49 |
1 files changed, 37 insertions, 12 deletions
diff --git a/networking/udhcp/dhcpc.c b/networking/udhcp/dhcpc.c index 99d91bf70..55f21c187 100644 --- a/networking/udhcp/dhcpc.c +++ b/networking/udhcp/dhcpc.c | |||
@@ -1,7 +1,6 @@ | |||
1 | /* vi: set sw=4 ts=4: */ | 1 | /* vi: set sw=4 ts=4: */ |
2 | /* | 2 | /* |
3 | * udhcp client | 3 | * udhcp client |
4 | * | ||
5 | * Russ Dill <Russ.Dill@asu.edu> July 2001 | 4 | * Russ Dill <Russ.Dill@asu.edu> July 2001 |
6 | * | 5 | * |
7 | * This program is free software; you can redistribute it and/or modify | 6 | * This program is free software; you can redistribute it and/or modify |
@@ -694,10 +693,16 @@ static int raw_bcast_from_client_config_ifindex(struct dhcp_packet *packet, uint | |||
694 | 693 | ||
695 | static int bcast_or_ucast(struct dhcp_packet *packet, uint32_t ciaddr, uint32_t server) | 694 | static int bcast_or_ucast(struct dhcp_packet *packet, uint32_t ciaddr, uint32_t server) |
696 | { | 695 | { |
697 | if (server) | 696 | if (server) { |
697 | /* Without MSG_DONTROUTE, the packet was seen routed over | ||
698 | * _other interface_ if server ID is bogus (example: 1.1.1.1). | ||
699 | */ | ||
698 | return udhcp_send_kernel_packet(packet, | 700 | return udhcp_send_kernel_packet(packet, |
699 | ciaddr, CLIENT_PORT, | 701 | ciaddr, CLIENT_PORT, |
700 | server, SERVER_PORT); | 702 | server, SERVER_PORT, |
703 | /*send_flags: "to hosts only on directly connected networks" */ MSG_DONTROUTE | ||
704 | ); | ||
705 | } | ||
701 | return raw_bcast_from_client_config_ifindex(packet, ciaddr); | 706 | return raw_bcast_from_client_config_ifindex(packet, ciaddr); |
702 | } | 707 | } |
703 | 708 | ||
@@ -735,7 +740,7 @@ static NOINLINE int send_discover(uint32_t xid, uint32_t requested) | |||
735 | static NOINLINE int send_select(uint32_t xid, uint32_t server, uint32_t requested) | 740 | static NOINLINE int send_select(uint32_t xid, uint32_t server, uint32_t requested) |
736 | { | 741 | { |
737 | struct dhcp_packet packet; | 742 | struct dhcp_packet packet; |
738 | struct in_addr addr; | 743 | struct in_addr temp_addr; |
739 | 744 | ||
740 | /* | 745 | /* |
741 | * RFC 2131 4.3.2 DHCPREQUEST message | 746 | * RFC 2131 4.3.2 DHCPREQUEST message |
@@ -766,8 +771,8 @@ static NOINLINE int send_select(uint32_t xid, uint32_t server, uint32_t requeste | |||
766 | */ | 771 | */ |
767 | add_client_options(&packet); | 772 | add_client_options(&packet); |
768 | 773 | ||
769 | addr.s_addr = requested; | 774 | temp_addr.s_addr = requested; |
770 | bb_error_msg("sending select for %s", inet_ntoa(addr)); | 775 | bb_error_msg("sending select for %s", inet_ntoa(temp_addr)); |
771 | return raw_bcast_from_client_config_ifindex(&packet, INADDR_ANY); | 776 | return raw_bcast_from_client_config_ifindex(&packet, INADDR_ANY); |
772 | } | 777 | } |
773 | 778 | ||
@@ -776,6 +781,7 @@ static NOINLINE int send_select(uint32_t xid, uint32_t server, uint32_t requeste | |||
776 | static NOINLINE int send_renew(uint32_t xid, uint32_t server, uint32_t ciaddr) | 781 | static NOINLINE int send_renew(uint32_t xid, uint32_t server, uint32_t ciaddr) |
777 | { | 782 | { |
778 | struct dhcp_packet packet; | 783 | struct dhcp_packet packet; |
784 | struct in_addr temp_addr; | ||
779 | 785 | ||
780 | /* | 786 | /* |
781 | * RFC 2131 4.3.2 DHCPREQUEST message | 787 | * RFC 2131 4.3.2 DHCPREQUEST message |
@@ -806,7 +812,8 @@ static NOINLINE int send_renew(uint32_t xid, uint32_t server, uint32_t ciaddr) | |||
806 | */ | 812 | */ |
807 | add_client_options(&packet); | 813 | add_client_options(&packet); |
808 | 814 | ||
809 | bb_error_msg("sending %s", "renew"); | 815 | temp_addr.s_addr = server; |
816 | bb_error_msg("sending renew to %s", inet_ntoa(temp_addr)); | ||
810 | return bcast_or_ucast(&packet, ciaddr, server); | 817 | return bcast_or_ucast(&packet, ciaddr, server); |
811 | } | 818 | } |
812 | 819 | ||
@@ -1010,9 +1017,14 @@ static int udhcp_raw_socket(int ifindex) | |||
1010 | */ | 1017 | */ |
1011 | log2("got raw socket fd"); | 1018 | log2("got raw socket fd"); |
1012 | 1019 | ||
1020 | memset(&sock, 0, sizeof(sock)); /* let's be deterministic */ | ||
1013 | sock.sll_family = AF_PACKET; | 1021 | sock.sll_family = AF_PACKET; |
1014 | sock.sll_protocol = htons(ETH_P_IP); | 1022 | sock.sll_protocol = htons(ETH_P_IP); |
1015 | sock.sll_ifindex = ifindex; | 1023 | sock.sll_ifindex = ifindex; |
1024 | /*sock.sll_hatype = ARPHRD_???;*/ | ||
1025 | /*sock.sll_pkttype = PACKET_???;*/ | ||
1026 | /*sock.sll_halen = ???;*/ | ||
1027 | /*sock.sll_addr[8] = ???;*/ | ||
1016 | xbind(fd, (struct sockaddr *) &sock, sizeof(sock)); | 1028 | xbind(fd, (struct sockaddr *) &sock, sizeof(sock)); |
1017 | 1029 | ||
1018 | #if 0 /* Several users reported breakage when BPF filter is used */ | 1030 | #if 0 /* Several users reported breakage when BPF filter is used */ |
@@ -1519,11 +1531,24 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv) | |||
1519 | * Anyway, it does recover by eventually failing through | 1531 | * Anyway, it does recover by eventually failing through |
1520 | * into INIT_SELECTING state. | 1532 | * into INIT_SELECTING state. |
1521 | */ | 1533 | */ |
1522 | send_renew(xid, server_addr, requested_ip); | 1534 | if (send_renew(xid, server_addr, requested_ip) >= 0) { |
1523 | timeout >>= 1; | 1535 | timeout >>= 1; |
1524 | continue; | 1536 | //TODO: the timeout to receive an answer for our renew should not be selected |
1537 | //with "timeout = lease_seconds / 2; ...; timeout = timeout / 2": it is often huge. | ||
1538 | //Waiting e.g. 4*3600 seconds for a reply does not make sense | ||
1539 | //(if reply isn't coming, we keep an open socket for hours), | ||
1540 | //it should be something like 10 seconds. | ||
1541 | //Also, it's probably best to try sending renew in kernel mode a few (3-5) times | ||
1542 | //and fall back to raw mode if it does not work. | ||
1543 | continue; | ||
1544 | } | ||
1545 | /* else: error sending. | ||
1546 | * example: ENETUNREACH seen with server | ||
1547 | * which gave us bogus server ID 1.1.1.1 | ||
1548 | * which wasn't reachable (and probably did not exist). | ||
1549 | */ | ||
1525 | } | 1550 | } |
1526 | /* Timed out, enter rebinding state */ | 1551 | /* Timed out or error, enter rebinding state */ |
1527 | log1("entering rebinding state"); | 1552 | log1("entering rebinding state"); |
1528 | state = REBINDING; | 1553 | state = REBINDING; |
1529 | /* fall right through */ | 1554 | /* fall right through */ |
@@ -1605,7 +1630,7 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv) | |||
1605 | len = udhcp_recv_raw_packet(&packet, sockfd); | 1630 | len = udhcp_recv_raw_packet(&packet, sockfd); |
1606 | if (len == -1) { | 1631 | if (len == -1) { |
1607 | /* Error is severe, reopen socket */ | 1632 | /* Error is severe, reopen socket */ |
1608 | bb_error_msg("read error: %s, reopening socket", strerror(errno)); | 1633 | bb_error_msg("read error: "STRERROR_FMT", reopening socket" STRERROR_ERRNO); |
1609 | sleep(discover_timeout); /* 3 seconds by default */ | 1634 | sleep(discover_timeout); /* 3 seconds by default */ |
1610 | change_listen_mode(listen_mode); /* just close and reopen */ | 1635 | change_listen_mode(listen_mode); /* just close and reopen */ |
1611 | } | 1636 | } |