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:
Denis Vlasenko 2007-04-07 01:05:47 +00:00
parent bb5b01c7c7
commit fbd2918f5c
9 changed files with 169 additions and 156 deletions

View File

@ -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;

View File

@ -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);

View File

@ -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;
}

View File

@ -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);

View File

@ -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;
}
}
}

View File

@ -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;

View File

@ -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;

View File

@ -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);
}

View File

@ -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) {