udhcp: many small fixes:
* arpping(): smaller and even probably fixed * lots of variables/params converted: ulong -> uint32_t * uptime() nuked in favor of monotonic_sec() * udhcp_get_packet(): only one "bad vendor", simplify function old new delta reservedIp 36 35 -1 udhcpc_main 2462 2460 -2 addStaticLease 64 62 -2 static.broken_vendors 16 - -16 uptime 19 - -19 udhcpd_main 1273 1238 -35 udhcp_get_packet 223 184 -39 .rodata 144162 144106 -56 arpping 690 609 -81 ------------------------------------------------------------------------------ (add/remove: 0/2 grow/shrink: 0/7 up/down: 0/-251) Total: -251 bytes text data bss dec hex filename 734241 3028 14400 751669 b7835 busybox_old 734005 3028 14400 751433 b7749 busybox_unstripped
This commit is contained in:
parent
54e19da86d
commit
42b3dea9bf
@ -15,44 +15,36 @@
|
|||||||
|
|
||||||
struct arpMsg {
|
struct arpMsg {
|
||||||
/* Ethernet header */
|
/* Ethernet header */
|
||||||
uint8_t h_dest[6]; /* destination ether addr */
|
uint8_t h_dest[6]; /* 00 destination ether addr */
|
||||||
uint8_t h_source[6]; /* source ether addr */
|
uint8_t h_source[6]; /* 06 source ether addr */
|
||||||
uint16_t h_proto; /* packet type ID field */
|
uint16_t h_proto; /* 0c packet type ID field */
|
||||||
|
|
||||||
/* ARP packet */
|
/* ARP packet */
|
||||||
uint16_t htype; /* hardware type (must be ARPHRD_ETHER) */
|
uint16_t htype; /* 0e hardware type (must be ARPHRD_ETHER) */
|
||||||
uint16_t ptype; /* protocol type (must be ETH_P_IP) */
|
uint16_t ptype; /* 10 protocol type (must be ETH_P_IP) */
|
||||||
uint8_t hlen; /* hardware address length (must be 6) */
|
uint8_t hlen; /* 12 hardware address length (must be 6) */
|
||||||
uint8_t plen; /* protocol address length (must be 4) */
|
uint8_t plen; /* 13 protocol address length (must be 4) */
|
||||||
uint16_t operation; /* ARP opcode */
|
uint16_t operation; /* 14 ARP opcode */
|
||||||
uint8_t sHaddr[6]; /* sender's hardware address */
|
uint8_t sHaddr[6]; /* 16 sender's hardware address */
|
||||||
uint8_t sInaddr[4]; /* sender's IP address */
|
uint8_t sInaddr[4]; /* 1c sender's IP address */
|
||||||
uint8_t tHaddr[6]; /* target's hardware address */
|
uint8_t tHaddr[6]; /* 20 target's hardware address */
|
||||||
uint8_t tInaddr[4]; /* target's IP address */
|
uint8_t tInaddr[4]; /* 26 target's IP address */
|
||||||
uint8_t pad[18]; /* pad for min. Ethernet payload (60 bytes) */
|
uint8_t pad[18]; /* 2a pad for min. ethernet payload (60 bytes) */
|
||||||
} ATTRIBUTE_PACKED;
|
} ATTRIBUTE_PACKED;
|
||||||
|
|
||||||
/* args: yiaddr - what IP to ping
|
|
||||||
* ip - our ip
|
|
||||||
* mac - our arp address
|
|
||||||
* interface - interface to use
|
|
||||||
* retn: 1 addr free
|
|
||||||
* 0 addr used
|
|
||||||
* -1 error
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* FIXME: match response against chaddr */
|
/* Returns 1 if no reply received */
|
||||||
int arpping(uint32_t yiaddr, uint32_t ip, uint8_t *mac, char *interface)
|
|
||||||
|
int arpping(uint32_t test_ip, uint32_t from_ip, uint8_t *from_mac, const char *interface)
|
||||||
{
|
{
|
||||||
int timeout = 2;
|
int timeout = 2;
|
||||||
int s; /* socket */
|
int s; /* socket */
|
||||||
int rv = 1; /* return value */
|
int rv = 1; /* "no reply received" yet */
|
||||||
struct sockaddr addr; /* for interface name */
|
struct sockaddr addr; /* for interface name */
|
||||||
struct arpMsg arp;
|
struct arpMsg arp;
|
||||||
fd_set fdset;
|
fd_set fdset;
|
||||||
struct timeval tm;
|
struct timeval tm;
|
||||||
time_t prevTime;
|
unsigned prevTime;
|
||||||
|
|
||||||
|
|
||||||
s = socket(PF_PACKET, SOCK_PACKET, htons(ETH_P_ARP));
|
s = socket(PF_PACKET, SOCK_PACKET, htons(ETH_P_ARP));
|
||||||
if (s == -1) {
|
if (s == -1) {
|
||||||
@ -62,55 +54,58 @@ int arpping(uint32_t yiaddr, uint32_t ip, uint8_t *mac, char *interface)
|
|||||||
|
|
||||||
if (setsockopt_broadcast(s) == -1) {
|
if (setsockopt_broadcast(s) == -1) {
|
||||||
bb_perror_msg("cannot setsocketopt on raw socket");
|
bb_perror_msg("cannot setsocketopt on raw socket");
|
||||||
close(s);
|
goto ret;
|
||||||
return -1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* send arp request */
|
/* send arp request */
|
||||||
memset(&arp, 0, sizeof(arp));
|
memset(&arp, 0, sizeof(arp));
|
||||||
memcpy(arp.h_dest, MAC_BCAST_ADDR, 6); /* MAC DA */
|
memset(arp.h_dest, 0xff, 6); /* MAC DA */
|
||||||
memcpy(arp.h_source, mac, 6); /* MAC SA */
|
memcpy(arp.h_source, from_mac, 6); /* MAC SA */
|
||||||
arp.h_proto = htons(ETH_P_ARP); /* protocol type (Ethernet) */
|
arp.h_proto = htons(ETH_P_ARP); /* protocol type (Ethernet) */
|
||||||
arp.htype = htons(ARPHRD_ETHER); /* hardware type */
|
arp.htype = htons(ARPHRD_ETHER); /* hardware type */
|
||||||
arp.ptype = htons(ETH_P_IP); /* protocol type (ARP message) */
|
arp.ptype = htons(ETH_P_IP); /* protocol type (ARP message) */
|
||||||
arp.hlen = 6; /* hardware address length */
|
arp.hlen = 6; /* hardware address length */
|
||||||
arp.plen = 4; /* protocol address length */
|
arp.plen = 4; /* protocol address length */
|
||||||
arp.operation = htons(ARPOP_REQUEST); /* ARP op code */
|
arp.operation = htons(ARPOP_REQUEST); /* ARP op code */
|
||||||
memcpy(arp.sInaddr, &ip, sizeof(ip)); /* source IP address */
|
memcpy(arp.sHaddr, from_mac, 6); /* source hardware address */
|
||||||
memcpy(arp.sHaddr, mac, 6); /* source hardware address */
|
memcpy(arp.sInaddr, &from_ip, sizeof(from_ip)); /* source IP address */
|
||||||
memcpy(arp.tInaddr, &yiaddr, sizeof(yiaddr)); /* target IP address */
|
/* tHaddr */ /* target hardware address */
|
||||||
|
memcpy(arp.tInaddr, &test_ip, sizeof(test_ip)); /* target IP address */
|
||||||
|
|
||||||
memset(&addr, 0, sizeof(addr));
|
memset(&addr, 0, sizeof(addr));
|
||||||
strcpy(addr.sa_data, interface);
|
safe_strncpy(addr.sa_data, interface, sizeof(addr.sa_data));
|
||||||
if (sendto(s, &arp, sizeof(arp), 0, &addr, sizeof(addr)) < 0)
|
if (sendto(s, &arp, sizeof(arp), 0, &addr, sizeof(addr)) < 0)
|
||||||
rv = 0;
|
goto ret;
|
||||||
|
|
||||||
/* wait arp reply, and check it */
|
/* wait for arp reply, and check it */
|
||||||
tm.tv_usec = 0;
|
do {
|
||||||
prevTime = uptime();
|
int r;
|
||||||
while (timeout > 0) {
|
prevTime = monotonic_sec();
|
||||||
FD_ZERO(&fdset);
|
FD_ZERO(&fdset);
|
||||||
FD_SET(s, &fdset);
|
FD_SET(s, &fdset);
|
||||||
tm.tv_sec = timeout;
|
tm.tv_sec = timeout;
|
||||||
if (select(s + 1, &fdset, (fd_set *) NULL, (fd_set *) NULL, &tm) < 0) {
|
tm.tv_usec = 0;
|
||||||
|
r = select(s + 1, &fdset, NULL, NULL, &tm);
|
||||||
|
if (r < 0) {
|
||||||
bb_perror_msg("error on ARPING request");
|
bb_perror_msg("error on ARPING request");
|
||||||
if (errno != EINTR)
|
if (errno != EINTR)
|
||||||
rv = 0;
|
break;
|
||||||
} else if (FD_ISSET(s, &fdset)) {
|
} else if (r) {
|
||||||
if (recv(s, &arp, sizeof(arp), 0) < 0)
|
if (recv(s, &arp, sizeof(arp), 0) < 0)
|
||||||
rv = 0;
|
break;
|
||||||
if (arp.operation == htons(ARPOP_REPLY) &&
|
if (arp.operation == htons(ARPOP_REPLY)
|
||||||
memcmp(arp.tHaddr, mac, 6) == 0 &&
|
&& memcmp(arp.tHaddr, from_mac, 6) == 0
|
||||||
*((uint32_t *) arp.sInaddr) == yiaddr) {
|
&& *((uint32_t *) arp.sInaddr) == test_ip
|
||||||
DEBUG("Valid arp reply received for this address");
|
) {
|
||||||
rv = 0;
|
rv = 0;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
timeout -= uptime() - prevTime;
|
timeout -= monotonic_sec() - prevTime;
|
||||||
prevTime = uptime();
|
} while (timeout > 0);
|
||||||
}
|
|
||||||
|
ret:
|
||||||
close(s);
|
close(s);
|
||||||
DEBUG("%salid arp replies for this address", rv ? "No v" : "V");
|
DEBUG("%srp reply received for this address", rv ? "No a" : "A");
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
@ -25,7 +25,7 @@
|
|||||||
|
|
||||||
|
|
||||||
/* Create a random xid */
|
/* Create a random xid */
|
||||||
unsigned random_xid(void)
|
uint32_t random_xid(void)
|
||||||
{
|
{
|
||||||
static smallint initialized;
|
static smallint initialized;
|
||||||
|
|
||||||
@ -44,8 +44,10 @@ static void init_packet(struct dhcpMessage *packet, char type)
|
|||||||
memcpy(packet->chaddr, client_config.arp, 6);
|
memcpy(packet->chaddr, client_config.arp, 6);
|
||||||
if (client_config.clientid)
|
if (client_config.clientid)
|
||||||
add_option_string(packet->options, client_config.clientid);
|
add_option_string(packet->options, client_config.clientid);
|
||||||
if (client_config.hostname) add_option_string(packet->options, client_config.hostname);
|
if (client_config.hostname)
|
||||||
if (client_config.fqdn) add_option_string(packet->options, client_config.fqdn);
|
add_option_string(packet->options, client_config.hostname);
|
||||||
|
if (client_config.fqdn)
|
||||||
|
add_option_string(packet->options, client_config.fqdn);
|
||||||
add_option_string(packet->options, client_config.vendorclass);
|
add_option_string(packet->options, client_config.vendorclass);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -69,7 +71,7 @@ static void add_requests(struct dhcpMessage *packet)
|
|||||||
|
|
||||||
|
|
||||||
/* Broadcast a DHCP discover packet to the network, with an optionally requested IP */
|
/* Broadcast a DHCP discover packet to the network, with an optionally requested IP */
|
||||||
int send_discover(unsigned long xid, unsigned long requested)
|
int send_discover(uint32_t xid, uint32_t requested)
|
||||||
{
|
{
|
||||||
struct dhcpMessage packet;
|
struct dhcpMessage packet;
|
||||||
|
|
||||||
@ -86,7 +88,7 @@ int send_discover(unsigned long xid, unsigned long requested)
|
|||||||
|
|
||||||
|
|
||||||
/* Broadcasts a DHCP request message */
|
/* Broadcasts a DHCP request message */
|
||||||
int send_selecting(unsigned long xid, unsigned long server, unsigned long requested)
|
int send_selecting(uint32_t xid, uint32_t server, uint32_t requested)
|
||||||
{
|
{
|
||||||
struct dhcpMessage packet;
|
struct dhcpMessage packet;
|
||||||
struct in_addr addr;
|
struct in_addr addr;
|
||||||
@ -106,10 +108,9 @@ int send_selecting(unsigned long xid, unsigned long server, unsigned long reques
|
|||||||
|
|
||||||
|
|
||||||
/* Unicasts or broadcasts a DHCP renew message */
|
/* Unicasts or broadcasts a DHCP renew message */
|
||||||
int send_renew(unsigned long xid, unsigned long server, unsigned long ciaddr)
|
int send_renew(uint32_t xid, uint32_t server, uint32_t ciaddr)
|
||||||
{
|
{
|
||||||
struct dhcpMessage packet;
|
struct dhcpMessage packet;
|
||||||
int ret = 0;
|
|
||||||
|
|
||||||
init_packet(&packet, DHCPREQUEST);
|
init_packet(&packet, DHCPREQUEST);
|
||||||
packet.xid = xid;
|
packet.xid = xid;
|
||||||
@ -118,15 +119,15 @@ int send_renew(unsigned long xid, unsigned long server, unsigned long ciaddr)
|
|||||||
add_requests(&packet);
|
add_requests(&packet);
|
||||||
bb_info_msg("Sending renew...");
|
bb_info_msg("Sending renew...");
|
||||||
if (server)
|
if (server)
|
||||||
ret = udhcp_kernel_packet(&packet, ciaddr, CLIENT_PORT, server, SERVER_PORT);
|
return udhcp_kernel_packet(&packet, ciaddr, CLIENT_PORT, server, SERVER_PORT);
|
||||||
else ret = udhcp_raw_packet(&packet, INADDR_ANY, CLIENT_PORT, INADDR_BROADCAST,
|
|
||||||
|
return udhcp_raw_packet(&packet, INADDR_ANY, CLIENT_PORT, INADDR_BROADCAST,
|
||||||
SERVER_PORT, MAC_BCAST_ADDR, client_config.ifindex);
|
SERVER_PORT, MAC_BCAST_ADDR, client_config.ifindex);
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Unicasts a DHCP release message */
|
/* Unicasts a DHCP release message */
|
||||||
int send_release(unsigned long server, unsigned long ciaddr)
|
int send_release(uint32_t server, uint32_t ciaddr)
|
||||||
{
|
{
|
||||||
struct dhcpMessage packet;
|
struct dhcpMessage packet;
|
||||||
|
|
||||||
@ -214,5 +215,4 @@ int get_raw_packet(struct dhcpMessage *payload, int fd)
|
|||||||
}
|
}
|
||||||
DEBUG("oooooh!!! got some!");
|
DEBUG("oooooh!!! got some!");
|
||||||
return bytes - (sizeof(packet.ip) + sizeof(packet.udp));
|
return bytes - (sizeof(packet.ip) + sizeof(packet.udp));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -10,31 +10,10 @@
|
|||||||
* Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
|
* Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <syslog.h>
|
|
||||||
|
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
|
|
||||||
|
|
||||||
const uint8_t MAC_BCAST_ADDR[6] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
|
const uint8_t MAC_BCAST_ADDR[6] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
|
||||||
|
|
||||||
long uptime(void)
|
|
||||||
{
|
|
||||||
struct sysinfo info;
|
|
||||||
sysinfo(&info);
|
|
||||||
return info.uptime;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void create_pidfile(const char *pidfile)
|
|
||||||
{
|
|
||||||
if (!pidfile)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (!write_pidfile(pidfile)) {
|
|
||||||
bb_perror_msg("cannot create pidfile %s", pidfile);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void udhcp_make_pidfile(const char *pidfile)
|
void udhcp_make_pidfile(const char *pidfile)
|
||||||
{
|
{
|
||||||
/* Make sure fd 0,1,2 are open */
|
/* Make sure fd 0,1,2 are open */
|
||||||
@ -44,7 +23,8 @@ void udhcp_make_pidfile(const char *pidfile)
|
|||||||
setlinebuf(stdout);
|
setlinebuf(stdout);
|
||||||
|
|
||||||
/* Create pidfile */
|
/* Create pidfile */
|
||||||
create_pidfile(pidfile);
|
if (pidfile && !write_pidfile(pidfile))
|
||||||
|
bb_perror_msg("cannot create pidfile %s", pidfile);
|
||||||
|
|
||||||
bb_info_msg("%s (v%s) started", applet_name, BB_VER);
|
bb_info_msg("%s (v%s) started", applet_name, BB_VER);
|
||||||
}
|
}
|
||||||
|
@ -80,14 +80,14 @@ void udhcp_run_script(struct dhcpMessage *packet, const char *name);
|
|||||||
/* from dhcpd.h */
|
/* from dhcpd.h */
|
||||||
#define server_config udhcp_server_config
|
#define server_config udhcp_server_config
|
||||||
|
|
||||||
long uptime(void);
|
|
||||||
void udhcp_sp_setup(void);
|
void udhcp_sp_setup(void);
|
||||||
int udhcp_sp_fd_set(fd_set *rfds, int extra_fd);
|
int udhcp_sp_fd_set(fd_set *rfds, int extra_fd);
|
||||||
int udhcp_sp_read(fd_set *rfds);
|
int udhcp_sp_read(fd_set *rfds);
|
||||||
int raw_socket(int ifindex);
|
int raw_socket(int ifindex);
|
||||||
int read_interface(const char *interface, int *ifindex, uint32_t *addr, uint8_t *arp);
|
int read_interface(const char *interface, int *ifindex, uint32_t *addr, uint8_t *arp);
|
||||||
int listen_socket(uint32_t ip, int port, const char *inf);
|
int listen_socket(uint32_t ip, int port, const char *inf);
|
||||||
int arpping(uint32_t yiaddr, uint32_t ip, uint8_t *arp, char *interface);
|
/* Returns 1 if no reply received */
|
||||||
|
int arpping(uint32_t test_ip, uint32_t from_ip, uint8_t *from_mac, const char *interface);
|
||||||
|
|
||||||
#if ENABLE_FEATURE_UDHCP_DEBUG
|
#if ENABLE_FEATURE_UDHCP_DEBUG
|
||||||
# define DEBUG(str, args...) bb_info_msg(str, ## args)
|
# define DEBUG(str, args...) bb_info_msg(str, ## args)
|
||||||
|
@ -22,8 +22,8 @@
|
|||||||
* in the code. Manpage says that struct in_addr has a member of type long (!)
|
* in the code. Manpage says that struct in_addr has a member of type long (!)
|
||||||
* which holds IPv4 address, and the struct is passed by value (!!)
|
* which holds IPv4 address, and the struct is passed by value (!!)
|
||||||
*/
|
*/
|
||||||
static unsigned long timeout;
|
static unsigned timeout;
|
||||||
static unsigned long requested_ip; /* = 0 */
|
static uint32_t requested_ip; /* = 0 */
|
||||||
static uint32_t server_addr;
|
static uint32_t server_addr;
|
||||||
static int packet_num; /* = 0 */
|
static int packet_num; /* = 0 */
|
||||||
static int sockfd = -1;
|
static int sockfd = -1;
|
||||||
@ -84,13 +84,13 @@ static void perform_renew(void)
|
|||||||
/* perform a release */
|
/* perform a release */
|
||||||
static void perform_release(void)
|
static void perform_release(void)
|
||||||
{
|
{
|
||||||
char buffer[16];
|
char buffer[sizeof("255.255.255.255")];
|
||||||
struct in_addr temp_addr;
|
struct in_addr temp_addr;
|
||||||
|
|
||||||
/* send release packet */
|
/* send release packet */
|
||||||
if (state == BOUND || state == RENEWING || state == REBINDING) {
|
if (state == BOUND || state == RENEWING || state == REBINDING) {
|
||||||
temp_addr.s_addr = server_addr;
|
temp_addr.s_addr = server_addr;
|
||||||
sprintf(buffer, "%s", inet_ntoa(temp_addr));
|
strcpy(buffer, inet_ntoa(temp_addr));
|
||||||
temp_addr.s_addr = requested_ip;
|
temp_addr.s_addr = requested_ip;
|
||||||
bb_info_msg("Unicasting a release of %s to %s",
|
bb_info_msg("Unicasting a release of %s to %s",
|
||||||
inet_ntoa(temp_addr), buffer);
|
inet_ntoa(temp_addr), buffer);
|
||||||
@ -101,7 +101,7 @@ static void perform_release(void)
|
|||||||
|
|
||||||
change_mode(LISTEN_NONE);
|
change_mode(LISTEN_NONE);
|
||||||
state = RELEASED;
|
state = RELEASED;
|
||||||
timeout = 0x7fffffff;
|
timeout = INT_MAX;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -115,12 +115,13 @@ static void client_background(void)
|
|||||||
* will work on NOMMU too */
|
* will work on NOMMU too */
|
||||||
#else
|
#else
|
||||||
bb_daemonize(0);
|
bb_daemonize(0);
|
||||||
|
logmode &= ~LOGMODE_STDIO;
|
||||||
/* rewrite pidfile, as our pid is different now */
|
/* rewrite pidfile, as our pid is different now */
|
||||||
if (client_config.pidfile)
|
if (client_config.pidfile)
|
||||||
write_pidfile(client_config.pidfile);
|
write_pidfile(client_config.pidfile);
|
||||||
logmode &= ~LOGMODE_STDIO;
|
|
||||||
#endif
|
#endif
|
||||||
client_config.foreground = 1; /* Do not fork again. */
|
/* Do not fork again. */
|
||||||
|
client_config.foreground = 1;
|
||||||
client_config.background_if_no_lease = 0;
|
client_config.background_if_no_lease = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -143,9 +144,11 @@ int udhcpc_main(int argc, char **argv)
|
|||||||
{
|
{
|
||||||
uint8_t *temp, *message;
|
uint8_t *temp, *message;
|
||||||
char *str_c, *str_V, *str_h, *str_F, *str_r, *str_T, *str_t;
|
char *str_c, *str_V, *str_h, *str_F, *str_r, *str_T, *str_t;
|
||||||
unsigned long t1 = 0, t2 = 0, xid = 0;
|
uint32_t xid = 0;
|
||||||
unsigned long start = 0, lease = 0;
|
uint32_t lease = 0; /* can be given as 32-bit quantity */
|
||||||
long now;
|
unsigned t1 = 0, t2 = 0;
|
||||||
|
unsigned start = 0;
|
||||||
|
unsigned now;
|
||||||
unsigned opt;
|
unsigned opt;
|
||||||
int max_fd;
|
int max_fd;
|
||||||
int sig;
|
int sig;
|
||||||
@ -292,7 +295,7 @@ int udhcpc_main(int argc, char **argv)
|
|||||||
change_mode(LISTEN_RAW);
|
change_mode(LISTEN_RAW);
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
tv.tv_sec = timeout - uptime();
|
tv.tv_sec = timeout - monotonic_sec();
|
||||||
tv.tv_usec = 0;
|
tv.tv_usec = 0;
|
||||||
|
|
||||||
if (listen_mode != LISTEN_NONE && sockfd < 0) {
|
if (listen_mode != LISTEN_NONE && sockfd < 0) {
|
||||||
@ -308,7 +311,7 @@ int udhcpc_main(int argc, char **argv)
|
|||||||
retval = select(max_fd + 1, &rfds, NULL, NULL, &tv);
|
retval = select(max_fd + 1, &rfds, NULL, NULL, &tv);
|
||||||
} else retval = 0; /* If we already timed out, fall through */
|
} else retval = 0; /* If we already timed out, fall through */
|
||||||
|
|
||||||
now = uptime();
|
now = monotonic_sec();
|
||||||
if (retval == 0) {
|
if (retval == 0) {
|
||||||
/* timeout dropped to zero */
|
/* timeout dropped to zero */
|
||||||
switch (state) {
|
switch (state) {
|
||||||
@ -398,7 +401,7 @@ int udhcpc_main(int argc, char **argv)
|
|||||||
break;
|
break;
|
||||||
case RELEASED:
|
case RELEASED:
|
||||||
/* yah, I know, *you* say it would never happen */
|
/* yah, I know, *you* say it would never happen */
|
||||||
timeout = 0x7fffffff;
|
timeout = INT_MAX;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
} else if (retval > 0 && listen_mode != LISTEN_NONE && FD_ISSET(sockfd, &rfds)) {
|
} else if (retval > 0 && listen_mode != LISTEN_NONE && FD_ISSET(sockfd, &rfds)) {
|
||||||
@ -415,8 +418,8 @@ int udhcpc_main(int argc, char **argv)
|
|||||||
if (len < 0) continue;
|
if (len < 0) continue;
|
||||||
|
|
||||||
if (packet.xid != xid) {
|
if (packet.xid != xid) {
|
||||||
DEBUG("Ignoring XID %lx (our xid is %lx)",
|
DEBUG("Ignoring XID %x (our xid is %x)",
|
||||||
(unsigned long) packet.xid, xid);
|
(unsigned)packet.xid, (unsigned)xid);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -471,10 +474,10 @@ int udhcpc_main(int argc, char **argv)
|
|||||||
t1 = lease / 2;
|
t1 = lease / 2;
|
||||||
|
|
||||||
/* little fixed point for n * .875 */
|
/* little fixed point for n * .875 */
|
||||||
t2 = (lease * 0x7) >> 3;
|
t2 = (lease * 7) >> 3;
|
||||||
temp_addr.s_addr = packet.yiaddr;
|
temp_addr.s_addr = packet.yiaddr;
|
||||||
bb_info_msg("Lease of %s obtained, lease time %ld",
|
bb_info_msg("Lease of %s obtained, lease time %u",
|
||||||
inet_ntoa(temp_addr), lease);
|
inet_ntoa(temp_addr), (unsigned)lease);
|
||||||
start = now;
|
start = now;
|
||||||
timeout = t1 + start;
|
timeout = t1 + start;
|
||||||
requested_ip = packet.yiaddr;
|
requested_ip = packet.yiaddr;
|
||||||
|
@ -38,12 +38,12 @@ extern struct client_config_t client_config;
|
|||||||
|
|
||||||
/*** clientpacket.h ***/
|
/*** clientpacket.h ***/
|
||||||
|
|
||||||
unsigned random_xid(void);
|
uint32_t random_xid(void);
|
||||||
int send_discover(unsigned long xid, unsigned long requested);
|
int send_discover(uint32_t xid, uint32_t requested);
|
||||||
int send_selecting(unsigned long xid, unsigned long server, unsigned long requested);
|
int send_selecting(uint32_t xid, uint32_t server, uint32_t requested);
|
||||||
int send_renew(unsigned long xid, unsigned long server, unsigned long ciaddr);
|
int send_renew(uint32_t xid, uint32_t server, uint32_t ciaddr);
|
||||||
int send_renew(unsigned long xid, unsigned long server, unsigned long ciaddr);
|
int send_renew(uint32_t xid, uint32_t server, uint32_t ciaddr);
|
||||||
int send_release(unsigned long server, unsigned long ciaddr);
|
int send_release(uint32_t server, uint32_t ciaddr);
|
||||||
int get_raw_packet(struct dhcpMessage *payload, int fd);
|
int get_raw_packet(struct dhcpMessage *payload, int fd);
|
||||||
|
|
||||||
|
|
||||||
|
@ -30,7 +30,8 @@ int udhcpd_main(int argc, char **argv)
|
|||||||
struct dhcpMessage packet;
|
struct dhcpMessage packet;
|
||||||
uint8_t *state, *server_id, *requested;
|
uint8_t *state, *server_id, *requested;
|
||||||
uint32_t server_id_align, requested_align, static_lease_ip;
|
uint32_t server_id_align, requested_align, static_lease_ip;
|
||||||
unsigned long timeout_end, num_ips;
|
unsigned timeout_end;
|
||||||
|
unsigned num_ips;
|
||||||
struct option_set *option;
|
struct option_set *option;
|
||||||
struct dhcpOfferedAddr *lease, static_lease;
|
struct dhcpOfferedAddr *lease, static_lease;
|
||||||
|
|
||||||
@ -48,7 +49,7 @@ int udhcpd_main(int argc, char **argv)
|
|||||||
|
|
||||||
/* Would rather not do read_config before daemonization -
|
/* Would rather not do read_config before daemonization -
|
||||||
* otherwise NOMMU machines will parse config twice */
|
* otherwise NOMMU machines will parse config twice */
|
||||||
read_config(argc < 2 ? DHCPD_CONF_FILE : argv[1]);
|
read_config(argv[1] ? argv[1] : DHCPD_CONF_FILE);
|
||||||
|
|
||||||
udhcp_make_pidfile(server_config.pidfile);
|
udhcp_make_pidfile(server_config.pidfile);
|
||||||
|
|
||||||
@ -62,9 +63,8 @@ int udhcpd_main(int argc, char **argv)
|
|||||||
/* Sanity check */
|
/* Sanity check */
|
||||||
num_ips = server_config.end_ip - server_config.start_ip + 1;
|
num_ips = server_config.end_ip - server_config.start_ip + 1;
|
||||||
if (server_config.max_leases > num_ips) {
|
if (server_config.max_leases > num_ips) {
|
||||||
bb_error_msg("max_leases=%lu is too big, "
|
bb_error_msg("max_leases=%u is too big, setting to %u",
|
||||||
"setting to %lu",
|
(unsigned)server_config.max_leases, num_ips);
|
||||||
server_config.max_leases, num_ips);
|
|
||||||
server_config.max_leases = num_ips;
|
server_config.max_leases = num_ips;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -80,7 +80,7 @@ int udhcpd_main(int argc, char **argv)
|
|||||||
/* Setup the signal pipe */
|
/* Setup the signal pipe */
|
||||||
udhcp_sp_setup();
|
udhcp_sp_setup();
|
||||||
|
|
||||||
timeout_end = time(0) + server_config.auto_time;
|
timeout_end = monotonic_sec() + server_config.auto_time;
|
||||||
while (1) { /* loop until universe collapses */
|
while (1) { /* loop until universe collapses */
|
||||||
|
|
||||||
if (server_socket < 0) {
|
if (server_socket < 0) {
|
||||||
@ -90,7 +90,7 @@ int udhcpd_main(int argc, char **argv)
|
|||||||
|
|
||||||
max_sock = udhcp_sp_fd_set(&rfds, server_socket);
|
max_sock = udhcp_sp_fd_set(&rfds, server_socket);
|
||||||
if (server_config.auto_time) {
|
if (server_config.auto_time) {
|
||||||
tv.tv_sec = timeout_end - time(0);
|
tv.tv_sec = timeout_end - monotonic_sec();
|
||||||
tv.tv_usec = 0;
|
tv.tv_usec = 0;
|
||||||
}
|
}
|
||||||
retval = 0;
|
retval = 0;
|
||||||
@ -100,7 +100,7 @@ int udhcpd_main(int argc, char **argv)
|
|||||||
}
|
}
|
||||||
if (retval == 0) {
|
if (retval == 0) {
|
||||||
write_leases();
|
write_leases();
|
||||||
timeout_end = time(0) + server_config.auto_time;
|
timeout_end = monotonic_sec() + server_config.auto_time;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (retval < 0 && errno != EINTR) {
|
if (retval < 0 && errno != EINTR) {
|
||||||
@ -113,7 +113,7 @@ int udhcpd_main(int argc, char **argv)
|
|||||||
bb_info_msg("Received a SIGUSR1");
|
bb_info_msg("Received a SIGUSR1");
|
||||||
write_leases();
|
write_leases();
|
||||||
/* why not just reset the timeout, eh */
|
/* why not just reset the timeout, eh */
|
||||||
timeout_end = time(0) + server_config.auto_time;
|
timeout_end = monotonic_sec() + server_config.auto_time;
|
||||||
continue;
|
continue;
|
||||||
case SIGTERM:
|
case SIGTERM:
|
||||||
bb_info_msg("Received a SIGTERM");
|
bb_info_msg("Received a SIGTERM");
|
||||||
@ -244,7 +244,7 @@ int udhcpd_main(int argc, char **argv)
|
|||||||
ret0:
|
ret0:
|
||||||
retval = 0;
|
retval = 0;
|
||||||
ret:
|
ret:
|
||||||
if (server_config.pidfile)
|
/*if (server_config.pidfile) - server_config.pidfile is never NULL */
|
||||||
remove_pidfile(server_config.pidfile);
|
remove_pidfile(server_config.pidfile);
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
@ -20,9 +20,9 @@ struct option_set {
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct static_lease {
|
struct static_lease {
|
||||||
|
struct static_lease *next;
|
||||||
uint8_t *mac;
|
uint8_t *mac;
|
||||||
uint32_t *ip;
|
uint32_t *ip;
|
||||||
struct static_lease *next;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct server_config_t {
|
struct server_config_t {
|
||||||
@ -36,15 +36,15 @@ struct server_config_t {
|
|||||||
uint8_t arp[6]; /* Our arp address */
|
uint8_t arp[6]; /* Our arp address */
|
||||||
char remaining; /* should the lease file be interpreted as lease time remaining, or
|
char remaining; /* should the lease file be interpreted as lease time remaining, or
|
||||||
* as the time the lease expires */
|
* as the time the lease expires */
|
||||||
unsigned long lease; /* lease time in seconds (host order) */
|
uint32_t lease; /* lease time in seconds (host order) */
|
||||||
unsigned long max_leases; /* maximum number of leases (including reserved address) */
|
uint32_t max_leases; /* maximum number of leases (including reserved address) */
|
||||||
unsigned long auto_time; /* how long should udhcpd wait before writing a config file.
|
uint32_t auto_time; /* how long should udhcpd wait before writing a config file.
|
||||||
* if this is zero, it will only write one on SIGUSR1 */
|
* if this is zero, it will only write one on SIGUSR1 */
|
||||||
unsigned long decline_time; /* how long an address is reserved if a client returns a
|
uint32_t decline_time; /* how long an address is reserved if a client returns a
|
||||||
* decline message */
|
* decline message */
|
||||||
unsigned long conflict_time; /* how long an arp conflict offender is leased for */
|
uint32_t conflict_time; /* how long an arp conflict offender is leased for */
|
||||||
unsigned long offer_time; /* how long an offered address is reserved */
|
uint32_t offer_time; /* how long an offered address is reserved */
|
||||||
unsigned long min_lease; /* minimum lease a client can request */
|
uint32_t min_lease; /* minimum lease a client can request */
|
||||||
char *lease_file;
|
char *lease_file;
|
||||||
char *pidfile;
|
char *pidfile;
|
||||||
char *notify_file; /* What to run whenever leases are written */
|
char *notify_file; /* What to run whenever leases are written */
|
||||||
|
@ -17,12 +17,11 @@ static int read_ip(const char *line, void *arg)
|
|||||||
len_and_sockaddr *lsa;
|
len_and_sockaddr *lsa;
|
||||||
|
|
||||||
lsa = host_and_af2sockaddr(line, 0, AF_INET);
|
lsa = host_and_af2sockaddr(line, 0, AF_INET);
|
||||||
if (lsa) {
|
if (!lsa)
|
||||||
|
return 0;
|
||||||
*(uint32_t*)arg = lsa->sin.sin_addr.s_addr;
|
*(uint32_t*)arg = lsa->sin.sin_addr.s_addr;
|
||||||
free(lsa);
|
free(lsa);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int read_mac(const char *line, void *arg)
|
static int read_mac(const char *line, void *arg)
|
||||||
|
@ -95,24 +95,26 @@ struct dhcpOfferedAddr *find_lease_by_yiaddr(uint32_t yiaddr)
|
|||||||
|
|
||||||
|
|
||||||
/* check is an IP is taken, if it is, add it to the lease table */
|
/* check is an IP is taken, if it is, add it to the lease table */
|
||||||
static int check_ip(uint32_t addr)
|
static int nobody_responds_to_arp(uint32_t addr)
|
||||||
{
|
{
|
||||||
static const uint8_t blank_chaddr[16]; /* 16 zero bytes */
|
static const uint8_t blank_chaddr[16]; /* 16 zero bytes */
|
||||||
|
|
||||||
struct in_addr temp;
|
struct in_addr temp;
|
||||||
|
int r;
|
||||||
|
|
||||||
|
r = arpping(addr, server_config.server, server_config.arp, server_config.interface);
|
||||||
|
if (r)
|
||||||
|
return r;
|
||||||
|
|
||||||
if (arpping(addr, server_config.server, server_config.arp, server_config.interface) == 0) {
|
|
||||||
temp.s_addr = addr;
|
temp.s_addr = addr;
|
||||||
bb_info_msg("%s belongs to someone, reserving it for %ld seconds",
|
bb_info_msg("%s belongs to someone, reserving it for %u seconds",
|
||||||
inet_ntoa(temp), server_config.conflict_time);
|
inet_ntoa(temp), (unsigned)server_config.conflict_time);
|
||||||
add_lease(blank_chaddr, addr, server_config.conflict_time);
|
add_lease(blank_chaddr, addr, server_config.conflict_time);
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* find an assignable address, it check_expired is true, we check all the expired leases as well.
|
/* find an assignable address, if check_expired is true, we check all the expired leases as well.
|
||||||
* Maybe this should try expired leases by age... */
|
* Maybe this should try expired leases by age... */
|
||||||
uint32_t find_address(int check_expired)
|
uint32_t find_address(int check_expired)
|
||||||
{
|
{
|
||||||
@ -129,15 +131,14 @@ uint32_t find_address(int check_expired)
|
|||||||
if ((addr & 0xFF) == 0xFF) continue;
|
if ((addr & 0xFF) == 0xFF) continue;
|
||||||
|
|
||||||
/* Only do if it isn't assigned as a static lease */
|
/* Only do if it isn't assigned as a static lease */
|
||||||
if (!reservedIp(server_config.static_leases, htonl(addr))) {
|
|
||||||
|
|
||||||
/* lease is not taken */
|
|
||||||
ret = htonl(addr);
|
ret = htonl(addr);
|
||||||
|
if (!reservedIp(server_config.static_leases, ret)) {
|
||||||
|
/* lease is not taken */
|
||||||
lease = find_lease_by_yiaddr(ret);
|
lease = find_lease_by_yiaddr(ret);
|
||||||
|
|
||||||
/* no lease or it expired and we are checking for expired leases */
|
/* no lease or it expired and we are checking for expired leases */
|
||||||
if ((!lease || (check_expired && lease_expired(lease)))
|
if ((!lease || (check_expired && lease_expired(lease)))
|
||||||
&& /* and it isn't on the network */ !check_ip(ret)
|
&& nobody_responds_to_arp(ret) /* it isn't used on the network */
|
||||||
) {
|
) {
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -41,16 +41,17 @@ void udhcp_init_header(struct dhcpMessage *packet, char type)
|
|||||||
/* read a packet from socket fd, return -1 on read error, -2 on packet error */
|
/* read a packet from socket fd, return -1 on read error, -2 on packet error */
|
||||||
int udhcp_get_packet(struct dhcpMessage *packet, int fd)
|
int udhcp_get_packet(struct dhcpMessage *packet, int fd)
|
||||||
{
|
{
|
||||||
|
#if 0
|
||||||
static const char broken_vendors[][8] = {
|
static const char broken_vendors[][8] = {
|
||||||
"MSFT 98",
|
"MSFT 98",
|
||||||
""
|
""
|
||||||
};
|
};
|
||||||
|
#endif
|
||||||
int bytes;
|
int bytes;
|
||||||
int i;
|
unsigned char *vendor;
|
||||||
char unsigned *vendor;
|
|
||||||
|
|
||||||
memset(packet, 0, sizeof(struct dhcpMessage));
|
memset(packet, 0, sizeof(*packet));
|
||||||
bytes = read(fd, packet, sizeof(struct dhcpMessage));
|
bytes = read(fd, packet, sizeof(*packet));
|
||||||
if (bytes < 0) {
|
if (bytes < 0) {
|
||||||
DEBUG("cannot read on listening socket, ignoring");
|
DEBUG("cannot read on listening socket, ignoring");
|
||||||
return -1;
|
return -1;
|
||||||
@ -62,7 +63,11 @@ int udhcp_get_packet(struct dhcpMessage *packet, int fd)
|
|||||||
}
|
}
|
||||||
DEBUG("Received a packet");
|
DEBUG("Received a packet");
|
||||||
|
|
||||||
if (packet->op == BOOTREQUEST && (vendor = get_option(packet, DHCP_VENDOR))) {
|
if (packet->op == BOOTREQUEST) {
|
||||||
|
vendor = get_option(packet, DHCP_VENDOR);
|
||||||
|
if (vendor) {
|
||||||
|
#if 0
|
||||||
|
int i;
|
||||||
for (i = 0; broken_vendors[i][0]; i++) {
|
for (i = 0; broken_vendors[i][0]; i++) {
|
||||||
if (vendor[OPT_LEN - 2] == (uint8_t)strlen(broken_vendors[i])
|
if (vendor[OPT_LEN - 2] == (uint8_t)strlen(broken_vendors[i])
|
||||||
&& !strncmp((char*)vendor, broken_vendors[i], vendor[OPT_LEN - 2])
|
&& !strncmp((char*)vendor, broken_vendors[i], vendor[OPT_LEN - 2])
|
||||||
@ -72,6 +77,15 @@ int udhcp_get_packet(struct dhcpMessage *packet, int fd)
|
|||||||
packet->flags |= htons(BROADCAST_FLAG);
|
packet->flags |= htons(BROADCAST_FLAG);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#else
|
||||||
|
if (vendor[OPT_LEN - 2] == (uint8_t)(sizeof("MSFT 98")-1)
|
||||||
|
&& memcmp(vendor, "MSFT 98", sizeof("MSFT 98")-1) == 0
|
||||||
|
) {
|
||||||
|
DEBUG("broken client (%s), forcing broadcast", "MSFT 98");
|
||||||
|
packet->flags |= htons(BROADCAST_FLAG);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return bytes;
|
return bytes;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user