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.c73
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 */
1116static void perform_renew(void) 1121static 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);