udhcp: MAC_BCAST_ADDR and blank_chaddr are in fact constant, move to rodata.
a few global variables reduced to smallints function old new delta add_lease 75 227 +152 static.blank_chaddr - 16 +16 MAC_BCAST_ADDR - 6 +6 sockfd 4 8 +4 udhcp_run_script 1153 1155 +2 state 8 5 -3 listen_mode 4 1 -3 perform_release 152 148 -4 fd 8 4 -4 blank_chaddr 16 - -16 udhcpc_main 2518 2497 -21 .rodata 131864 131832 -32 oldest_expired_lease 61 - -61 clear_lease 127 - -127 ------------------------------------------------------------------------------ (add/remove: 2/3 grow/shrink: 3/6 up/down: 180/-271) Total: -91 bytes
This commit is contained in:
parent
bb5b01c7c7
commit
fbd2918f5c
@ -15,6 +15,8 @@
|
|||||||
#include "common.h"
|
#include "common.h"
|
||||||
|
|
||||||
|
|
||||||
|
const uint8_t MAC_BCAST_ADDR[6] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
|
||||||
|
|
||||||
long uptime(void)
|
long uptime(void)
|
||||||
{
|
{
|
||||||
struct sysinfo info;
|
struct sysinfo info;
|
||||||
|
@ -14,8 +14,7 @@
|
|||||||
|
|
||||||
#define DEFAULT_SCRIPT "/usr/share/udhcpc/default.script"
|
#define DEFAULT_SCRIPT "/usr/share/udhcpc/default.script"
|
||||||
|
|
||||||
#define COMBINED_BINARY
|
extern const uint8_t MAC_BCAST_ADDR[6]; /* six all-ones */
|
||||||
|
|
||||||
|
|
||||||
/*** packet.h ***/
|
/*** packet.h ***/
|
||||||
|
|
||||||
@ -52,7 +51,8 @@ int udhcp_get_packet(struct dhcpMessage *packet, int fd);
|
|||||||
uint16_t udhcp_checksum(void *addr, int count);
|
uint16_t udhcp_checksum(void *addr, int count);
|
||||||
int udhcp_raw_packet(struct dhcpMessage *payload,
|
int udhcp_raw_packet(struct dhcpMessage *payload,
|
||||||
uint32_t source_ip, int source_port,
|
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,
|
int udhcp_kernel_packet(struct dhcpMessage *payload,
|
||||||
uint32_t source_ip, int source_port,
|
uint32_t source_ip, int source_port,
|
||||||
uint32_t dest_ip, int dest_port);
|
uint32_t dest_ip, int dest_port);
|
||||||
|
@ -17,22 +17,23 @@
|
|||||||
#include "options.h"
|
#include "options.h"
|
||||||
|
|
||||||
|
|
||||||
static int state;
|
|
||||||
/* Something is definitely wrong here. IPv4 addresses
|
/* Something is definitely wrong here. IPv4 addresses
|
||||||
* in variables of type long?? BTW, we use inet_ntoa()
|
* 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 (!)
|
* 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 long requested_ip; /* = 0 */
|
static unsigned long requested_ip; /* = 0 */
|
||||||
static uint32_t server_addr;
|
static uint32_t server_addr;
|
||||||
static unsigned long timeout;
|
|
||||||
static int packet_num; /* = 0 */
|
static int packet_num; /* = 0 */
|
||||||
static int fd = -1;
|
static int sockfd = -1;
|
||||||
|
|
||||||
#define LISTEN_NONE 0
|
#define LISTEN_NONE 0
|
||||||
#define LISTEN_KERNEL 1
|
#define LISTEN_KERNEL 1
|
||||||
#define LISTEN_RAW 2
|
#define LISTEN_RAW 2
|
||||||
static int listen_mode;
|
static smallint listen_mode;
|
||||||
|
|
||||||
|
static smallint state;
|
||||||
|
|
||||||
struct client_config_t client_config;
|
struct client_config_t client_config;
|
||||||
|
|
||||||
@ -42,8 +43,10 @@ static void change_mode(int new_mode)
|
|||||||
{
|
{
|
||||||
DEBUG("entering %s listen mode",
|
DEBUG("entering %s listen mode",
|
||||||
new_mode ? (new_mode == 1 ? "kernel" : "raw") : "none");
|
new_mode ? (new_mode == 1 ? "kernel" : "raw") : "none");
|
||||||
if (fd >= 0) close(fd);
|
if (sockfd >= 0) {
|
||||||
fd = -1;
|
close(sockfd);
|
||||||
|
sockfd = -1;
|
||||||
|
}
|
||||||
listen_mode = new_mode;
|
listen_mode = new_mode;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -111,6 +114,7 @@ static void client_background(void)
|
|||||||
* If that will be properly disabled for NOMMU, client_background()
|
* If that will be properly disabled for NOMMU, client_background()
|
||||||
* will work on NOMMU too */
|
* will work on NOMMU too */
|
||||||
#else
|
#else
|
||||||
|
// chdir(/) is problematic. Imagine that e.g. pidfile name is RELATIVE! what will unlink do then, eh?
|
||||||
bb_daemonize(DAEMON_CHDIR_ROOT);
|
bb_daemonize(DAEMON_CHDIR_ROOT);
|
||||||
logmode &= ~LOGMODE_STDIO;
|
logmode &= ~LOGMODE_STDIO;
|
||||||
#endif
|
#endif
|
||||||
@ -289,13 +293,13 @@ int udhcpc_main(int argc, char **argv)
|
|||||||
tv.tv_sec = timeout - uptime();
|
tv.tv_sec = timeout - uptime();
|
||||||
tv.tv_usec = 0;
|
tv.tv_usec = 0;
|
||||||
|
|
||||||
if (listen_mode != LISTEN_NONE && fd < 0) {
|
if (listen_mode != LISTEN_NONE && sockfd < 0) {
|
||||||
if (listen_mode == LISTEN_KERNEL)
|
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
|
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) {
|
if (tv.tv_sec > 0) {
|
||||||
DEBUG("Waiting on select...");
|
DEBUG("Waiting on select...");
|
||||||
@ -342,7 +346,8 @@ int udhcpc_main(int argc, char **argv)
|
|||||||
packet_num++;
|
packet_num++;
|
||||||
} else {
|
} else {
|
||||||
/* timed out, go back to init state */
|
/* 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;
|
state = INIT_SELECTING;
|
||||||
timeout = now;
|
timeout = now;
|
||||||
packet_num = 0;
|
packet_num = 0;
|
||||||
@ -393,12 +398,12 @@ int udhcpc_main(int argc, char **argv)
|
|||||||
timeout = 0x7fffffff;
|
timeout = 0x7fffffff;
|
||||||
break;
|
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 */
|
/* a packet is ready, read it */
|
||||||
|
|
||||||
if (listen_mode == LISTEN_KERNEL)
|
if (listen_mode == LISTEN_KERNEL)
|
||||||
len = udhcp_get_packet(&packet, fd);
|
len = udhcp_get_packet(&packet, sockfd);
|
||||||
else len = get_raw_packet(&packet, fd);
|
else len = get_raw_packet(&packet, sockfd);
|
||||||
|
|
||||||
if (len == -1 && errno != EINTR) {
|
if (len == -1 && errno != EINTR) {
|
||||||
DEBUG("error on read, %s, reopening socket", strerror(errno));
|
DEBUG("error on read, %s, reopening socket", strerror(errno));
|
||||||
@ -418,7 +423,8 @@ int udhcpc_main(int argc, char **argv)
|
|||||||
continue;
|
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");
|
bb_error_msg("cannot get option from packet - ignoring");
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -14,81 +14,6 @@
|
|||||||
/* where to find the DHCP server configuration file */
|
/* where to find the DHCP server configuration file */
|
||||||
#define DHCPD_CONF_FILE "/etc/udhcpd.conf"
|
#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 {
|
struct option_set {
|
||||||
uint8_t *data;
|
uint8_t *data;
|
||||||
struct option_set *next;
|
struct option_set *next;
|
||||||
@ -140,13 +65,9 @@ struct dhcpOfferedAddr {
|
|||||||
uint32_t expires; /* host order */
|
uint32_t expires; /* host order */
|
||||||
};
|
};
|
||||||
|
|
||||||
extern uint8_t blank_chaddr[];
|
struct dhcpOfferedAddr *add_lease(const uint8_t *chaddr, uint32_t yiaddr, unsigned long lease);
|
||||||
|
|
||||||
void clear_lease(uint8_t *chaddr, uint32_t yiaddr);
|
|
||||||
struct dhcpOfferedAddr *add_lease(uint8_t *chaddr, uint32_t yiaddr, unsigned long lease);
|
|
||||||
int lease_expired(struct dhcpOfferedAddr *lease);
|
int lease_expired(struct dhcpOfferedAddr *lease);
|
||||||
struct dhcpOfferedAddr *oldest_expired_lease(void);
|
struct dhcpOfferedAddr *find_lease_by_chaddr(const uint8_t *chaddr);
|
||||||
struct dhcpOfferedAddr *find_lease_by_chaddr(uint8_t *chaddr);
|
|
||||||
struct dhcpOfferedAddr *find_lease_by_yiaddr(uint32_t yiaddr);
|
struct dhcpOfferedAddr *find_lease_by_yiaddr(uint32_t yiaddr);
|
||||||
uint32_t find_address(int check_expired);
|
uint32_t find_address(int check_expired);
|
||||||
|
|
||||||
|
@ -8,25 +8,41 @@
|
|||||||
#include "dhcpd.h"
|
#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 */
|
/* 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 (j = 0; j < 16 && !chaddr[j]; j++);
|
||||||
|
|
||||||
for (i = 0; i < server_config.max_leases; i++)
|
for (i = 0; i < server_config.max_leases; i++)
|
||||||
if ((j != 16 && !memcmp(leases[i].chaddr, chaddr, 16)) ||
|
if ((j != 16 && memcmp(leases[i].chaddr, chaddr, 16) != 0)
|
||||||
(yiaddr && leases[i].yiaddr == yiaddr)) {
|
|| (yiaddr && leases[i].yiaddr == yiaddr)
|
||||||
|
) {
|
||||||
memset(&(leases[i]), 0, sizeof(struct dhcpOfferedAddr));
|
memset(&(leases[i]), 0, sizeof(struct dhcpOfferedAddr));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* add a lease into the table, clearing out any old ones */
|
/* 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;
|
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 */
|
/* 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++)
|
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;
|
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 */
|
/* Find the first lease that matches yiaddr, NULL is no match */
|
||||||
struct dhcpOfferedAddr *find_lease_by_yiaddr(uint32_t yiaddr)
|
struct dhcpOfferedAddr *find_lease_by_yiaddr(uint32_t yiaddr)
|
||||||
{
|
{
|
||||||
unsigned int i;
|
unsigned i;
|
||||||
|
|
||||||
for (i = 0; i < server_config.max_leases; 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;
|
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 */
|
/* check is an IP is taken, if it is, add it to the lease table */
|
||||||
static int check_ip(uint32_t addr)
|
static int check_ip(uint32_t addr)
|
||||||
{
|
{
|
||||||
|
static const uint8_t blank_chaddr[16]; /* 16 zero bytes */
|
||||||
|
|
||||||
struct in_addr temp;
|
struct in_addr temp;
|
||||||
|
|
||||||
if (arpping(addr, server_config.server, server_config.arp, server_config.interface) == 0) {
|
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);
|
inet_ntoa(temp), 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 1;
|
||||||
} else return 0;
|
}
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -125,7 +128,7 @@ uint32_t find_address(int check_expired)
|
|||||||
/* ie, 192.168.55.255 */
|
/* ie, 192.168.55.255 */
|
||||||
if ((addr & 0xFF) == 0xFF) continue;
|
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))) {
|
if (!reservedIp(server_config.static_leases, htonl(addr))) {
|
||||||
|
|
||||||
/* lease is not taken */
|
/* lease is not taken */
|
||||||
@ -137,7 +140,6 @@ uint32_t find_address(int check_expired)
|
|||||||
&& /* and it isn't on the network */ !check_ip(ret)
|
&& /* and it isn't on the network */ !check_ip(ret)
|
||||||
) {
|
) {
|
||||||
return ret;
|
return ret;
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -23,6 +23,80 @@ enum {
|
|||||||
#define OPTION_REQ 0x10 /* have the client request this option */
|
#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 */
|
#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 {
|
struct dhcp_option {
|
||||||
char name[12];
|
char name[12];
|
||||||
char flags;
|
char flags;
|
||||||
|
@ -112,7 +112,7 @@ uint16_t udhcp_checksum(void *addr, int count)
|
|||||||
void BUG_sizeof_struct_udp_dhcp_packet_must_be_576(void);
|
void BUG_sizeof_struct_udp_dhcp_packet_must_be_576(void);
|
||||||
int udhcp_raw_packet(struct dhcpMessage *payload,
|
int udhcp_raw_packet(struct dhcpMessage *payload,
|
||||||
uint32_t source_ip, int source_port,
|
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 fd;
|
||||||
int result;
|
int result;
|
||||||
|
@ -9,7 +9,6 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
#include "dhcpd.h"
|
|
||||||
#include "dhcpc.h"
|
#include "dhcpc.h"
|
||||||
#include "options.h"
|
#include "options.h"
|
||||||
|
|
||||||
@ -77,7 +76,7 @@ static char *alloc_fill_opts(uint8_t *option, const struct dhcp_option *type_p)
|
|||||||
switch (type) {
|
switch (type) {
|
||||||
case OPTION_IP_PAIR:
|
case OPTION_IP_PAIR:
|
||||||
dest += sprintip(dest, "", option);
|
dest += sprintip(dest, "", option);
|
||||||
*(dest++) = '/';
|
*dest++ = '/';
|
||||||
option += 4;
|
option += 4;
|
||||||
optlen = 4;
|
optlen = 4;
|
||||||
case OPTION_IP: /* Works regardless of host byte order. */
|
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 num_options = 0;
|
||||||
int i, j;
|
int i, j;
|
||||||
char **envp;
|
char **envp;
|
||||||
|
char *var;
|
||||||
uint8_t *temp;
|
uint8_t *temp;
|
||||||
struct in_addr subnet;
|
struct in_addr subnet;
|
||||||
char over = 0;
|
char over = 0;
|
||||||
|
|
||||||
if (packet == NULL)
|
if (packet) {
|
||||||
num_options = 0;
|
for (i = 0; dhcp_options[i].code; i++) {
|
||||||
else {
|
|
||||||
for (i = 0; dhcp_options[i].code; i++)
|
|
||||||
if (get_option(packet, dhcp_options[i].code)) {
|
if (get_option(packet, dhcp_options[i].code)) {
|
||||||
num_options++;
|
num_options++;
|
||||||
if (dhcp_options[i].code == DHCP_SUBNET)
|
if (dhcp_options[i].code == DHCP_SUBNET)
|
||||||
num_options++; /* for mton */
|
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;
|
over = *temp;
|
||||||
if (!(over & FILE_FIELD) && packet->file[0]) num_options++;
|
if (!(over & FILE_FIELD) && packet->file[0])
|
||||||
if (!(over & SNAME_FIELD) && packet->sname[0]) num_options++;
|
num_options++;
|
||||||
|
if (!(over & SNAME_FIELD) && packet->sname[0])
|
||||||
|
num_options++;
|
||||||
}
|
}
|
||||||
|
|
||||||
envp = xzalloc(sizeof(char *) * (num_options + 5));
|
envp = xzalloc(sizeof(char *) * (num_options + 5));
|
||||||
j = 0;
|
j = 0;
|
||||||
envp[j++] = xasprintf("interface=%s", client_config.interface);
|
envp[j++] = xasprintf("interface=%s", client_config.interface);
|
||||||
envp[j++] = xasprintf("PATH=%s",
|
var = getenv("PATH");
|
||||||
getenv("PATH") ? : "/bin:/usr/bin:/sbin:/usr/sbin");
|
if (var)
|
||||||
envp[j++] = xasprintf("HOME=%s", getenv("HOME") ? : "/");
|
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"));
|
envp[j] = xmalloc(sizeof("ip=255.255.255.255"));
|
||||||
sprintip(envp[j++], "ip=", (uint8_t *) &packet->yiaddr);
|
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);
|
DEBUG("vfork'ing and execle'ing %s", client_config.script);
|
||||||
|
|
||||||
envp = fill_envp(packet);
|
envp = fill_envp(packet);
|
||||||
|
|
||||||
/* call script */
|
/* call script */
|
||||||
|
// can we use wait4pid(spawn(...)) here?
|
||||||
pid = vfork();
|
pid = vfork();
|
||||||
if (pid) {
|
if (pid < 0) return;
|
||||||
waitpid(pid, NULL, 0);
|
if (pid == 0) {
|
||||||
for (curr = envp; *curr; curr++) free(*curr);
|
|
||||||
free(envp);
|
|
||||||
return;
|
|
||||||
} else if (pid == 0) {
|
|
||||||
/* close fd's? */
|
/* close fd's? */
|
||||||
/* exec script */
|
/* exec script */
|
||||||
execle(client_config.script, client_config.script,
|
execle(client_config.script, client_config.script,
|
||||||
name, NULL, envp);
|
name, NULL, envp);
|
||||||
bb_perror_msg("script %s failed", client_config.script);
|
bb_perror_msg_and_die("script %s failed", client_config.script);
|
||||||
exit(1);
|
|
||||||
}
|
}
|
||||||
|
waitpid(pid, NULL, 0);
|
||||||
|
for (curr = envp; *curr; curr++)
|
||||||
|
free(*curr);
|
||||||
|
free(envp);
|
||||||
}
|
}
|
||||||
|
@ -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 */
|
/* 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)
|
static int send_packet_to_client(struct dhcpMessage *payload, int force_broadcast)
|
||||||
{
|
{
|
||||||
uint8_t *chaddr;
|
const uint8_t *chaddr;
|
||||||
uint32_t ciaddr;
|
uint32_t ciaddr;
|
||||||
|
|
||||||
if (force_broadcast) {
|
if (force_broadcast) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user