udhcpc: convert to getopt32

This commit is contained in:
Denis Vlasenko 2006-11-27 23:43:28 +00:00
parent 30d7a346e6
commit e2d3ded354
4 changed files with 154 additions and 170 deletions

View File

@ -1,4 +1,13 @@
/* vi: set sw=4 ts=4: */ /* vi: set sw=4 ts=4: */
/*
* This file suffers from chronically incorrect tabification
* of messages. Before editing this file:
* 1. Switch you editor to 8-space tab mode.
* 2. Do not use \t in messages, use real tab character.
* 3. Start each source line with message as follows:
* |<7 spaces>"text with tabs"
*/
#ifndef __BB_USAGE_H__ #ifndef __BB_USAGE_H__
#define __BB_USAGE_H__ #define __BB_USAGE_H__

View File

@ -33,25 +33,8 @@ static int fd = -1;
#define LISTEN_RAW 2 #define LISTEN_RAW 2
static int listen_mode; static int listen_mode;
struct client_config_t client_config = { struct client_config_t client_config;
/* Default options. */
.abort_if_no_lease = 0,
.foreground = 0,
.quit_after_lease = 0,
.release_on_quit = 0,
.background_if_no_lease = 0,
.interface = "eth0",
.pidfile = NULL,
.script = DEFAULT_SCRIPT,
.clientid = NULL,
.vendorclass = NULL,
.hostname = NULL,
.fqdn = NULL,
.ifindex = 0,
.retries = 3,
.timeout = 3,
.arp = "\0\0\0\0\0\0", /* appease gcc-3.0 */
};
/* just a little helper */ /* just a little helper */
static void change_mode(int new_mode) static void change_mode(int new_mode)
@ -126,139 +109,137 @@ static void client_background(void)
} }
static uint8_t* alloc_dhcp_option(int code, const char *str, int extra)
{
uint8_t *storage;
int len = strlen(str);
if (len > 255) len = 255;
storage = xzalloc(len + extra + OPT_DATA);
storage[OPT_CODE] = code;
storage[OPT_LEN] = len + extra;
memcpy(storage + extra + OPT_DATA, str, len);
return storage;
}
int udhcpc_main(int argc, char *argv[]) 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;
unsigned long t1 = 0, t2 = 0, xid = 0; unsigned long t1 = 0, t2 = 0, xid = 0;
unsigned long start = 0, lease = 0; unsigned long start = 0, lease = 0;
fd_set rfds;
int retval;
struct timeval tv;
int c, len;
struct dhcpMessage packet;
struct in_addr temp_addr;
long now; long now;
unsigned opt;
int max_fd; int max_fd;
int sig; int sig;
int retval;
int len;
int no_clientid = 0; int no_clientid = 0;
fd_set rfds;
struct timeval tv;
struct dhcpMessage packet;
struct in_addr temp_addr;
enum {
OPT_c = 1 << 0,
OPT_C = 1 << 1,
OPT_V = 1 << 2,
OPT_f = 1 << 3,
OPT_b = 1 << 4,
OPT_H = 1 << 5,
OPT_h = 1 << 6,
OPT_F = 1 << 7,
OPT_i = 1 << 8,
OPT_n = 1 << 9,
OPT_p = 1 << 10,
OPT_q = 1 << 11,
OPT_R = 1 << 12,
OPT_r = 1 << 13,
OPT_s = 1 << 14,
OPT_T = 1 << 15,
OPT_t = 1 << 16,
OPT_v = 1 << 17,
};
static const struct option arg_options[] = { static const struct option arg_options[] = {
{"clientid", required_argument, 0, 'c'}, { "clientid", required_argument, 0, 'c' },
{"clientid-none", no_argument, 0, 'C'}, { "clientid-none", no_argument, 0, 'C' },
{"vendorclass", required_argument, 0, 'V'}, { "vendorclass", required_argument, 0, 'V' },
{"foreground", no_argument, 0, 'f'}, { "foreground", no_argument, 0, 'f' },
{"background", no_argument, 0, 'b'}, { "background", no_argument, 0, 'b' },
{"hostname", required_argument, 0, 'H'}, { "hostname", required_argument, 0, 'H' },
{"hostname", required_argument, 0, 'h'}, { "hostname", required_argument, 0, 'h' },
{"fqdn", required_argument, 0, 'F'}, { "fqdn", required_argument, 0, 'F' },
{"interface", required_argument, 0, 'i'}, { "interface", required_argument, 0, 'i' },
{"now", no_argument, 0, 'n'}, { "now", no_argument, 0, 'n' },
{"pidfile", required_argument, 0, 'p'}, { "pidfile", required_argument, 0, 'p' },
{"quit", no_argument, 0, 'q'}, { "quit", no_argument, 0, 'q' },
{"release", no_argument, 0, 'R'}, { "release", no_argument, 0, 'R' },
{"request", required_argument, 0, 'r'}, { "request", required_argument, 0, 'r' },
{"script", required_argument, 0, 's'}, { "script", required_argument, 0, 's' },
{"timeout", required_argument, 0, 'T'}, { "timeout", required_argument, 0, 'T' },
{"version", no_argument, 0, 'v'}, { "version", no_argument, 0, 'v' },
{"retries", required_argument, 0, 't'}, { "retries", required_argument, 0, 't' },
{0, 0, 0, 0} { 0, 0, 0, 0 }
}; };
/* get options */ /* Default options. */
while (1) { client_config.interface = "eth0";
int option_index = 0; client_config.script = DEFAULT_SCRIPT;
c = getopt_long(argc, argv, "c:CV:fbH:h:F:i:np:qRr:s:T:t:v", arg_options, &option_index); client_config.retries = 3;
if (c == -1) break; client_config.timeout = 3;
switch (c) { /* Parse command line */
case 'c': opt_complementary = "?:c--C:C--c" // mutually exclusive
if (no_clientid) bb_show_usage(); ":hH:Hh"; // -h and -H are the same
len = strlen(optarg) > 255 ? 255 : strlen(optarg); applet_long_options = arg_options;
free(client_config.clientid); opt = getopt32(argc, argv, "c:CV:fbH:h:F:i:np:qRr:s:T:t:v",
client_config.clientid = xmalloc(len + 2); &str_c, &str_V, &str_h, &str_h, &str_F,
client_config.clientid[OPT_CODE] = DHCP_CLIENT_ID; &client_config.interface, &client_config.pidfile, &str_r,
client_config.clientid[OPT_LEN] = len; &client_config.script, &str_T, &str_t
client_config.clientid[OPT_DATA] = '\0'; );
strncpy((char*)client_config.clientid + OPT_DATA, optarg, len);
break; if (opt & OPT_c)
case 'C': client_config.clientid = alloc_dhcp_option(DHCP_CLIENT_ID, str_c, 0);
if (client_config.clientid) bb_show_usage(); if (opt & OPT_C)
no_clientid = 1; no_clientid = 1;
break; if (opt & OPT_V)
case 'V': client_config.vendorclass = alloc_dhcp_option(DHCP_VENDOR, str_V, 0);
len = strlen(optarg) > 255 ? 255 : strlen(optarg); if (opt & OPT_f)
free(client_config.vendorclass); client_config.foreground = 1;
client_config.vendorclass = xmalloc(len + 2); if (opt & OPT_b)
client_config.vendorclass[OPT_CODE] = DHCP_VENDOR; client_config.background_if_no_lease = 1;
client_config.vendorclass[OPT_LEN] = len; if (opt & OPT_h)
strncpy((char*)client_config.vendorclass + OPT_DATA, optarg, len); client_config.hostname = alloc_dhcp_option(DHCP_HOST_NAME, str_h, 0);
break; if (opt & OPT_F) {
case 'f': client_config.fqdn = alloc_dhcp_option(DHCP_FQDN, str_F, 3);
client_config.foreground = 1; /* Flags: 0000NEOS
break; S: 1 => Client requests Server to update A RR in DNS as well as PTR
case 'b': O: 1 => Server indicates to client that DNS has been updated regardless
client_config.background_if_no_lease = 1; E: 1 => Name data is DNS format, i.e. <4>host<6>domain<4>com<0> not "host.domain.com"
break; N: 1 => Client requests Server to not update DNS
case 'h': */
case 'H': client_config.fqdn[OPT_DATA + 0] = 0x1;
len = strlen(optarg) > 255 ? 255 : strlen(optarg); /* client_config.fqdn[OPT_DATA + 1] = 0; - redundant */
free(client_config.hostname); /* client_config.fqdn[OPT_DATA + 2] = 0; - redundant */
client_config.hostname = xmalloc(len + 2); }
client_config.hostname[OPT_CODE] = DHCP_HOST_NAME; // if (opt & OPT_i) client_config.interface = ...
client_config.hostname[OPT_LEN] = len; if (opt & OPT_n)
strncpy((char*)client_config.hostname + 2, optarg, len); client_config.abort_if_no_lease = 1;
break; // if (opt & OPT_p) client_config.pidfile = ...
case 'F': if (opt & OPT_q)
len = strlen(optarg) > 255 ? 255 : strlen(optarg); client_config.quit_after_lease = 1;
free(client_config.fqdn); if (opt & OPT_R)
client_config.fqdn = xmalloc(len + 5); client_config.release_on_quit = 1;
client_config.fqdn[OPT_CODE] = DHCP_FQDN; if (opt & OPT_r)
client_config.fqdn[OPT_LEN] = len + 3; requested_ip = inet_addr(str_r);
/* Flags: 0000NEOS // if (opt & OPT_s) client_config.script = ...
S: 1 => Client requests Server to update A RR in DNS as well as PTR if (opt & OPT_T)
O: 1 => Server indicates to client that DNS has been updated regardless client_config.timeout = xatoi_u(str_T);
E: 1 => Name data is DNS format, i.e. <4>host<6>domain<4>com<0> not "host.domain.com" if (opt & OPT_t)
N: 1 => Client requests Server to not update DNS client_config.retries = xatoi_u(str_t);
*/ if (opt & OPT_v) {
client_config.fqdn[OPT_LEN + 1] = 0x1; printf("version %s\n\n", BB_VER);
client_config.fqdn[OPT_LEN + 2] = 0; return 0;
client_config.fqdn[OPT_LEN + 3] = 0;
strncpy((char*)client_config.fqdn + 5, optarg, len);
break;
case 'i':
client_config.interface = optarg;
break;
case 'n':
client_config.abort_if_no_lease = 1;
break;
case 'p':
client_config.pidfile = optarg;
break;
case 'q':
client_config.quit_after_lease = 1;
break;
case 'R':
client_config.release_on_quit = 1;
break;
case 'r':
requested_ip = inet_addr(optarg);
break;
case 's':
client_config.script = optarg;
break;
case 'T':
client_config.timeout = xatoi_u(optarg);
break;
case 't':
client_config.retries = xatoi_u(optarg);
break;
case 'v':
printf("version %s\n\n", BB_VER);
return 0;
break;
default:
bb_show_usage();
}
} }
/* Start the log, sanitize fd's, and write a pid file */ /* Start the log, sanitize fd's, and write a pid file */
@ -270,22 +251,13 @@ int udhcpc_main(int argc, char *argv[])
/* if not set, and not suppressed, setup the default client ID */ /* if not set, and not suppressed, setup the default client ID */
if (!client_config.clientid && !no_clientid) { if (!client_config.clientid && !no_clientid) {
client_config.clientid = xmalloc(6 + 3); client_config.clientid = alloc_dhcp_option(DHCP_CLIENT_ID, "", 7);
client_config.clientid[OPT_CODE] = DHCP_CLIENT_ID;
client_config.clientid[OPT_LEN] = 7;
client_config.clientid[OPT_DATA] = 1; client_config.clientid[OPT_DATA] = 1;
memcpy(client_config.clientid + 3, client_config.arp, 6); memcpy(client_config.clientid + OPT_DATA+1, client_config.arp, 6);
}
if (!client_config.vendorclass) {
client_config.vendorclass = xmalloc(sizeof("udhcp "BB_VER) + 2);
client_config.vendorclass[OPT_CODE] = DHCP_VENDOR;
client_config.vendorclass[OPT_LEN] = sizeof("udhcp "BB_VER) - 1;
client_config.vendorclass[OPT_DATA] = 1;
memcpy(&client_config.vendorclass[OPT_DATA],
"udhcp "BB_VER, sizeof("udhcp "BB_VER) - 1);
} }
if (!client_config.vendorclass)
client_config.vendorclass = alloc_dhcp_option(DHCP_VENDOR, "udhcp "BB_VER, 0);
/* setup the signal pipe */ /* setup the signal pipe */
udhcp_sp_setup(); udhcp_sp_setup();
@ -295,7 +267,6 @@ 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 - uptime();
tv.tv_usec = 0; tv.tv_usec = 0;

