diff options
-rw-r--r-- | networking/udhcp/common.c | 2 | ||||
-rw-r--r-- | networking/udhcp/common.h | 6 | ||||
-rw-r--r-- | networking/udhcp/dhcpc.c | 36 | ||||
-rw-r--r-- | networking/udhcp/dhcpd.h | 83 | ||||
-rw-r--r-- | networking/udhcp/leases.c | 68 | ||||
-rw-r--r-- | networking/udhcp/options.h | 74 | ||||
-rw-r--r-- | networking/udhcp/packet.c | 2 | ||||
-rw-r--r-- | networking/udhcp/script.c | 52 | ||||
-rw-r--r-- | networking/udhcp/serverpacket.c | 2 |
9 files changed, 169 insertions, 156 deletions
diff --git a/networking/udhcp/common.c b/networking/udhcp/common.c index 46cc0348f..721888f6d 100644 --- a/networking/udhcp/common.c +++ b/networking/udhcp/common.c @@ -15,6 +15,8 @@ #include "common.h" +const uint8_t MAC_BCAST_ADDR[6] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; + long uptime(void) { struct sysinfo info; diff --git a/networking/udhcp/common.h b/networking/udhcp/common.h index 00890ac1c..6c0db5b4c 100644 --- a/networking/udhcp/common.h +++ b/networking/udhcp/common.h @@ -14,8 +14,7 @@ #define DEFAULT_SCRIPT "/usr/share/udhcpc/default.script" -#define COMBINED_BINARY - +extern const uint8_t MAC_BCAST_ADDR[6]; /* six all-ones */ /*** packet.h ***/ @@ -52,7 +51,8 @@ int udhcp_get_packet(struct dhcpMessage *packet, int fd); uint16_t udhcp_checksum(void *addr, int count); int udhcp_raw_packet(struct dhcpMessage *payload, uint32_t source_ip, int source_port, - uint32_t dest_ip, int dest_port, uint8_t *dest_arp, int ifindex); + uint32_t dest_ip, int dest_port, + const uint8_t *dest_arp, int ifindex); int udhcp_kernel_packet(struct dhcpMessage *payload, uint32_t source_ip, int source_port, uint32_t dest_ip, int dest_port); diff --git a/networking/udhcp/dhcpc.c b/networking/udhcp/dhcpc.c index e8cdd79df..362e70169 100644 --- a/networking/udhcp/dhcpc.c +++ b/networking/udhcp/dhcpc.c @@ -17,22 +17,23 @@ #include "options.h" -static int state; /* Something is definitely wrong here. IPv4 addresses * in variables of type long?? BTW, we use inet_ntoa() * 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 (!!) */ +static unsigned long timeout; static unsigned long requested_ip; /* = 0 */ static uint32_t server_addr; -static unsigned long timeout; static int packet_num; /* = 0 */ -static int fd = -1; +static int sockfd = -1; #define LISTEN_NONE 0 #define LISTEN_KERNEL 1 #define LISTEN_RAW 2 -static int listen_mode; +static smallint listen_mode; + +static smallint state; struct client_config_t client_config; @@ -42,8 +43,10 @@ static void change_mode(int new_mode) { DEBUG("entering %s listen mode", new_mode ? (new_mode == 1 ? "kernel" : "raw") : "none"); - if (fd >= 0) close(fd); - fd = -1; + if (sockfd >= 0) { + close(sockfd); + sockfd = -1; + } listen_mode = new_mode; } @@ -111,6 +114,7 @@ static void client_background(void) * If that will be properly disabled for NOMMU, client_background() * will work on NOMMU too */ #else +// chdir(/) is problematic. Imagine that e.g. pidfile name is RELATIVE! what will unlink do then, eh? bb_daemonize(DAEMON_CHDIR_ROOT); logmode &= ~LOGMODE_STDIO; #endif @@ -289,13 +293,13 @@ int udhcpc_main(int argc, char **argv) tv.tv_sec = timeout - uptime(); tv.tv_usec = 0; - if (listen_mode != LISTEN_NONE && fd < 0) { + if (listen_mode != LISTEN_NONE && sockfd < 0) { if (listen_mode == LISTEN_KERNEL) - fd = listen_socket(INADDR_ANY, CLIENT_PORT, client_config.interface); + sockfd = listen_socket(INADDR_ANY, CLIENT_PORT, client_config.interface); else - fd = raw_socket(client_config.ifindex); + sockfd = raw_socket(client_config.ifindex); } - max_fd = udhcp_sp_fd_set(&rfds, fd); + max_fd = udhcp_sp_fd_set(&rfds, sockfd); if (tv.tv_sec > 0) { DEBUG("Waiting on select..."); @@ -342,7 +346,8 @@ int udhcpc_main(int argc, char **argv) packet_num++; } else { /* timed out, go back to init state */ - if (state == RENEW_REQUESTED) udhcp_run_script(NULL, "deconfig"); + if (state == RENEW_REQUESTED) + udhcp_run_script(NULL, "deconfig"); state = INIT_SELECTING; timeout = now; packet_num = 0; @@ -393,12 +398,12 @@ int udhcpc_main(int argc, char **argv) timeout = 0x7fffffff; break; } - } else if (retval > 0 && listen_mode != LISTEN_NONE && FD_ISSET(fd, &rfds)) { + } else if (retval > 0 && listen_mode != LISTEN_NONE && FD_ISSET(sockfd, &rfds)) { /* a packet is ready, read it */ if (listen_mode == LISTEN_KERNEL) - len = udhcp_get_packet(&packet, fd); - else len = get_raw_packet(&packet, fd); + len = udhcp_get_packet(&packet, sockfd); + else len = get_raw_packet(&packet, sockfd); if (len == -1 && errno != EINTR) { DEBUG("error on read, %s, reopening socket", strerror(errno)); @@ -418,7 +423,8 @@ int udhcpc_main(int argc, char **argv) continue; } - if ((message = get_option(&packet, DHCP_MESSAGE_TYPE)) == NULL) { + message = get_option(&packet, DHCP_MESSAGE_TYPE); + if (message == NULL) { bb_error_msg("cannot get option from packet - ignoring"); continue; } diff --git a/networking/udhcp/dhcpd.h b/networking/udhcp/dhcpd.h index 40959e4ae..7c4fe695a 100644 --- a/networking/udhcp/dhcpd.h +++ b/networking/udhcp/dhcpd.h @@ -14,81 +14,6 @@ /* where to find the DHCP server configuration file */ #define DHCPD_CONF_FILE "/etc/udhcpd.conf" -/*****************************************************************/ -/* Do not modify below here unless you know what you are doing!! */ -/*****************************************************************/ - -/* DHCP protocol -- see RFC 2131 */ -#define SERVER_PORT 67 -#define CLIENT_PORT 68 - -#define DHCP_MAGIC 0x63825363 - -/* DHCP option codes (partial list) */ -#define DHCP_PADDING 0x00 -#define DHCP_SUBNET 0x01 -#define DHCP_TIME_OFFSET 0x02 -#define DHCP_ROUTER 0x03 -#define DHCP_TIME_SERVER 0x04 -#define DHCP_NAME_SERVER 0x05 -#define DHCP_DNS_SERVER 0x06 -#define DHCP_LOG_SERVER 0x07 -#define DHCP_COOKIE_SERVER 0x08 -#define DHCP_LPR_SERVER 0x09 -#define DHCP_HOST_NAME 0x0c -#define DHCP_BOOT_SIZE 0x0d -#define DHCP_DOMAIN_NAME 0x0f -#define DHCP_SWAP_SERVER 0x10 -#define DHCP_ROOT_PATH 0x11 -#define DHCP_IP_TTL 0x17 -#define DHCP_MTU 0x1a -#define DHCP_BROADCAST 0x1c -#define DHCP_NTP_SERVER 0x2a -#define DHCP_WINS_SERVER 0x2c -#define DHCP_REQUESTED_IP 0x32 -#define DHCP_LEASE_TIME 0x33 -#define DHCP_OPTION_OVER 0x34 -#define DHCP_MESSAGE_TYPE 0x35 -#define DHCP_SERVER_ID 0x36 -#define DHCP_PARAM_REQ 0x37 -#define DHCP_MESSAGE 0x38 -#define DHCP_MAX_SIZE 0x39 -#define DHCP_T1 0x3a -#define DHCP_T2 0x3b -#define DHCP_VENDOR 0x3c -#define DHCP_CLIENT_ID 0x3d -#define DHCP_FQDN 0x51 - -#define DHCP_END 0xFF - - -#define BOOTREQUEST 1 -#define BOOTREPLY 2 - -#define ETH_10MB 1 -#define ETH_10MB_LEN 6 - -#define DHCPDISCOVER 1 -#define DHCPOFFER 2 -#define DHCPREQUEST 3 -#define DHCPDECLINE 4 -#define DHCPACK 5 -#define DHCPNAK 6 -#define DHCPRELEASE 7 -#define DHCPINFORM 8 - -#define BROADCAST_FLAG 0x8000 - -#define OPTION_FIELD 0 -#define FILE_FIELD 1 -#define SNAME_FIELD 2 - -/* miscellaneous defines */ -#define MAC_BCAST_ADDR (uint8_t *) "\xff\xff\xff\xff\xff\xff" -#define OPT_CODE 0 -#define OPT_LEN 1 -#define OPT_DATA 2 - struct option_set { uint8_t *data; struct option_set *next; @@ -140,13 +65,9 @@ struct dhcpOfferedAddr { uint32_t expires; /* host order */ }; -extern uint8_t blank_chaddr[]; - -void clear_lease(uint8_t *chaddr, uint32_t yiaddr); -struct dhcpOfferedAddr *add_lease(uint8_t *chaddr, uint32_t yiaddr, unsigned long lease); +struct dhcpOfferedAddr *add_lease(const uint8_t *chaddr, uint32_t yiaddr, unsigned long lease); int lease_expired(struct dhcpOfferedAddr *lease); -struct dhcpOfferedAddr *oldest_expired_lease(void); -struct dhcpOfferedAddr *find_lease_by_chaddr(uint8_t *chaddr); +struct dhcpOfferedAddr *find_lease_by_chaddr(const uint8_t *chaddr); struct dhcpOfferedAddr *find_lease_by_yiaddr(uint32_t yiaddr); uint32_t find_address(int check_expired); diff --git a/networking/udhcp/leases.c b/networking/udhcp/leases.c index 2f7847d74..5d8775f63 100644 --- a/networking/udhcp/leases.c +++ b/networking/udhcp/leases.c @@ -8,25 +8,41 @@ #include "dhcpd.h" -uint8_t blank_chaddr[] = {[0 ... 15] = 0}; +/* Find the oldest expired lease, NULL if there are no expired leases */ +static struct dhcpOfferedAddr *oldest_expired_lease(void) +{ + struct dhcpOfferedAddr *oldest = NULL; + unsigned long oldest_lease = time(0); + unsigned i; + + + for (i = 0; i < server_config.max_leases; i++) + if (oldest_lease > leases[i].expires) { + oldest_lease = leases[i].expires; + oldest = &(leases[i]); + } + return oldest; +} + /* clear every lease out that chaddr OR yiaddr matches and is nonzero */ -void clear_lease(uint8_t *chaddr, uint32_t yiaddr) +static void clear_lease(const uint8_t *chaddr, uint32_t yiaddr) { - unsigned int i, j; + unsigned i, j; for (j = 0; j < 16 && !chaddr[j]; j++); for (i = 0; i < server_config.max_leases; i++) - if ((j != 16 && !memcmp(leases[i].chaddr, chaddr, 16)) || - (yiaddr && leases[i].yiaddr == yiaddr)) { + if ((j != 16 && memcmp(leases[i].chaddr, chaddr, 16) != 0) + || (yiaddr && leases[i].yiaddr == yiaddr) + ) { memset(&(leases[i]), 0, sizeof(struct dhcpOfferedAddr)); } } /* add a lease into the table, clearing out any old ones */ -struct dhcpOfferedAddr *add_lease(uint8_t *chaddr, uint32_t yiaddr, unsigned long lease) +struct dhcpOfferedAddr *add_lease(const uint8_t *chaddr, uint32_t yiaddr, unsigned long lease) { struct dhcpOfferedAddr *oldest; @@ -52,31 +68,14 @@ int lease_expired(struct dhcpOfferedAddr *lease) } -/* Find the oldest expired lease, NULL if there are no expired leases */ -struct dhcpOfferedAddr *oldest_expired_lease(void) -{ - struct dhcpOfferedAddr *oldest = NULL; - unsigned long oldest_lease = time(0); - unsigned int i; - - - for (i = 0; i < server_config.max_leases; i++) - if (oldest_lease > leases[i].expires) { - oldest_lease = leases[i].expires; - oldest = &(leases[i]); - } - return oldest; - -} - - /* Find the first lease that matches chaddr, NULL if no match */ -struct dhcpOfferedAddr *find_lease_by_chaddr(uint8_t *chaddr) +struct dhcpOfferedAddr *find_lease_by_chaddr(const uint8_t *chaddr) { - unsigned int i; + unsigned i; for (i = 0; i < server_config.max_leases; i++) - if (!memcmp(leases[i].chaddr, chaddr, 16)) return &(leases[i]); + if (!memcmp(leases[i].chaddr, chaddr, 16)) + return &(leases[i]); return NULL; } @@ -85,10 +84,11 @@ struct dhcpOfferedAddr *find_lease_by_chaddr(uint8_t *chaddr) /* Find the first lease that matches yiaddr, NULL is no match */ struct dhcpOfferedAddr *find_lease_by_yiaddr(uint32_t yiaddr) { - unsigned int i; + unsigned i; for (i = 0; i < server_config.max_leases; i++) - if (leases[i].yiaddr == yiaddr) return &(leases[i]); + if (leases[i].yiaddr == yiaddr) + return &(leases[i]); return NULL; } @@ -97,6 +97,8 @@ struct dhcpOfferedAddr *find_lease_by_yiaddr(uint32_t yiaddr) /* check is an IP is taken, if it is, add it to the lease table */ static int check_ip(uint32_t addr) { + static const uint8_t blank_chaddr[16]; /* 16 zero bytes */ + struct in_addr temp; if (arpping(addr, server_config.server, server_config.arp, server_config.interface) == 0) { @@ -105,7 +107,8 @@ static int check_ip(uint32_t addr) inet_ntoa(temp), server_config.conflict_time); add_lease(blank_chaddr, addr, server_config.conflict_time); return 1; - } else return 0; + } + return 0; } @@ -125,7 +128,7 @@ uint32_t find_address(int check_expired) /* ie, 192.168.55.255 */ if ((addr & 0xFF) == 0xFF) continue; - /* Only do if it isn't an 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 */ @@ -133,11 +136,10 @@ uint32_t find_address(int check_expired) lease = find_lease_by_yiaddr(ret); /* 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) ) { return ret; - break; } } } diff --git a/networking/udhcp/options.h b/networking/udhcp/options.h index 11f013fd4..5e9adf881 100644 --- a/networking/udhcp/options.h +++ b/networking/udhcp/options.h @@ -23,6 +23,80 @@ enum { #define OPTION_REQ 0x10 /* have the client request this option */ #define OPTION_LIST 0x20 /* There can be a list of 1 or more of these */ +/*****************************************************************/ +/* Do not modify below here unless you know what you are doing!! */ +/*****************************************************************/ + +/* DHCP protocol -- see RFC 2131 */ +#define SERVER_PORT 67 +#define CLIENT_PORT 68 + +#define DHCP_MAGIC 0x63825363 + +/* DHCP option codes (partial list) */ +#define DHCP_PADDING 0x00 +#define DHCP_SUBNET 0x01 +#define DHCP_TIME_OFFSET 0x02 +#define DHCP_ROUTER 0x03 +#define DHCP_TIME_SERVER 0x04 +#define DHCP_NAME_SERVER 0x05 +#define DHCP_DNS_SERVER 0x06 +#define DHCP_LOG_SERVER 0x07 +#define DHCP_COOKIE_SERVER 0x08 +#define DHCP_LPR_SERVER 0x09 +#define DHCP_HOST_NAME 0x0c +#define DHCP_BOOT_SIZE 0x0d +#define DHCP_DOMAIN_NAME 0x0f +#define DHCP_SWAP_SERVER 0x10 +#define DHCP_ROOT_PATH 0x11 +#define DHCP_IP_TTL 0x17 +#define DHCP_MTU 0x1a +#define DHCP_BROADCAST 0x1c +#define DHCP_NTP_SERVER 0x2a +#define DHCP_WINS_SERVER 0x2c +#define DHCP_REQUESTED_IP 0x32 +#define DHCP_LEASE_TIME 0x33 +#define DHCP_OPTION_OVER 0x34 +#define DHCP_MESSAGE_TYPE 0x35 +#define DHCP_SERVER_ID 0x36 +#define DHCP_PARAM_REQ 0x37 +#define DHCP_MESSAGE 0x38 +#define DHCP_MAX_SIZE 0x39 +#define DHCP_T1 0x3a +#define DHCP_T2 0x3b +#define DHCP_VENDOR 0x3c +#define DHCP_CLIENT_ID 0x3d +#define DHCP_FQDN 0x51 + +#define DHCP_END 0xFF + + +#define BOOTREQUEST 1 +#define BOOTREPLY 2 + +#define ETH_10MB 1 +#define ETH_10MB_LEN 6 + +#define DHCPDISCOVER 1 +#define DHCPOFFER 2 +#define DHCPREQUEST 3 +#define DHCPDECLINE 4 +#define DHCPACK 5 +#define DHCPNAK 6 +#define DHCPRELEASE 7 +#define DHCPINFORM 8 + +#define BROADCAST_FLAG 0x8000 + +#define OPTION_FIELD 0 +#define FILE_FIELD 1 +#define SNAME_FIELD 2 + +/* miscellaneous defines */ +#define OPT_CODE 0 +#define OPT_LEN 1 +#define OPT_DATA 2 + struct dhcp_option { char name[12]; char flags; diff --git a/networking/udhcp/packet.c b/networking/udhcp/packet.c index 25c55faab..da3807773 100644 --- a/networking/udhcp/packet.c +++ b/networking/udhcp/packet.c @@ -112,7 +112,7 @@ uint16_t udhcp_checksum(void *addr, int count) void BUG_sizeof_struct_udp_dhcp_packet_must_be_576(void); int udhcp_raw_packet(struct dhcpMessage *payload, uint32_t source_ip, int source_port, - uint32_t dest_ip, int dest_port, uint8_t *dest_arp, int ifindex) + uint32_t dest_ip, int dest_port, const uint8_t *dest_arp, int ifindex) { int fd; int result; diff --git a/networking/udhcp/script.c b/networking/udhcp/script.c index dc8ff7a1c..98706a592 100644 --- a/networking/udhcp/script.c +++ b/networking/udhcp/script.c @@ -9,7 +9,6 @@ */ #include "common.h" -#include "dhcpd.h" #include "dhcpc.h" #include "options.h" @@ -77,7 +76,7 @@ static char *alloc_fill_opts(uint8_t *option, const struct dhcp_option *type_p) switch (type) { case OPTION_IP_PAIR: dest += sprintip(dest, "", option); - *(dest++) = '/'; + *dest++ = '/'; option += 4; optlen = 4; case OPTION_IP: /* Works regardless of host byte order. */ @@ -132,34 +131,42 @@ static char **fill_envp(struct dhcpMessage *packet) int num_options = 0; int i, j; char **envp; + char *var; uint8_t *temp; struct in_addr subnet; char over = 0; - if (packet == NULL) - num_options = 0; - else { - for (i = 0; dhcp_options[i].code; i++) + if (packet) { + for (i = 0; dhcp_options[i].code; i++) { if (get_option(packet, dhcp_options[i].code)) { num_options++; if (dhcp_options[i].code == DHCP_SUBNET) num_options++; /* for mton */ } - if (packet->siaddr) num_options++; - if ((temp = get_option(packet, DHCP_OPTION_OVER))) + } + if (packet->siaddr) + num_options++; + temp = get_option(packet, DHCP_OPTION_OVER); + if (temp) over = *temp; - if (!(over & FILE_FIELD) && packet->file[0]) num_options++; - if (!(over & SNAME_FIELD) && packet->sname[0]) num_options++; + if (!(over & FILE_FIELD) && packet->file[0]) + num_options++; + if (!(over & SNAME_FIELD) && packet->sname[0]) + num_options++; } envp = xzalloc(sizeof(char *) * (num_options + 5)); j = 0; envp[j++] = xasprintf("interface=%s", client_config.interface); - envp[j++] = xasprintf("PATH=%s", - getenv("PATH") ? : "/bin:/usr/bin:/sbin:/usr/sbin"); - envp[j++] = xasprintf("HOME=%s", getenv("HOME") ? : "/"); + var = getenv("PATH"); + if (var) + envp[j++] = xasprintf("PATH=%s", var); + var = getenv("HOME"); + if (var) + envp[j++] = xasprintf("HOME=%s", var); - if (packet == NULL) return envp; + if (packet == NULL) + return envp; envp[j] = xmalloc(sizeof("ip=255.255.255.255")); sprintip(envp[j++], "ip=", (uint8_t *) &packet->yiaddr); @@ -206,19 +213,20 @@ void udhcp_run_script(struct dhcpMessage *packet, const char *name) DEBUG("vfork'ing and execle'ing %s", client_config.script); envp = fill_envp(packet); + /* call script */ +// can we use wait4pid(spawn(...)) here? pid = vfork(); - if (pid) { - waitpid(pid, NULL, 0); - for (curr = envp; *curr; curr++) free(*curr); - free(envp); - return; - } else if (pid == 0) { + if (pid < 0) return; + if (pid == 0) { /* close fd's? */ /* exec script */ execle(client_config.script, client_config.script, name, NULL, envp); - bb_perror_msg("script %s failed", client_config.script); - exit(1); + bb_perror_msg_and_die("script %s failed", client_config.script); } + waitpid(pid, NULL, 0); + for (curr = envp; *curr; curr++) + free(*curr); + free(envp); } diff --git a/networking/udhcp/serverpacket.c b/networking/udhcp/serverpacket.c index 8889fda86..e1a88addd 100644 --- a/networking/udhcp/serverpacket.c +++ b/networking/udhcp/serverpacket.c @@ -38,7 +38,7 @@ static int send_packet_to_relay(struct dhcpMessage *payload) /* send a packet to a specific arp address and ip address by creating our own ip packet */ static int send_packet_to_client(struct dhcpMessage *payload, int force_broadcast) { - uint8_t *chaddr; + const uint8_t *chaddr; uint32_t ciaddr; if (force_broadcast) { |