aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--networking/udhcp/arpping.c121
-rw-r--r--networking/udhcp/clientpacket.c24
-rw-r--r--networking/udhcp/common.c24
-rw-r--r--networking/udhcp/common.h4
-rw-r--r--networking/udhcp/dhcpc.c39
-rw-r--r--networking/udhcp/dhcpc.h12
-rw-r--r--networking/udhcp/dhcpd.c20
-rw-r--r--networking/udhcp/dhcpd.h46
-rw-r--r--networking/udhcp/files.c11
-rw-r--r--networking/udhcp/leases.c27
-rw-r--r--networking/udhcp/packet.c34
11 files changed, 177 insertions, 185 deletions
diff --git a/networking/udhcp/arpping.c b/networking/udhcp/arpping.c
index 615a91172..4ac52c640 100644
--- a/networking/udhcp/arpping.c
+++ b/networking/udhcp/arpping.c
@@ -15,44 +15,36 @@
15 15
16struct arpMsg { 16struct arpMsg {
17 /* Ethernet header */ 17 /* Ethernet header */
18 uint8_t h_dest[6]; /* destination ether addr */ 18 uint8_t h_dest[6]; /* 00 destination ether addr */
19 uint8_t h_source[6]; /* source ether addr */ 19 uint8_t h_source[6]; /* 06 source ether addr */
20 uint16_t h_proto; /* packet type ID field */ 20 uint16_t h_proto; /* 0c packet type ID field */
21 21
22 /* ARP packet */ 22 /* ARP packet */
23 uint16_t htype; /* hardware type (must be ARPHRD_ETHER) */ 23 uint16_t htype; /* 0e hardware type (must be ARPHRD_ETHER) */
24 uint16_t ptype; /* protocol type (must be ETH_P_IP) */ 24 uint16_t ptype; /* 10 protocol type (must be ETH_P_IP) */
25 uint8_t hlen; /* hardware address length (must be 6) */ 25 uint8_t hlen; /* 12 hardware address length (must be 6) */
26 uint8_t plen; /* protocol address length (must be 4) */ 26 uint8_t plen; /* 13 protocol address length (must be 4) */
27 uint16_t operation; /* ARP opcode */ 27 uint16_t operation; /* 14 ARP opcode */
28 uint8_t sHaddr[6]; /* sender's hardware address */ 28 uint8_t sHaddr[6]; /* 16 sender's hardware address */
29 uint8_t sInaddr[4]; /* sender's IP address */ 29 uint8_t sInaddr[4]; /* 1c sender's IP address */
30 uint8_t tHaddr[6]; /* target's hardware address */ 30 uint8_t tHaddr[6]; /* 20 target's hardware address */
31 uint8_t tInaddr[4]; /* target's IP address */ 31 uint8_t tInaddr[4]; /* 26 target's IP address */
32 uint8_t pad[18]; /* pad for min. Ethernet payload (60 bytes) */ 32 uint8_t pad[18]; /* 2a pad for min. ethernet payload (60 bytes) */
33} ATTRIBUTE_PACKED; 33} ATTRIBUTE_PACKED;
34 34
35/* args: yiaddr - what IP to ping
36 * ip - our ip
37 * mac - our arp address
38 * interface - interface to use
39 * retn: 1 addr free
40 * 0 addr used
41 * -1 error
42 */
43 35
44/* FIXME: match response against chaddr */ 36/* Returns 1 if no reply received */
45int arpping(uint32_t yiaddr, uint32_t ip, uint8_t *mac, char *interface)
46{
47 int timeout = 2;
48 int s; /* socket */
49 int rv = 1; /* return value */
50 struct sockaddr addr; /* for interface name */
51 struct arpMsg arp;
52 fd_set fdset;
53 struct timeval tm;
54 time_t prevTime;
55 37
38int arpping(uint32_t test_ip, uint32_t from_ip, uint8_t *from_mac, const char *interface)
39{
40 int timeout = 2;
41 int s; /* socket */
42 int rv = 1; /* "no reply received" yet */
43 struct sockaddr addr; /* for interface name */
44 struct arpMsg arp;
45 fd_set fdset;
46 struct timeval tm;
47 unsigned prevTime;
56 48
57 s = socket(PF_PACKET, SOCK_PACKET, htons(ETH_P_ARP)); 49 s = socket(PF_PACKET, SOCK_PACKET, htons(ETH_P_ARP));
58 if (s == -1) { 50 if (s == -1) {
@@ -62,55 +54,58 @@ int arpping(uint32_t yiaddr, uint32_t ip, uint8_t *mac, char *interface)
62 54
63 if (setsockopt_broadcast(s) == -1) { 55 if (setsockopt_broadcast(s) == -1) {
64 bb_perror_msg("cannot setsocketopt on raw socket"); 56 bb_perror_msg("cannot setsocketopt on raw socket");
65 close(s); 57 goto ret;
66 return -1;
67 } 58 }
68 59
69 /* send arp request */ 60 /* send arp request */
70 memset(&arp, 0, sizeof(arp)); 61 memset(&arp, 0, sizeof(arp));
71 memcpy(arp.h_dest, MAC_BCAST_ADDR, 6); /* MAC DA */ 62 memset(arp.h_dest, 0xff, 6); /* MAC DA */
72 memcpy(arp.h_source, mac, 6); /* MAC SA */ 63 memcpy(arp.h_source, from_mac, 6); /* MAC SA */
73 arp.h_proto = htons(ETH_P_ARP); /* protocol type (Ethernet) */ 64 arp.h_proto = htons(ETH_P_ARP); /* protocol type (Ethernet) */
74 arp.htype = htons(ARPHRD_ETHER); /* hardware type */ 65 arp.htype = htons(ARPHRD_ETHER); /* hardware type */
75 arp.ptype = htons(ETH_P_IP); /* protocol type (ARP message) */ 66 arp.ptype = htons(ETH_P_IP); /* protocol type (ARP message) */
76 arp.hlen = 6; /* hardware address length */ 67 arp.hlen = 6; /* hardware address length */
77 arp.plen = 4; /* protocol address length */ 68 arp.plen = 4; /* protocol address length */
78 arp.operation = htons(ARPOP_REQUEST); /* ARP op code */ 69 arp.operation = htons(ARPOP_REQUEST); /* ARP op code */
79 memcpy(arp.sInaddr, &ip, sizeof(ip)); /* source IP address */ 70 memcpy(arp.sHaddr, from_mac, 6); /* source hardware address */
80 memcpy(arp.sHaddr, mac, 6); /* source hardware address */ 71 memcpy(arp.sInaddr, &from_ip, sizeof(from_ip)); /* source IP address */
81 memcpy(arp.tInaddr, &yiaddr, sizeof(yiaddr)); /* target IP address */ 72 /* tHaddr */ /* target hardware address */
73 memcpy(arp.tInaddr, &test_ip, sizeof(test_ip)); /* target IP address */
82 74
83 memset(&addr, 0, sizeof(addr)); 75 memset(&addr, 0, sizeof(addr));
84 strcpy(addr.sa_data, interface); 76 safe_strncpy(addr.sa_data, interface, sizeof(addr.sa_data));
85 if (sendto(s, &arp, sizeof(arp), 0, &addr, sizeof(addr)) < 0) 77 if (sendto(s, &arp, sizeof(arp), 0, &addr, sizeof(addr)) < 0)
86 rv = 0; 78 goto ret;
87 79
88 /* wait arp reply, and check it */ 80 /* wait for arp reply, and check it */
89 tm.tv_usec = 0; 81 do {
90 prevTime = uptime(); 82 int r;
91 while (timeout > 0) { 83 prevTime = monotonic_sec();
92 FD_ZERO(&fdset); 84 FD_ZERO(&fdset);
93 FD_SET(s, &fdset); 85 FD_SET(s, &fdset);
94 tm.tv_sec = timeout; 86 tm.tv_sec = timeout;
95 if (select(s + 1, &fdset, (fd_set *) NULL, (fd_set *) NULL, &tm) < 0) { 87 tm.tv_usec = 0;
88 r = select(s + 1, &fdset, NULL, NULL, &tm);
89 if (r < 0) {
96 bb_perror_msg("error on ARPING request"); 90 bb_perror_msg("error on ARPING request");
97 if (errno != EINTR) 91 if (errno != EINTR)
98 rv = 0; 92 break;
99 } else if (FD_ISSET(s, &fdset)) { 93 } else if (r) {
100 if (recv(s, &arp, sizeof(arp), 0) < 0) 94 if (recv(s, &arp, sizeof(arp), 0) < 0)
101 rv = 0; 95 break;
102 if (arp.operation == htons(ARPOP_REPLY) && 96 if (arp.operation == htons(ARPOP_REPLY)
103 memcmp(arp.tHaddr, mac, 6) == 0 && 97 && memcmp(arp.tHaddr, from_mac, 6) == 0
104 *((uint32_t *) arp.sInaddr) == yiaddr) { 98 && *((uint32_t *) arp.sInaddr) == test_ip
105 DEBUG("Valid arp reply received for this address"); 99 ) {
106 rv = 0; 100 rv = 0;
107 break; 101 break;
108 } 102 }
109 } 103 }
110 timeout -= uptime() - prevTime; 104 timeout -= monotonic_sec() - prevTime;
111 prevTime = uptime(); 105 } while (timeout > 0);
112 } 106
107 ret:
113 close(s); 108 close(s);
114 DEBUG("%salid arp replies for this address", rv ? "No v" : "V"); 109 DEBUG("%srp reply received for this address", rv ? "No a" : "A");
115 return rv; 110 return rv;
116} 111}
diff --git a/networking/udhcp/clientpacket.c b/networking/udhcp/clientpacket.c
index af97962a0..42b4895e5 100644
--- a/networking/udhcp/clientpacket.c
+++ b/networking/udhcp/clientpacket.c
@@ -25,7 +25,7 @@
25 25
26 26
27/* Create a random xid */ 27/* Create a random xid */
28unsigned random_xid(void) 28uint32_t random_xid(void)
29{ 29{
30 static smallint initialized; 30 static smallint initialized;
31 31
@@ -44,8 +44,10 @@ static void init_packet(struct dhcpMessage *packet, char type)
44 memcpy(packet->chaddr, client_config.arp, 6); 44 memcpy(packet->chaddr, client_config.arp, 6);
45 if (client_config.clientid) 45 if (client_config.clientid)
46 add_option_string(packet->options, client_config.clientid); 46 add_option_string(packet->options, client_config.clientid);
47 if (client_config.hostname) add_option_string(packet->options, client_config.hostname); 47 if (client_config.hostname)
48 if (client_config.fqdn) add_option_string(packet->options, client_config.fqdn); 48 add_option_string(packet->options, client_config.hostname);
49 if (client_config.fqdn)
50 add_option_string(packet->options, client_config.fqdn);
49 add_option_string(packet->options, client_config.vendorclass); 51 add_option_string(packet->options, client_config.vendorclass);
50} 52}
51 53
@@ -69,7 +71,7 @@ static void add_requests(struct dhcpMessage *packet)
69 71
70 72
71/* Broadcast a DHCP discover packet to the network, with an optionally requested IP */ 73/* Broadcast a DHCP discover packet to the network, with an optionally requested IP */
72int send_discover(unsigned long xid, unsigned long requested) 74int send_discover(uint32_t xid, uint32_t requested)
73{ 75{
74 struct dhcpMessage packet; 76 struct dhcpMessage packet;
75 77
@@ -86,7 +88,7 @@ int send_discover(unsigned long xid, unsigned long requested)
86 88
87 89
88/* Broadcasts a DHCP request message */ 90/* Broadcasts a DHCP request message */
89int send_selecting(unsigned long xid, unsigned long server, unsigned long requested) 91int send_selecting(uint32_t xid, uint32_t server, uint32_t requested)
90{ 92{
91 struct dhcpMessage packet; 93 struct dhcpMessage packet;
92 struct in_addr addr; 94 struct in_addr addr;
@@ -106,10 +108,9 @@ int send_selecting(unsigned long xid, unsigned long server, unsigned long reques
106 108
107 109
108/* Unicasts or broadcasts a DHCP renew message */ 110/* Unicasts or broadcasts a DHCP renew message */
109int send_renew(unsigned long xid, unsigned long server, unsigned long ciaddr) 111int send_renew(uint32_t xid, uint32_t server, uint32_t ciaddr)
110{ 112{
111 struct dhcpMessage packet; 113 struct dhcpMessage packet;
112 int ret = 0;
113 114
114 init_packet(&packet, DHCPREQUEST); 115 init_packet(&packet, DHCPREQUEST);
115 packet.xid = xid; 116 packet.xid = xid;
@@ -118,15 +119,15 @@ int send_renew(unsigned long xid, unsigned long server, unsigned long ciaddr)
118 add_requests(&packet); 119 add_requests(&packet);
119 bb_info_msg("Sending renew..."); 120 bb_info_msg("Sending renew...");
120 if (server) 121 if (server)
121 ret = udhcp_kernel_packet(&packet, ciaddr, CLIENT_PORT, server, SERVER_PORT); 122 return udhcp_kernel_packet(&packet, ciaddr, CLIENT_PORT, server, SERVER_PORT);
122 else ret = udhcp_raw_packet(&packet, INADDR_ANY, CLIENT_PORT, INADDR_BROADCAST, 123
124 return udhcp_raw_packet(&packet, INADDR_ANY, CLIENT_PORT, INADDR_BROADCAST,
123 SERVER_PORT, MAC_BCAST_ADDR, client_config.ifindex); 125 SERVER_PORT, MAC_BCAST_ADDR, client_config.ifindex);
124 return ret;
125} 126}
126 127
127 128
128/* Unicasts a DHCP release message */ 129/* Unicasts a DHCP release message */
129int send_release(unsigned long server, unsigned long ciaddr) 130int send_release(uint32_t server, uint32_t ciaddr)
130{ 131{
131 struct dhcpMessage packet; 132 struct dhcpMessage packet;
132 133
@@ -214,5 +215,4 @@ int get_raw_packet(struct dhcpMessage *payload, int fd)
214 } 215 }
215 DEBUG("oooooh!!! got some!"); 216 DEBUG("oooooh!!! got some!");
216 return bytes - (sizeof(packet.ip) + sizeof(packet.udp)); 217 return bytes - (sizeof(packet.ip) + sizeof(packet.udp));
217
218} 218}
diff --git a/networking/udhcp/common.c b/networking/udhcp/common.c
index 76f8bf703..108ab2e95 100644
--- a/networking/udhcp/common.c
+++ b/networking/udhcp/common.c
@@ -10,31 +10,10 @@
10 * Licensed under GPLv2 or later, see file LICENSE in this tarball for details. 10 * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
11 */ 11 */
12 12
13#include <syslog.h>
14
15#include "common.h" 13#include "common.h"
16 14
17
18const uint8_t MAC_BCAST_ADDR[6] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; 15const uint8_t MAC_BCAST_ADDR[6] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
19 16
20long uptime(void)
21{
22 struct sysinfo info;
23 sysinfo(&info);
24 return info.uptime;
25}
26
27static void create_pidfile(const char *pidfile)
28{
29 if (!pidfile)
30 return;
31
32 if (!write_pidfile(pidfile)) {
33 bb_perror_msg("cannot create pidfile %s", pidfile);
34 return;
35 }
36}
37
38void udhcp_make_pidfile(const char *pidfile) 17void udhcp_make_pidfile(const char *pidfile)
39{ 18{
40 /* Make sure fd 0,1,2 are open */ 19 /* Make sure fd 0,1,2 are open */
@@ -44,7 +23,8 @@ void udhcp_make_pidfile(const char *pidfile)
44 setlinebuf(stdout); 23 setlinebuf(stdout);
45 24
46 /* Create pidfile */ 25 /* Create pidfile */
47 create_pidfile(pidfile); 26 if (pidfile && !write_pidfile(pidfile))
27 bb_perror_msg("cannot create pidfile %s", pidfile);
48 28
49 bb_info_msg("%s (v%s) started", applet_name, BB_VER); 29 bb_info_msg("%s (v%s) started", applet_name, BB_VER);
50} 30}
diff --git a/networking/udhcp/common.h b/networking/udhcp/common.h
index 006d580d3..588750462 100644
--- a/networking/udhcp/common.h
+++ b/networking/udhcp/common.h
@@ -80,14 +80,14 @@ void udhcp_run_script(struct dhcpMessage *packet, const char *name);
80/* from dhcpd.h */ 80/* from dhcpd.h */
81#define server_config udhcp_server_config 81#define server_config udhcp_server_config
82 82
83long uptime(void);
84void udhcp_sp_setup(void); 83void udhcp_sp_setup(void);
85int udhcp_sp_fd_set(fd_set *rfds, int extra_fd); 84int udhcp_sp_fd_set(fd_set *rfds, int extra_fd);
86int udhcp_sp_read(fd_set *rfds); 85int udhcp_sp_read(fd_set *rfds);
87int raw_socket(int ifindex); 86int raw_socket(int ifindex);
88int read_interface(const char *interface, int *ifindex, uint32_t *addr, uint8_t *arp); 87int read_interface(const char *interface, int *ifindex, uint32_t *addr, uint8_t *arp);
89int listen_socket(uint32_t ip, int port, const char *inf); 88int listen_socket(uint32_t ip, int port, const char *inf);
90int arpping(uint32_t yiaddr, uint32_t ip, uint8_t *arp, char *interface); 89/* Returns 1 if no reply received */
90int arpping(uint32_t test_ip, uint32_t from_ip, uint8_t *from_mac, const char *interface);
91 91
92#if ENABLE_FEATURE_UDHCP_DEBUG 92#if ENABLE_FEATURE_UDHCP_DEBUG
93# define DEBUG(str, args...) bb_info_msg(str, ## args) 93# define DEBUG(str, args...) bb_info_msg(str, ## args)
diff --git a/networking/udhcp/dhcpc.c b/networking/udhcp/dhcpc.c
index 50ac31e61..6909e8489 100644
--- a/networking/udhcp/dhcpc.c
+++ b/networking/udhcp/dhcpc.c
@@ -22,8 +22,8 @@
22 * in the code. Manpage says that struct in_addr has a member of type long (!) 22 * in the code. Manpage says that struct in_addr has a member of type long (!)
23 * which holds IPv4 address, and the struct is passed by value (!!) 23 * which holds IPv4 address, and the struct is passed by value (!!)
24 */ 24 */
25static unsigned long timeout; 25static unsigned timeout;
26static unsigned long requested_ip; /* = 0 */ 26static uint32_t requested_ip; /* = 0 */
27static uint32_t server_addr; 27static uint32_t server_addr;
28static int packet_num; /* = 0 */ 28static int packet_num; /* = 0 */
29static int sockfd = -1; 29static int sockfd = -1;
@@ -84,13 +84,13 @@ static void perform_renew(void)
84/* perform a release */ 84/* perform a release */
85static void perform_release(void) 85static void perform_release(void)
86{ 86{
87 char buffer[16]; 87 char buffer[sizeof("255.255.255.255")];
88 struct in_addr temp_addr; 88 struct in_addr temp_addr;
89 89
90 /* send release packet */ 90 /* send release packet */
91 if (state == BOUND || state == RENEWING || state == REBINDING) { 91 if (state == BOUND || state == RENEWING || state == REBINDING) {
92 temp_addr.s_addr = server_addr; 92 temp_addr.s_addr = server_addr;
93 sprintf(buffer, "%s", inet_ntoa(temp_addr)); 93 strcpy(buffer, inet_ntoa(temp_addr));
94 temp_addr.s_addr = requested_ip; 94 temp_addr.s_addr = requested_ip;
95 bb_info_msg("Unicasting a release of %s to %s", 95 bb_info_msg("Unicasting a release of %s to %s",
96 inet_ntoa(temp_addr), buffer); 96 inet_ntoa(temp_addr), buffer);
@@ -101,7 +101,7 @@ static void perform_release(void)
101 101
102 change_mode(LISTEN_NONE); 102 change_mode(LISTEN_NONE);
103 state = RELEASED; 103 state = RELEASED;
104 timeout = 0x7fffffff; 104 timeout = INT_MAX;
105} 105}
106 106
107 107
@@ -115,12 +115,13 @@ static void client_background(void)
115 * will work on NOMMU too */ 115 * will work on NOMMU too */
116#else 116#else
117 bb_daemonize(0); 117 bb_daemonize(0);
118 logmode &= ~LOGMODE_STDIO;
118 /* rewrite pidfile, as our pid is different now */ 119 /* rewrite pidfile, as our pid is different now */
119 if (client_config.pidfile) 120 if (client_config.pidfile)
120 write_pidfile(client_config.pidfile); 121 write_pidfile(client_config.pidfile);
121 logmode &= ~LOGMODE_STDIO;
122#endif 122#endif
123 client_config.foreground = 1; /* Do not fork again. */ 123 /* Do not fork again. */
124 client_config.foreground = 1;
124 client_config.background_if_no_lease = 0; 125 client_config.background_if_no_lease = 0;
125} 126}
126 127
@@ -143,9 +144,11 @@ int udhcpc_main(int argc, char **argv)
143{ 144{
144 uint8_t *temp, *message; 145 uint8_t *temp, *message;
145 char *str_c, *str_V, *str_h, *str_F, *str_r, *str_T, *str_t; 146 char *str_c, *str_V, *str_h, *str_F, *str_r, *str_T, *str_t;
146 unsigned long t1 = 0, t2 = 0, xid = 0; 147 uint32_t xid = 0;
147 unsigned long start = 0, lease = 0; 148 uint32_t lease = 0; /* can be given as 32-bit quantity */
148 long now; 149 unsigned t1 = 0, t2 = 0;
150 unsigned start = 0;
151 unsigned now;
149 unsigned opt; 152 unsigned opt;
150 int max_fd; 153 int max_fd;
151 int sig; 154 int sig;
@@ -292,7 +295,7 @@ int udhcpc_main(int argc, char **argv)
292 change_mode(LISTEN_RAW); 295 change_mode(LISTEN_RAW);
293 296
294 for (;;) { 297 for (;;) {
295 tv.tv_sec = timeout - uptime(); 298 tv.tv_sec = timeout - monotonic_sec();
296 tv.tv_usec = 0; 299 tv.tv_usec = 0;
297 300
298 if (listen_mode != LISTEN_NONE && sockfd < 0) { 301 if (listen_mode != LISTEN_NONE && sockfd < 0) {
@@ -308,7 +311,7 @@ int udhcpc_main(int argc, char **argv)
308 retval = select(max_fd + 1, &rfds, NULL, NULL, &tv); 311 retval = select(max_fd + 1, &rfds, NULL, NULL, &tv);
309 } else retval = 0; /* If we already timed out, fall through */ 312 } else retval = 0; /* If we already timed out, fall through */
310 313
311 now = uptime(); 314 now = monotonic_sec();
312 if (retval == 0) { 315 if (retval == 0) {
313 /* timeout dropped to zero */ 316 /* timeout dropped to zero */
314 switch (state) { 317 switch (state) {
@@ -398,7 +401,7 @@ int udhcpc_main(int argc, char **argv)
398 break; 401 break;
399 case RELEASED: 402 case RELEASED:
400 /* yah, I know, *you* say it would never happen */ 403 /* yah, I know, *you* say it would never happen */
401 timeout = 0x7fffffff; 404 timeout = INT_MAX;
402 break; 405 break;
403 } 406 }
404 } else if (retval > 0 && listen_mode != LISTEN_NONE && FD_ISSET(sockfd, &rfds)) { 407 } else if (retval > 0 && listen_mode != LISTEN_NONE && FD_ISSET(sockfd, &rfds)) {
@@ -415,8 +418,8 @@ int udhcpc_main(int argc, char **argv)
415 if (len < 0) continue; 418 if (len < 0) continue;
416 419
417 if (packet.xid != xid) { 420 if (packet.xid != xid) {
418 DEBUG("Ignoring XID %lx (our xid is %lx)", 421 DEBUG("Ignoring XID %x (our xid is %x)",
419 (unsigned long) packet.xid, xid); 422 (unsigned)packet.xid, (unsigned)xid);
420 continue; 423 continue;
421 } 424 }
422 425
@@ -471,10 +474,10 @@ int udhcpc_main(int argc, char **argv)
471 t1 = lease / 2; 474 t1 = lease / 2;
472 475
473 /* little fixed point for n * .875 */ 476 /* little fixed point for n * .875 */
474 t2 = (lease * 0x7) >> 3; 477 t2 = (lease * 7) >> 3;
475 temp_addr.s_addr = packet.yiaddr; 478 temp_addr.s_addr = packet.yiaddr;
476 bb_info_msg("Lease of %s obtained, lease time %ld", 479 bb_info_msg("Lease of %s obtained, lease time %u",
477 inet_ntoa(temp_addr), lease); 480 inet_ntoa(temp_addr), (unsigned)lease);
478 start = now; 481 start = now;
479 timeout = t1 + start; 482 timeout = t1 + start;
480 requested_ip = packet.yiaddr; 483 requested_ip = packet.yiaddr;
diff --git a/networking/udhcp/dhcpc.h b/networking/udhcp/dhcpc.h
index 09b014239..20f4e52b8 100644
--- a/networking/udhcp/dhcpc.h
+++ b/networking/udhcp/dhcpc.h
@@ -38,12 +38,12 @@ extern struct client_config_t client_config;
38 38
39/*** clientpacket.h ***/ 39/*** clientpacket.h ***/
40 40
41unsigned random_xid(void); 41uint32_t random_xid(void);
42int send_discover(unsigned long xid, unsigned long requested); 42int send_discover(uint32_t xid, uint32_t requested);
43int send_selecting(unsigned long xid, unsigned long server, unsigned long requested); 43int send_selecting(uint32_t xid, uint32_t server, uint32_t requested);
44int send_renew(unsigned long xid, unsigned long server, unsigned long ciaddr); 44int send_renew(uint32_t xid, uint32_t server, uint32_t ciaddr);
45int send_renew(unsigned long xid, unsigned long server, unsigned long ciaddr); 45int send_renew(uint32_t xid, uint32_t server, uint32_t ciaddr);
46int send_release(unsigned long server, unsigned long ciaddr); 46int send_release(uint32_t server, uint32_t ciaddr);
47int get_raw_packet(struct dhcpMessage *payload, int fd); 47int get_raw_packet(struct dhcpMessage *payload, int fd);
48 48
49 49
diff --git a/networking/udhcp/dhcpd.c b/networking/udhcp/dhcpd.c
index 9dbd35d4e..8cac68195 100644
--- a/networking/udhcp/dhcpd.c
+++ b/networking/udhcp/dhcpd.c
@@ -30,7 +30,8 @@ int udhcpd_main(int argc, char **argv)
30 struct dhcpMessage packet; 30 struct dhcpMessage packet;
31 uint8_t *state, *server_id, *requested; 31 uint8_t *state, *server_id, *requested;
32 uint32_t server_id_align, requested_align, static_lease_ip; 32 uint32_t server_id_align, requested_align, static_lease_ip;
33 unsigned long timeout_end, num_ips; 33 unsigned timeout_end;
34 unsigned num_ips;
34 struct option_set *option; 35 struct option_set *option;
35 struct dhcpOfferedAddr *lease, static_lease; 36 struct dhcpOfferedAddr *lease, static_lease;
36 37
@@ -48,7 +49,7 @@ int udhcpd_main(int argc, char **argv)
48 49
49 /* Would rather not do read_config before daemonization - 50 /* Would rather not do read_config before daemonization -
50 * otherwise NOMMU machines will parse config twice */ 51 * otherwise NOMMU machines will parse config twice */
51 read_config(argc < 2 ? DHCPD_CONF_FILE : argv[1]); 52 read_config(argv[1] ? argv[1] : DHCPD_CONF_FILE);
52 53
53 udhcp_make_pidfile(server_config.pidfile); 54 udhcp_make_pidfile(server_config.pidfile);
54 55
@@ -62,9 +63,8 @@ int udhcpd_main(int argc, char **argv)
62 /* Sanity check */ 63 /* Sanity check */
63 num_ips = server_config.end_ip - server_config.start_ip + 1; 64 num_ips = server_config.end_ip - server_config.start_ip + 1;
64 if (server_config.max_leases > num_ips) { 65 if (server_config.max_leases > num_ips) {
65 bb_error_msg("max_leases=%lu is too big, " 66 bb_error_msg("max_leases=%u is too big, setting to %u",
66 "setting to %lu", 67 (unsigned)server_config.max_leases, num_ips);
67 server_config.max_leases, num_ips);
68 server_config.max_leases = num_ips; 68 server_config.max_leases = num_ips;
69 } 69 }
70 70
@@ -80,7 +80,7 @@ int udhcpd_main(int argc, char **argv)
80 /* Setup the signal pipe */ 80 /* Setup the signal pipe */
81 udhcp_sp_setup(); 81 udhcp_sp_setup();
82 82
83 timeout_end = time(0) + server_config.auto_time; 83 timeout_end = monotonic_sec() + server_config.auto_time;
84 while (1) { /* loop until universe collapses */ 84 while (1) { /* loop until universe collapses */
85 85
86 if (server_socket < 0) { 86 if (server_socket < 0) {
@@ -90,7 +90,7 @@ int udhcpd_main(int argc, char **argv)
90 90
91 max_sock = udhcp_sp_fd_set(&rfds, server_socket); 91 max_sock = udhcp_sp_fd_set(&rfds, server_socket);
92 if (server_config.auto_time) { 92 if (server_config.auto_time) {
93 tv.tv_sec = timeout_end - time(0); 93 tv.tv_sec = timeout_end - monotonic_sec();
94 tv.tv_usec = 0; 94 tv.tv_usec = 0;
95 } 95 }
96 retval = 0; 96 retval = 0;
@@ -100,7 +100,7 @@ int udhcpd_main(int argc, char **argv)
100 } 100 }
101 if (retval == 0) { 101 if (retval == 0) {
102 write_leases(); 102 write_leases();
103 timeout_end = time(0) + server_config.auto_time; 103 timeout_end = monotonic_sec() + server_config.auto_time;
104 continue; 104 continue;
105 } 105 }
106 if (retval < 0 && errno != EINTR) { 106 if (retval < 0 && errno != EINTR) {
@@ -113,7 +113,7 @@ int udhcpd_main(int argc, char **argv)
113 bb_info_msg("Received a SIGUSR1"); 113 bb_info_msg("Received a SIGUSR1");
114 write_leases(); 114 write_leases();
115 /* why not just reset the timeout, eh */ 115 /* why not just reset the timeout, eh */
116 timeout_end = time(0) + server_config.auto_time; 116 timeout_end = monotonic_sec() + server_config.auto_time;
117 continue; 117 continue;
118 case SIGTERM: 118 case SIGTERM:
119 bb_info_msg("Received a SIGTERM"); 119 bb_info_msg("Received a SIGTERM");
@@ -244,7 +244,7 @@ int udhcpd_main(int argc, char **argv)
244 ret0: 244 ret0:
245 retval = 0; 245 retval = 0;
246 ret: 246 ret:
247 if (server_config.pidfile) 247 /*if (server_config.pidfile) - server_config.pidfile is never NULL */
248 remove_pidfile(server_config.pidfile); 248 remove_pidfile(server_config.pidfile);
249 return retval; 249 return retval;
250} 250}
diff --git a/networking/udhcp/dhcpd.h b/networking/udhcp/dhcpd.h
index 05e3cf004..fc6b1d6ab 100644
--- a/networking/udhcp/dhcpd.h
+++ b/networking/udhcp/dhcpd.h
@@ -20,37 +20,37 @@ struct option_set {
20}; 20};
21 21
22struct static_lease { 22struct static_lease {
23 struct static_lease *next;
23 uint8_t *mac; 24 uint8_t *mac;
24 uint32_t *ip; 25 uint32_t *ip;
25 struct static_lease *next;
26}; 26};
27 27
28struct server_config_t { 28struct server_config_t {
29 uint32_t server; /* Our IP, in network order */ 29 uint32_t server; /* Our IP, in network order */
30 /* start,end are in host order: we need to compare start <= ip <= end */ 30 /* start,end are in host order: we need to compare start <= ip <= end */
31 uint32_t start_ip; /* Start address of leases, in host order */ 31 uint32_t start_ip; /* Start address of leases, in host order */
32 uint32_t end_ip; /* End of leases, in host order */ 32 uint32_t end_ip; /* End of leases, in host order */
33 struct option_set *options; /* List of DHCP options loaded from the config file */ 33 struct option_set *options; /* List of DHCP options loaded from the config file */
34 char *interface; /* The name of the interface to use */ 34 char *interface; /* The name of the interface to use */
35 int ifindex; /* Index number of the interface to use */ 35 int ifindex; /* Index number of the interface to use */
36 uint8_t arp[6]; /* Our arp address */ 36 uint8_t arp[6]; /* Our arp address */
37 char remaining; /* should the lease file be interpreted as lease time remaining, or 37 char remaining; /* should the lease file be interpreted as lease time remaining, or
38 * as the time the lease expires */ 38 * as the time the lease expires */
39 unsigned long lease; /* lease time in seconds (host order) */ 39 uint32_t lease; /* lease time in seconds (host order) */
40 unsigned long max_leases; /* maximum number of leases (including reserved address) */ 40 uint32_t max_leases; /* maximum number of leases (including reserved address) */
41 unsigned long auto_time; /* how long should udhcpd wait before writing a config file. 41 uint32_t auto_time; /* how long should udhcpd wait before writing a config file.
42 * if this is zero, it will only write one on SIGUSR1 */ 42 * if this is zero, it will only write one on SIGUSR1 */
43 unsigned long decline_time; /* how long an address is reserved if a client returns a 43 uint32_t decline_time; /* how long an address is reserved if a client returns a
44 * decline message */ 44 * decline message */
45 unsigned long conflict_time; /* how long an arp conflict offender is leased for */ 45 uint32_t conflict_time; /* how long an arp conflict offender is leased for */
46 unsigned long offer_time; /* how long an offered address is reserved */ 46 uint32_t offer_time; /* how long an offered address is reserved */
47 unsigned long min_lease; /* minimum lease a client can request */ 47 uint32_t min_lease; /* minimum lease a client can request */
48 char *lease_file; 48 char *lease_file;
49 char *pidfile; 49 char *pidfile;
50 char *notify_file; /* What to run whenever leases are written */ 50 char *notify_file; /* What to run whenever leases are written */
51 uint32_t siaddr; /* next server bootp option */ 51 uint32_t siaddr; /* next server bootp option */
52 char *sname; /* bootp server name */ 52 char *sname; /* bootp server name */
53 char *boot_file; /* bootp boot file option */ 53 char *boot_file; /* bootp boot file option */
54 struct static_lease *static_leases; /* List of ip/mac pairs to assign static leases */ 54 struct static_lease *static_leases; /* List of ip/mac pairs to assign static leases */
55}; 55};
56 56
diff --git a/networking/udhcp/files.c b/networking/udhcp/files.c
index 7fc734889..8ed485558 100644
--- a/networking/udhcp/files.c
+++ b/networking/udhcp/files.c
@@ -17,12 +17,11 @@ static int read_ip(const char *line, void *arg)
17 len_and_sockaddr *lsa; 17 len_and_sockaddr *lsa;
18 18
19 lsa = host_and_af2sockaddr(line, 0, AF_INET); 19 lsa = host_and_af2sockaddr(line, 0, AF_INET);
20 if (lsa) { 20 if (!lsa)
21 *(uint32_t*)arg = lsa->sin.sin_addr.s_addr; 21 return 0;
22 free(lsa); 22 *(uint32_t*)arg = lsa->sin.sin_addr.s_addr;
23 return 1; 23 free(lsa);
24 } 24 return 1;
25 return 0;
26} 25}
27 26
28static int read_mac(const char *line, void *arg) 27static int read_mac(const char *line, void *arg)
diff --git a/networking/udhcp/leases.c b/networking/udhcp/leases.c
index ceec07345..997daea6c 100644
--- a/networking/udhcp/leases.c
+++ b/networking/udhcp/leases.c
@@ -95,24 +95,26 @@ struct dhcpOfferedAddr *find_lease_by_yiaddr(uint32_t yiaddr)
95 95
96 96
97/* check is an IP is taken, if it is, add it to the lease table */ 97/* check is an IP is taken, if it is, add it to the lease table */
98static int check_ip(uint32_t addr) 98static int nobody_responds_to_arp(uint32_t addr)
99{ 99{
100 static const uint8_t blank_chaddr[16]; /* 16 zero bytes */ 100 static const uint8_t blank_chaddr[16]; /* 16 zero bytes */
101 101
102 struct in_addr temp; 102 struct in_addr temp;
103 int r;
103 104
104 if (arpping(addr, server_config.server, server_config.arp, server_config.interface) == 0) { 105 r = arpping(addr, server_config.server, server_config.arp, server_config.interface);
105 temp.s_addr = addr; 106 if (r)
106 bb_info_msg("%s belongs to someone, reserving it for %ld seconds", 107 return r;
107 inet_ntoa(temp), server_config.conflict_time); 108
108 add_lease(blank_chaddr, addr, server_config.conflict_time); 109 temp.s_addr = addr;
109 return 1; 110 bb_info_msg("%s belongs to someone, reserving it for %u seconds",
110 } 111 inet_ntoa(temp), (unsigned)server_config.conflict_time);
112 add_lease(blank_chaddr, addr, server_config.conflict_time);
111 return 0; 113 return 0;
112} 114}
113 115
114 116
115/* find an assignable address, it check_expired is true, we check all the expired leases as well. 117/* find an assignable address, if check_expired is true, we check all the expired leases as well.
116 * Maybe this should try expired leases by age... */ 118 * Maybe this should try expired leases by age... */
117uint32_t find_address(int check_expired) 119uint32_t find_address(int check_expired)
118{ 120{
@@ -129,15 +131,14 @@ uint32_t find_address(int check_expired)
129 if ((addr & 0xFF) == 0xFF) continue; 131 if ((addr & 0xFF) == 0xFF) continue;
130 132
131 /* Only do if it isn't assigned as a static lease */ 133 /* Only do if it isn't assigned as a static lease */
132 if (!reservedIp(server_config.static_leases, htonl(addr))) { 134 ret = htonl(addr);
133 135 if (!reservedIp(server_config.static_leases, ret)) {
134 /* lease is not taken */ 136 /* lease is not taken */
135 ret = htonl(addr);
136 lease = find_lease_by_yiaddr(ret); 137 lease = find_lease_by_yiaddr(ret);
137 138
138 /* no lease or it expired and we are checking for expired leases */ 139 /* no lease or it expired and we are checking for expired leases */
139 if ((!lease || (check_expired && lease_expired(lease))) 140 if ((!lease || (check_expired && lease_expired(lease)))
140 && /* and it isn't on the network */ !check_ip(ret) 141 && nobody_responds_to_arp(ret) /* it isn't used on the network */
141 ) { 142 ) {
142 return ret; 143 return ret;
143 } 144 }
diff --git a/networking/udhcp/packet.c b/networking/udhcp/packet.c
index da3807773..272e79df1 100644
--- a/networking/udhcp/packet.c
+++ b/networking/udhcp/packet.c
@@ -41,16 +41,17 @@ void udhcp_init_header(struct dhcpMessage *packet, char type)
41/* read a packet from socket fd, return -1 on read error, -2 on packet error */ 41/* read a packet from socket fd, return -1 on read error, -2 on packet error */
42int udhcp_get_packet(struct dhcpMessage *packet, int fd) 42int udhcp_get_packet(struct dhcpMessage *packet, int fd)
43{ 43{
44#if 0
44 static const char broken_vendors[][8] = { 45 static const char broken_vendors[][8] = {
45 "MSFT 98", 46 "MSFT 98",
46 "" 47 ""
47 }; 48 };
49#endif
48 int bytes; 50 int bytes;
49 int i; 51 unsigned char *vendor;
50 char unsigned *vendor;
51 52
52 memset(packet, 0, sizeof(struct dhcpMessage)); 53 memset(packet, 0, sizeof(*packet));
53 bytes = read(fd, packet, sizeof(struct dhcpMessage)); 54 bytes = read(fd, packet, sizeof(*packet));
54 if (bytes < 0) { 55 if (bytes < 0) {
55 DEBUG("cannot read on listening socket, ignoring"); 56 DEBUG("cannot read on listening socket, ignoring");
56 return -1; 57 return -1;
@@ -62,15 +63,28 @@ int udhcp_get_packet(struct dhcpMessage *packet, int fd)
62 } 63 }
63 DEBUG("Received a packet"); 64 DEBUG("Received a packet");
64 65
65 if (packet->op == BOOTREQUEST && (vendor = get_option(packet, DHCP_VENDOR))) { 66 if (packet->op == BOOTREQUEST) {
66 for (i = 0; broken_vendors[i][0]; i++) { 67 vendor = get_option(packet, DHCP_VENDOR);
67 if (vendor[OPT_LEN - 2] == (uint8_t)strlen(broken_vendors[i]) 68 if (vendor) {
68 && !strncmp((char*)vendor, broken_vendors[i], vendor[OPT_LEN - 2]) 69#if 0
70 int i;
71 for (i = 0; broken_vendors[i][0]; i++) {
72 if (vendor[OPT_LEN - 2] == (uint8_t)strlen(broken_vendors[i])
73 && !strncmp((char*)vendor, broken_vendors[i], vendor[OPT_LEN - 2])
74 ) {
75 DEBUG("broken client (%s), forcing broadcast",
76 broken_vendors[i]);
77 packet->flags |= htons(BROADCAST_FLAG);
78 }
79 }
80#else
81 if (vendor[OPT_LEN - 2] == (uint8_t)(sizeof("MSFT 98")-1)
82 && memcmp(vendor, "MSFT 98", sizeof("MSFT 98")-1) == 0
69 ) { 83 ) {
70 DEBUG("broken client (%s), forcing broadcast", 84 DEBUG("broken client (%s), forcing broadcast", "MSFT 98");
71 broken_vendors[i]);
72 packet->flags |= htons(BROADCAST_FLAG); 85 packet->flags |= htons(BROADCAST_FLAG);
73 } 86 }
87#endif
74 } 88 }
75 } 89 }
76 90