View File

@ -13,22 +13,24 @@
#define RELEASED 7 #define RELEASED 7
struct client_config_t { struct client_config_t {
char foreground; /* Do not fork */ /* TODO: combine flag fields into single "unsigned opt" */
char quit_after_lease; /* Quit after obtaining lease */ /* (can be set directly to the result of getopt32) */
char release_on_quit; /* perform release on quit */ char foreground; /* Do not fork */
char abort_if_no_lease; /* Abort if no lease */ char quit_after_lease; /* Quit after obtaining lease */
char background_if_no_lease; /* Fork to background if no lease */ char release_on_quit; /* perform release on quit */
char *interface; /* The name of the interface to use */ char abort_if_no_lease; /* Abort if no lease */
char *pidfile; /* Optionally store the process ID */ char background_if_no_lease; /* Fork to background if no lease */
char *script; /* User script to run at dhcp events */ char *interface; /* The name of the interface to use */
uint8_t *clientid; /* Optional client id to use */ char *pidfile; /* Optionally store the process ID */
uint8_t *vendorclass; /* Optional vendor class-id to use */ char *script; /* User script to run at dhcp events */
uint8_t *hostname; /* Optional hostname to use */ uint8_t *clientid; /* Optional client id to use */
uint8_t *fqdn; /* Optional fully qualified domain name to use */ uint8_t *vendorclass; /* Optional vendor class-id to use */
int ifindex; /* Index number of the interface to use */ uint8_t *hostname; /* Optional hostname to use */
int retries; /* Max number of request packets */ uint8_t *fqdn; /* Optional fully qualified domain name to use */
int timeout; /* Number of seconds to try to get a lease */ int ifindex; /* Index number of the interface to use */
uint8_t arp[6]; /* Our arp address */ int retries; /* Max number of request packets */
int timeout; /* Number of seconds to try to get a lease */
uint8_t arp[6]; /* Our arp address */
}; };
extern struct client_config_t client_config; extern struct client_config_t client_config;

View File

@ -68,11 +68,13 @@ int udhcpd_main(int argc, char *argv[])
timeout_end = time(0) + server_config.auto_time; timeout_end = time(0) + server_config.auto_time;
while (1) { /* loop until universe collapses */ while (1) { /* loop until universe collapses */
if (server_socket < 0) if (server_socket < 0) {
if ((server_socket = listen_socket(INADDR_ANY, SERVER_PORT, server_config.interface)) < 0) { server_socket = listen_socket(INADDR_ANY, SERVER_PORT, server_config.interface);
if (server_socket < 0) {
bb_perror_msg("FATAL: cannot create server socket"); bb_perror_msg("FATAL: cannot create server socket");
return 2; return 2;
} }
}
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) {