diff options
Diffstat (limited to 'networking/udhcp/dhcpc.c')
-rw-r--r-- | networking/udhcp/dhcpc.c | 73 |
1 files changed, 39 insertions, 34 deletions
diff --git a/networking/udhcp/dhcpc.c b/networking/udhcp/dhcpc.c index cb85fa9e3..656295ff7 100644 --- a/networking/udhcp/dhcpc.c +++ b/networking/udhcp/dhcpc.c | |||
@@ -449,15 +449,16 @@ static char **fill_envp(struct dhcp_packet *packet) | |||
449 | 449 | ||
450 | memset(found_opts, 0, sizeof(found_opts)); | 450 | memset(found_opts, 0, sizeof(found_opts)); |
451 | 451 | ||
452 | /* We need 6 elements for: | 452 | /* We need 7 elements for: |
453 | * "interface=IFACE" | 453 | * "interface=IFACE" |
454 | * "ip=N.N.N.N" from packet->yiaddr | 454 | * "ip=N.N.N.N" from packet->yiaddr |
455 | * "giaddr=IP" from packet->gateway_nip (unless 0) | ||
455 | * "siaddr=IP" from packet->siaddr_nip (unless 0) | 456 | * "siaddr=IP" from packet->siaddr_nip (unless 0) |
456 | * "boot_file=FILE" from packet->file (unless overloaded) | 457 | * "boot_file=FILE" from packet->file (unless overloaded) |
457 | * "sname=SERVER_HOSTNAME" from packet->sname (unless overloaded) | 458 | * "sname=SERVER_HOSTNAME" from packet->sname (unless overloaded) |
458 | * terminating NULL | 459 | * terminating NULL |
459 | */ | 460 | */ |
460 | envc = 6; | 461 | envc = 7; |
461 | /* +1 element for each option, +2 for subnet option: */ | 462 | /* +1 element for each option, +2 for subnet option: */ |
462 | if (packet) { | 463 | if (packet) { |
463 | /* note: do not search for "pad" (0) and "end" (255) options */ | 464 | /* note: do not search for "pad" (0) and "end" (255) options */ |
@@ -493,9 +494,7 @@ static char **fill_envp(struct dhcp_packet *packet) | |||
493 | * uint16_t flags; // only one flag so far: bcast. Never set by server | 494 | * uint16_t flags; // only one flag so far: bcast. Never set by server |
494 | * uint32_t ciaddr; // client IP (usually == yiaddr. can it be different | 495 | * uint32_t ciaddr; // client IP (usually == yiaddr. can it be different |
495 | * // if during renew server wants to give us different IP?) | 496 | * // if during renew server wants to give us different IP?) |
496 | * uint32_t gateway_nip; // relay agent IP address | ||
497 | * uint8_t chaddr[16]; // link-layer client hardware address (MAC) | 497 | * uint8_t chaddr[16]; // link-layer client hardware address (MAC) |
498 | * TODO: export gateway_nip as $giaddr? | ||
499 | */ | 498 | */ |
500 | /* Most important one: yiaddr as $ip */ | 499 | /* Most important one: yiaddr as $ip */ |
501 | *curr = xmalloc(sizeof("ip=255.255.255.255")); | 500 | *curr = xmalloc(sizeof("ip=255.255.255.255")); |
@@ -507,6 +506,12 @@ static char **fill_envp(struct dhcp_packet *packet) | |||
507 | sprint_nip(*curr, "siaddr=", (uint8_t *) &packet->siaddr_nip); | 506 | sprint_nip(*curr, "siaddr=", (uint8_t *) &packet->siaddr_nip); |
508 | putenv(*curr++); | 507 | putenv(*curr++); |
509 | } | 508 | } |
509 | if (packet->gateway_nip) { | ||
510 | /* IP address of DHCP relay agent */ | ||
511 | *curr = xmalloc(sizeof("giaddr=255.255.255.255")); | ||
512 | sprint_nip(*curr, "giaddr=", (uint8_t *) &packet->gateway_nip); | ||
513 | putenv(*curr++); | ||
514 | } | ||
510 | if (!(overload & FILE_FIELD) && packet->file[0]) { | 515 | if (!(overload & FILE_FIELD) && packet->file[0]) { |
511 | /* watch out for invalid packets */ | 516 | /* watch out for invalid packets */ |
512 | *curr = xasprintf("boot_file=%."DHCP_PKT_FILE_LEN_STR"s", packet->file); | 517 | *curr = xasprintf("boot_file=%."DHCP_PKT_FILE_LEN_STR"s", packet->file); |
@@ -901,7 +906,7 @@ static NOINLINE int udhcp_recv_raw_packet(struct dhcp_packet *dhcp_pkt, int fd) | |||
901 | if (bytes < 0) { | 906 | if (bytes < 0) { |
902 | if (errno == EINTR) | 907 | if (errno == EINTR) |
903 | continue; | 908 | continue; |
904 | log1("packet read error, ignoring"); | 909 | log1s("packet read error, ignoring"); |
905 | /* NB: possible down interface, etc. Caller should pause. */ | 910 | /* NB: possible down interface, etc. Caller should pause. */ |
906 | return bytes; /* returns -1 */ | 911 | return bytes; /* returns -1 */ |
907 | } | 912 | } |
@@ -909,13 +914,13 @@ static NOINLINE int udhcp_recv_raw_packet(struct dhcp_packet *dhcp_pkt, int fd) | |||
909 | } | 914 | } |
910 | 915 | ||
911 | if (bytes < (int) (sizeof(packet.ip) + sizeof(packet.udp))) { | 916 | if (bytes < (int) (sizeof(packet.ip) + sizeof(packet.udp))) { |
912 | log1("packet is too short, ignoring"); | 917 | log1s("packet is too short, ignoring"); |
913 | return -2; | 918 | return -2; |
914 | } | 919 | } |
915 | 920 | ||
916 | if (bytes < ntohs(packet.ip.tot_len)) { | 921 | if (bytes < ntohs(packet.ip.tot_len)) { |
917 | /* packet is bigger than sizeof(packet), we did partial read */ | 922 | /* packet is bigger than sizeof(packet), we did partial read */ |
918 | log1("oversized packet, ignoring"); | 923 | log1s("oversized packet, ignoring"); |
919 | return -2; | 924 | return -2; |
920 | } | 925 | } |
921 | 926 | ||
@@ -930,7 +935,7 @@ static NOINLINE int udhcp_recv_raw_packet(struct dhcp_packet *dhcp_pkt, int fd) | |||
930 | /* || bytes > (int) sizeof(packet) - can't happen */ | 935 | /* || bytes > (int) sizeof(packet) - can't happen */ |
931 | || ntohs(packet.udp.len) != (uint16_t)(bytes - sizeof(packet.ip)) | 936 | || ntohs(packet.udp.len) != (uint16_t)(bytes - sizeof(packet.ip)) |
932 | ) { | 937 | ) { |
933 | log1("unrelated/bogus packet, ignoring"); | 938 | log1s("unrelated/bogus packet, ignoring"); |
934 | return -2; | 939 | return -2; |
935 | } | 940 | } |
936 | 941 | ||
@@ -938,7 +943,7 @@ static NOINLINE int udhcp_recv_raw_packet(struct dhcp_packet *dhcp_pkt, int fd) | |||
938 | check = packet.ip.check; | 943 | check = packet.ip.check; |
939 | packet.ip.check = 0; | 944 | packet.ip.check = 0; |
940 | if (check != inet_cksum((uint16_t *)&packet.ip, sizeof(packet.ip))) { | 945 | if (check != inet_cksum((uint16_t *)&packet.ip, sizeof(packet.ip))) { |
941 | log1("bad IP header checksum, ignoring"); | 946 | log1s("bad IP header checksum, ignoring"); |
942 | return -2; | 947 | return -2; |
943 | } | 948 | } |
944 | 949 | ||
@@ -963,13 +968,13 @@ static NOINLINE int udhcp_recv_raw_packet(struct dhcp_packet *dhcp_pkt, int fd) | |||
963 | check = packet.udp.check; | 968 | check = packet.udp.check; |
964 | packet.udp.check = 0; | 969 | packet.udp.check = 0; |
965 | if (check && check != inet_cksum((uint16_t *)&packet, bytes)) { | 970 | if (check && check != inet_cksum((uint16_t *)&packet, bytes)) { |
966 | log1("packet with bad UDP checksum received, ignoring"); | 971 | log1s("packet with bad UDP checksum received, ignoring"); |
967 | return -2; | 972 | return -2; |
968 | } | 973 | } |
969 | skip_udp_sum_check: | 974 | skip_udp_sum_check: |
970 | 975 | ||
971 | if (packet.data.cookie != htonl(DHCP_MAGIC)) { | 976 | if (packet.data.cookie != htonl(DHCP_MAGIC)) { |
972 | bb_info_msg("packet with bad magic, ignoring"); | 977 | bb_simple_info_msg("packet with bad magic, ignoring"); |
973 | return -2; | 978 | return -2; |
974 | } | 979 | } |
975 | 980 | ||
@@ -1017,7 +1022,7 @@ static int udhcp_raw_socket(int ifindex) | |||
1017 | * SOCK_DGRAM: remove link-layer headers on input (SOCK_RAW keeps them) | 1022 | * SOCK_DGRAM: remove link-layer headers on input (SOCK_RAW keeps them) |
1018 | * ETH_P_IP: want to receive only packets with IPv4 eth type | 1023 | * ETH_P_IP: want to receive only packets with IPv4 eth type |
1019 | */ | 1024 | */ |
1020 | log2("got raw socket fd"); | 1025 | log3("got raw socket fd %d", fd); |
1021 | 1026 | ||
1022 | memset(&sock, 0, sizeof(sock)); /* let's be deterministic */ | 1027 | memset(&sock, 0, sizeof(sock)); /* let's be deterministic */ |
1023 | sock.sll_family = AF_PACKET; | 1028 | sock.sll_family = AF_PACKET; |
@@ -1084,10 +1089,10 @@ static int udhcp_raw_socket(int ifindex) | |||
1084 | 1089 | ||
1085 | if (setsockopt_1(fd, SOL_PACKET, PACKET_AUXDATA) != 0) { | 1090 | if (setsockopt_1(fd, SOL_PACKET, PACKET_AUXDATA) != 0) { |
1086 | if (errno != ENOPROTOOPT) | 1091 | if (errno != ENOPROTOOPT) |
1087 | log1("can't set PACKET_AUXDATA on raw socket"); | 1092 | log1s("can't set PACKET_AUXDATA on raw socket"); |
1088 | } | 1093 | } |
1089 | 1094 | ||
1090 | log1("created raw socket"); | 1095 | log1s("created raw socket"); |
1091 | 1096 | ||
1092 | return fd; | 1097 | return fd; |
1093 | } | 1098 | } |
@@ -1115,7 +1120,7 @@ static void change_listen_mode(int new_mode) | |||
1115 | /* Called only on SIGUSR1 */ | 1120 | /* Called only on SIGUSR1 */ |
1116 | static void perform_renew(void) | 1121 | static void perform_renew(void) |
1117 | { | 1122 | { |
1118 | bb_info_msg("performing DHCP renew"); | 1123 | bb_simple_info_msg("performing DHCP renew"); |
1119 | switch (client_data.state) { | 1124 | switch (client_data.state) { |
1120 | case BOUND: | 1125 | case BOUND: |
1121 | change_listen_mode(LISTEN_KERNEL); | 1126 | change_listen_mode(LISTEN_KERNEL); |
@@ -1153,7 +1158,7 @@ static void perform_release(uint32_t server_addr, uint32_t requested_ip) | |||
1153 | inet_ntoa(temp_addr), buffer); | 1158 | inet_ntoa(temp_addr), buffer); |
1154 | send_release(server_addr, requested_ip); /* unicast */ | 1159 | send_release(server_addr, requested_ip); /* unicast */ |
1155 | } | 1160 | } |
1156 | bb_info_msg("entering released state"); | 1161 | bb_simple_info_msg("entering released state"); |
1157 | /* | 1162 | /* |
1158 | * We can be here on: SIGUSR2, | 1163 | * We can be here on: SIGUSR2, |
1159 | * or on exit (SIGTERM) and -R "release on quit" is specified. | 1164 | * or on exit (SIGTERM) and -R "release on quit" is specified. |
@@ -1271,6 +1276,10 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv) | |||
1271 | client_data.sockfd = -1; | 1276 | client_data.sockfd = -1; |
1272 | str_V = "udhcp "BB_VER; | 1277 | str_V = "udhcp "BB_VER; |
1273 | 1278 | ||
1279 | /* Make sure fd 0,1,2 are open */ | ||
1280 | /* Set up the signal pipe on fds 3,4 - must be before openlog() */ | ||
1281 | udhcp_sp_setup(); | ||
1282 | |||
1274 | /* Parse command line */ | 1283 | /* Parse command line */ |
1275 | opt = getopt32long(argv, "^" | 1284 | opt = getopt32long(argv, "^" |
1276 | /* O,x: list; -T,-t,-A take numeric param */ | 1285 | /* O,x: list; -T,-t,-A take numeric param */ |
@@ -1294,7 +1303,7 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv) | |||
1294 | ); | 1303 | ); |
1295 | if (opt & (OPT_h|OPT_H)) { | 1304 | if (opt & (OPT_h|OPT_H)) { |
1296 | //msg added 2011-11 | 1305 | //msg added 2011-11 |
1297 | bb_error_msg("option -h NAME is deprecated, use -x hostname:NAME"); | 1306 | bb_simple_error_msg("option -h NAME is deprecated, use -x hostname:NAME"); |
1298 | client_data.hostname = alloc_dhcp_option(DHCP_HOST_NAME, str_h, 0); | 1307 | client_data.hostname = alloc_dhcp_option(DHCP_HOST_NAME, str_h, 0); |
1299 | } | 1308 | } |
1300 | if (opt & OPT_F) { | 1309 | if (opt & OPT_F) { |
@@ -1385,14 +1394,10 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv) | |||
1385 | logmode |= LOGMODE_SYSLOG; | 1394 | logmode |= LOGMODE_SYSLOG; |
1386 | } | 1395 | } |
1387 | 1396 | ||
1388 | /* Make sure fd 0,1,2 are open */ | ||
1389 | bb_sanitize_stdio(); | ||
1390 | /* Create pidfile */ | 1397 | /* Create pidfile */ |
1391 | write_pidfile(client_data.pidfile); | 1398 | write_pidfile(client_data.pidfile); |
1392 | /* Goes to stdout (unless NOMMU) and possibly syslog */ | 1399 | /* Goes to stdout (unless NOMMU) and possibly syslog */ |
1393 | bb_info_msg("started, v"BB_VER); | 1400 | bb_simple_info_msg("started, v"BB_VER); |
1394 | /* Set up the signal pipe */ | ||
1395 | udhcp_sp_setup(); | ||
1396 | /* We want random_xid to be random... */ | 1401 | /* We want random_xid to be random... */ |
1397 | srand(monotonic_us()); | 1402 | srand(monotonic_us()); |
1398 | 1403 | ||
@@ -1439,7 +1444,7 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv) | |||
1439 | continue; | 1444 | continue; |
1440 | } | 1445 | } |
1441 | /* Else: an error occurred, panic! */ | 1446 | /* Else: an error occurred, panic! */ |
1442 | bb_perror_msg_and_die("poll"); | 1447 | bb_simple_perror_msg_and_die("poll"); |
1443 | } | 1448 | } |
1444 | } | 1449 | } |
1445 | 1450 | ||
@@ -1480,7 +1485,7 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv) | |||
1480 | udhcp_run_script(NULL, "leasefail"); | 1485 | udhcp_run_script(NULL, "leasefail"); |
1481 | #if BB_MMU /* -b is not supported on NOMMU */ | 1486 | #if BB_MMU /* -b is not supported on NOMMU */ |
1482 | if (opt & OPT_b) { /* background if no lease */ | 1487 | if (opt & OPT_b) { /* background if no lease */ |
1483 | bb_info_msg("no lease, forking to background"); | 1488 | bb_simple_info_msg("no lease, forking to background"); |
1484 | client_background(); | 1489 | client_background(); |
1485 | /* do not background again! */ | 1490 | /* do not background again! */ |
1486 | opt = ((opt & ~(OPT_b|OPT_n)) | OPT_f); | 1491 | opt = ((opt & ~(OPT_b|OPT_n)) | OPT_f); |
@@ -1493,7 +1498,7 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv) | |||
1493 | } else | 1498 | } else |
1494 | #endif | 1499 | #endif |
1495 | if (opt & OPT_n) { /* abort if no lease */ | 1500 | if (opt & OPT_n) { /* abort if no lease */ |
1496 | bb_info_msg("no lease, failing"); | 1501 | bb_simple_info_msg("no lease, failing"); |
1497 | retval = 1; | 1502 | retval = 1; |
1498 | goto ret; | 1503 | goto ret; |
1499 | } | 1504 | } |
@@ -1521,7 +1526,7 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv) | |||
1521 | client_data.state = RENEWING; | 1526 | client_data.state = RENEWING; |
1522 | client_data.first_secs = 0; /* make secs field count from 0 */ | 1527 | client_data.first_secs = 0; /* make secs field count from 0 */ |
1523 | change_listen_mode(LISTEN_KERNEL); | 1528 | change_listen_mode(LISTEN_KERNEL); |
1524 | log1("entering renew state"); | 1529 | log1s("entering renew state"); |
1525 | /* fall right through */ | 1530 | /* fall right through */ |
1526 | case RENEW_REQUESTED: /* manual (SIGUSR1) renew */ | 1531 | case RENEW_REQUESTED: /* manual (SIGUSR1) renew */ |
1527 | case_RENEW_REQUESTED: | 1532 | case_RENEW_REQUESTED: |
@@ -1554,7 +1559,7 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv) | |||
1554 | */ | 1559 | */ |
1555 | } | 1560 | } |
1556 | /* Timed out or error, enter rebinding state */ | 1561 | /* Timed out or error, enter rebinding state */ |
1557 | log1("entering rebinding state"); | 1562 | log1s("entering rebinding state"); |
1558 | client_data.state = REBINDING; | 1563 | client_data.state = REBINDING; |
1559 | /* fall right through */ | 1564 | /* fall right through */ |
1560 | case REBINDING: | 1565 | case REBINDING: |
@@ -1569,7 +1574,7 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv) | |||
1569 | continue; | 1574 | continue; |
1570 | } | 1575 | } |
1571 | /* Timed out, enter init state */ | 1576 | /* Timed out, enter init state */ |
1572 | bb_info_msg("lease lost, entering init state"); | 1577 | bb_simple_info_msg("lease lost, entering init state"); |
1573 | udhcp_run_script(NULL, "deconfig"); | 1578 | udhcp_run_script(NULL, "deconfig"); |
1574 | client_data.state = INIT_SELECTING; | 1579 | client_data.state = INIT_SELECTING; |
1575 | client_data.first_secs = 0; /* make secs field count from 0 */ | 1580 | client_data.first_secs = 0; /* make secs field count from 0 */ |
@@ -1655,13 +1660,13 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv) | |||
1655 | || memcmp(packet.chaddr, client_data.client_mac, 6) != 0 | 1660 | || memcmp(packet.chaddr, client_data.client_mac, 6) != 0 |
1656 | ) { | 1661 | ) { |
1657 | //FIXME: need to also check that last 10 bytes are zero | 1662 | //FIXME: need to also check that last 10 bytes are zero |
1658 | log1("chaddr does not match, ignoring packet"); // log2? | 1663 | log1("chaddr does not match%s", ", ignoring packet"); // log2? |
1659 | continue; | 1664 | continue; |
1660 | } | 1665 | } |
1661 | 1666 | ||
1662 | message = udhcp_get_option(&packet, DHCP_MESSAGE_TYPE); | 1667 | message = udhcp_get_option(&packet, DHCP_MESSAGE_TYPE); |
1663 | if (message == NULL) { | 1668 | if (message == NULL) { |
1664 | bb_info_msg("no message type option, ignoring packet"); | 1669 | bb_info_msg("no message type option%s", ", ignoring packet"); |
1665 | continue; | 1670 | continue; |
1666 | } | 1671 | } |
1667 | 1672 | ||
@@ -1698,7 +1703,7 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv) | |||
1698 | server_addr = 0; | 1703 | server_addr = 0; |
1699 | temp = udhcp_get_option32(&packet, DHCP_SERVER_ID); | 1704 | temp = udhcp_get_option32(&packet, DHCP_SERVER_ID); |
1700 | if (!temp) { | 1705 | if (!temp) { |
1701 | bb_info_msg("no server ID, using 0.0.0.0"); | 1706 | bb_simple_info_msg("no server ID, using 0.0.0.0"); |
1702 | } else { | 1707 | } else { |
1703 | /* it IS unaligned sometimes, don't "optimize" */ | 1708 | /* it IS unaligned sometimes, don't "optimize" */ |
1704 | move_from_unaligned32(server_addr, temp); | 1709 | move_from_unaligned32(server_addr, temp); |
@@ -1725,7 +1730,7 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv) | |||
1725 | 1730 | ||
1726 | temp = udhcp_get_option32(&packet, DHCP_LEASE_TIME); | 1731 | temp = udhcp_get_option32(&packet, DHCP_LEASE_TIME); |
1727 | if (!temp) { | 1732 | if (!temp) { |
1728 | bb_info_msg("no lease time with ACK, using 1 hour lease"); | 1733 | bb_simple_info_msg("no lease time with ACK, using 1 hour lease"); |
1729 | lease_seconds = 60 * 60; | 1734 | lease_seconds = 60 * 60; |
1730 | } else { | 1735 | } else { |
1731 | /* it IS unaligned sometimes, don't "optimize" */ | 1736 | /* it IS unaligned sometimes, don't "optimize" */ |
@@ -1758,7 +1763,7 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv) | |||
1758 | client_data.interface, | 1763 | client_data.interface, |
1759 | arpping_ms) | 1764 | arpping_ms) |
1760 | ) { | 1765 | ) { |
1761 | bb_info_msg("offered address is in use " | 1766 | bb_simple_info_msg("offered address is in use " |
1762 | "(got ARP reply), declining"); | 1767 | "(got ARP reply), declining"); |
1763 | send_decline(/*xid,*/ server_addr, packet.yiaddr); | 1768 | send_decline(/*xid,*/ server_addr, packet.yiaddr); |
1764 | 1769 | ||
@@ -1822,7 +1827,7 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv) | |||
1822 | if (!temp) { | 1827 | if (!temp) { |
1823 | non_matching_svid: | 1828 | non_matching_svid: |
1824 | log1("received DHCP NAK with wrong" | 1829 | log1("received DHCP NAK with wrong" |
1825 | " server ID, ignoring packet"); | 1830 | " server ID%s", ", ignoring packet"); |
1826 | continue; | 1831 | continue; |
1827 | } | 1832 | } |
1828 | move_from_unaligned32(svid, temp); | 1833 | move_from_unaligned32(svid, temp); |