udhcpc: convert to getopt32
This commit is contained in:
parent
30d7a346e6
commit
e2d3ded354
@ -1,4 +1,13 @@
|
||||
/* 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__
|
||||
#define __BB_USAGE_H__
|
||||
|
||||
|
@ -33,25 +33,8 @@ static int fd = -1;
|
||||
#define LISTEN_RAW 2
|
||||
static int listen_mode;
|
||||
|
||||
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 */
|
||||
};
|
||||
struct client_config_t client_config;
|
||||
|
||||
|
||||
/* just a little helper */
|
||||
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[])
|
||||
{
|
||||
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 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;
|
||||
unsigned opt;
|
||||
int max_fd;
|
||||
int sig;
|
||||
int retval;
|
||||
int len;
|
||||
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[] = {
|
||||
{"clientid", required_argument, 0, 'c'},
|
||||
{"clientid-none", no_argument, 0, 'C'},
|
||||
{"vendorclass", required_argument, 0, 'V'},
|
||||
{"foreground", no_argument, 0, 'f'},
|
||||
{"background", no_argument, 0, 'b'},
|
||||
{"hostname", required_argument, 0, 'H'},
|
||||
{"hostname", required_argument, 0, 'h'},
|
||||
{"fqdn", required_argument, 0, 'F'},
|
||||
{"interface", required_argument, 0, 'i'},
|
||||
{"now", no_argument, 0, 'n'},
|
||||
{"pidfile", required_argument, 0, 'p'},
|
||||
{"quit", no_argument, 0, 'q'},
|
||||
{"release", no_argument, 0, 'R'},
|
||||
{"request", required_argument, 0, 'r'},
|
||||
{"script", required_argument, 0, 's'},
|
||||
{"timeout", required_argument, 0, 'T'},
|
||||
{"version", no_argument, 0, 'v'},
|
||||
{"retries", required_argument, 0, 't'},
|
||||
{0, 0, 0, 0}
|
||||
{ "clientid", required_argument, 0, 'c' },
|
||||
{ "clientid-none", no_argument, 0, 'C' },
|
||||
{ "vendorclass", required_argument, 0, 'V' },
|
||||
{ "foreground", no_argument, 0, 'f' },
|
||||
{ "background", no_argument, 0, 'b' },
|
||||
{ "hostname", required_argument, 0, 'H' },
|
||||
{ "hostname", required_argument, 0, 'h' },
|
||||
{ "fqdn", required_argument, 0, 'F' },
|
||||
{ "interface", required_argument, 0, 'i' },
|
||||
{ "now", no_argument, 0, 'n' },
|
||||
{ "pidfile", required_argument, 0, 'p' },
|
||||
{ "quit", no_argument, 0, 'q' },
|
||||
{ "release", no_argument, 0, 'R' },
|
||||
{ "request", required_argument, 0, 'r' },
|
||||
{ "script", required_argument, 0, 's' },
|
||||
{ "timeout", required_argument, 0, 'T' },
|
||||
{ "version", no_argument, 0, 'v' },
|
||||
{ "retries", required_argument, 0, 't' },
|
||||
{ 0, 0, 0, 0 }
|
||||
};
|
||||
|
||||
/* get options */
|
||||
while (1) {
|
||||
int option_index = 0;
|
||||
c = getopt_long(argc, argv, "c:CV:fbH:h:F:i:np:qRr:s:T:t:v", arg_options, &option_index);
|
||||
if (c == -1) break;
|
||||
/* Default options. */
|
||||
client_config.interface = "eth0";
|
||||
client_config.script = DEFAULT_SCRIPT;
|
||||
client_config.retries = 3;
|
||||
client_config.timeout = 3;
|
||||
|
||||
switch (c) {
|
||||
case 'c':
|
||||
if (no_clientid) bb_show_usage();
|
||||
len = strlen(optarg) > 255 ? 255 : strlen(optarg);
|
||||
free(client_config.clientid);
|
||||
client_config.clientid = xmalloc(len + 2);
|
||||
client_config.clientid[OPT_CODE] = DHCP_CLIENT_ID;
|
||||
client_config.clientid[OPT_LEN] = len;
|
||||
client_config.clientid[OPT_DATA] = '\0';
|
||||
strncpy((char*)client_config.clientid + OPT_DATA, optarg, len);
|
||||
break;
|
||||
case 'C':
|
||||
if (client_config.clientid) bb_show_usage();
|
||||
no_clientid = 1;
|
||||
break;
|
||||
case 'V':
|
||||
len = strlen(optarg) > 255 ? 255 : strlen(optarg);
|
||||
free(client_config.vendorclass);
|
||||
client_config.vendorclass = xmalloc(len + 2);
|
||||
client_config.vendorclass[OPT_CODE] = DHCP_VENDOR;
|
||||
client_config.vendorclass[OPT_LEN] = len;
|
||||
strncpy((char*)client_config.vendorclass + OPT_DATA, optarg, len);
|
||||
break;
|
||||
case 'f':
|
||||
client_config.foreground = 1;
|
||||
break;
|
||||
case 'b':
|
||||
client_config.background_if_no_lease = 1;
|
||||
break;
|
||||
case 'h':
|
||||
case 'H':
|
||||
len = strlen(optarg) > 255 ? 255 : strlen(optarg);
|
||||
free(client_config.hostname);
|
||||
client_config.hostname = xmalloc(len + 2);
|
||||
client_config.hostname[OPT_CODE] = DHCP_HOST_NAME;
|
||||
client_config.hostname[OPT_LEN] = len;
|
||||
strncpy((char*)client_config.hostname + 2, optarg, len);
|
||||
break;
|
||||
case 'F':
|
||||
len = strlen(optarg) > 255 ? 255 : strlen(optarg);
|
||||
free(client_config.fqdn);
|
||||
client_config.fqdn = xmalloc(len + 5);
|
||||
client_config.fqdn[OPT_CODE] = DHCP_FQDN;
|
||||
client_config.fqdn[OPT_LEN] = len + 3;
|
||||
/* Flags: 0000NEOS
|
||||
S: 1 => Client requests Server to update A RR in DNS as well as PTR
|
||||
O: 1 => Server indicates to client that DNS has been updated regardless
|
||||
E: 1 => Name data is DNS format, i.e. <4>host<6>domain<4>com<0> not "host.domain.com"
|
||||
N: 1 => Client requests Server to not update DNS
|
||||
*/
|
||||
client_config.fqdn[OPT_LEN + 1] = 0x1;
|
||||
client_config.fqdn[OPT_LEN + 2] = 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();
|
||||
}
|
||||
/* Parse command line */
|
||||
opt_complementary = "?:c--C:C--c" // mutually exclusive
|
||||
":hH:Hh"; // -h and -H are the same
|
||||
applet_long_options = arg_options;
|
||||
opt = getopt32(argc, argv, "c:CV:fbH:h:F:i:np:qRr:s:T:t:v",
|
||||
&str_c, &str_V, &str_h, &str_h, &str_F,
|
||||
&client_config.interface, &client_config.pidfile, &str_r,
|
||||
&client_config.script, &str_T, &str_t
|
||||
);
|
||||
|
||||
if (opt & OPT_c)
|
||||
client_config.clientid = alloc_dhcp_option(DHCP_CLIENT_ID, str_c, 0);
|
||||
if (opt & OPT_C)
|
||||
no_clientid = 1;
|
||||
if (opt & OPT_V)
|
||||
client_config.vendorclass = alloc_dhcp_option(DHCP_VENDOR, str_V, 0);
|
||||
if (opt & OPT_f)
|
||||
client_config.foreground = 1;
|
||||
if (opt & OPT_b)
|
||||
client_config.background_if_no_lease = 1;
|
||||
if (opt & OPT_h)
|
||||
client_config.hostname = alloc_dhcp_option(DHCP_HOST_NAME, str_h, 0);
|
||||
if (opt & OPT_F) {
|
||||
client_config.fqdn = alloc_dhcp_option(DHCP_FQDN, str_F, 3);
|
||||
/* Flags: 0000NEOS
|
||||
S: 1 => Client requests Server to update A RR in DNS as well as PTR
|
||||
O: 1 => Server indicates to client that DNS has been updated regardless
|
||||
E: 1 => Name data is DNS format, i.e. <4>host<6>domain<4>com<0> not "host.domain.com"
|
||||
N: 1 => Client requests Server to not update DNS
|
||||
*/
|
||||
client_config.fqdn[OPT_DATA + 0] = 0x1;
|
||||
/* client_config.fqdn[OPT_DATA + 1] = 0; - redundant */
|
||||
/* client_config.fqdn[OPT_DATA + 2] = 0; - redundant */
|
||||
}
|
||||
// if (opt & OPT_i) client_config.interface = ...
|
||||
if (opt & OPT_n)
|
||||
client_config.abort_if_no_lease = 1;
|
||||
// if (opt & OPT_p) client_config.pidfile = ...
|
||||
if (opt & OPT_q)
|
||||
client_config.quit_after_lease = 1;
|
||||
if (opt & OPT_R)
|
||||
client_config.release_on_quit = 1;
|
||||
if (opt & OPT_r)
|
||||
requested_ip = inet_addr(str_r);
|
||||
// if (opt & OPT_s) client_config.script = ...
|
||||
if (opt & OPT_T)
|
||||
client_config.timeout = xatoi_u(str_T);
|
||||
if (opt & OPT_t)
|
||||
client_config.retries = xatoi_u(str_t);
|
||||
if (opt & OPT_v) {
|
||||
printf("version %s\n\n", BB_VER);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* 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 (!client_config.clientid && !no_clientid) {
|
||||
client_config.clientid = xmalloc(6 + 3);
|
||||
client_config.clientid[OPT_CODE] = DHCP_CLIENT_ID;
|
||||
client_config.clientid[OPT_LEN] = 7;
|
||||
client_config.clientid = alloc_dhcp_option(DHCP_CLIENT_ID, "", 7);
|
||||
client_config.clientid[OPT_DATA] = 1;
|
||||
memcpy(client_config.clientid + 3, 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);
|
||||
memcpy(client_config.clientid + OPT_DATA+1, client_config.arp, 6);
|
||||
}
|
||||
|
||||
if (!client_config.vendorclass)
|
||||
client_config.vendorclass = alloc_dhcp_option(DHCP_VENDOR, "udhcp "BB_VER, 0);
|
||||
|
||||
/* setup the signal pipe */
|
||||
udhcp_sp_setup();
|
||||
@ -295,7 +267,6 @@ int udhcpc_main(int argc, char *argv[])
|
||||
change_mode(LISTEN_RAW);
|
||||
|
||||
for (;;) {
|
||||
|
||||
tv.tv_sec = timeout - uptime();
|
||||
tv.tv_usec = 0;
|
||||
|
||||
|
@ -13,22 +13,24 @@
|
||||
#define RELEASED 7
|
||||
|
||||
struct client_config_t {
|
||||
char foreground; /* Do not fork */
|
||||
char quit_after_lease; /* Quit after obtaining lease */
|
||||
char release_on_quit; /* perform release on quit */
|
||||
char abort_if_no_lease; /* Abort if no lease */
|
||||
char background_if_no_lease; /* Fork to background if no lease */
|
||||
char *interface; /* The name of the interface to use */
|
||||
char *pidfile; /* Optionally store the process ID */
|
||||
char *script; /* User script to run at dhcp events */
|
||||
uint8_t *clientid; /* Optional client id to use */
|
||||
uint8_t *vendorclass; /* Optional vendor class-id to use */
|
||||
uint8_t *hostname; /* Optional hostname to use */
|
||||
uint8_t *fqdn; /* Optional fully qualified domain name to use */
|
||||
int ifindex; /* Index number of the interface to use */
|
||||
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 */
|
||||
/* TODO: combine flag fields into single "unsigned opt" */
|
||||
/* (can be set directly to the result of getopt32) */
|
||||
char foreground; /* Do not fork */
|
||||
char quit_after_lease; /* Quit after obtaining lease */
|
||||
char release_on_quit; /* perform release on quit */
|
||||
char abort_if_no_lease; /* Abort if no lease */
|
||||
char background_if_no_lease; /* Fork to background if no lease */
|
||||
char *interface; /* The name of the interface to use */
|
||||
char *pidfile; /* Optionally store the process ID */
|
||||
char *script; /* User script to run at dhcp events */
|
||||
uint8_t *clientid; /* Optional client id to use */
|
||||
uint8_t *vendorclass; /* Optional vendor class-id to use */
|
||||
uint8_t *hostname; /* Optional hostname to use */
|
||||
uint8_t *fqdn; /* Optional fully qualified domain name to use */
|
||||
int ifindex; /* Index number of the interface to use */
|
||||
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;
|
||||
|
@ -68,11 +68,13 @@ int udhcpd_main(int argc, char *argv[])
|
||||
timeout_end = time(0) + server_config.auto_time;
|
||||
while (1) { /* loop until universe collapses */
|
||||
|
||||
if (server_socket < 0)
|
||||
if ((server_socket = listen_socket(INADDR_ANY, SERVER_PORT, server_config.interface)) < 0) {
|
||||
if (server_socket < 0) {
|
||||
server_socket = listen_socket(INADDR_ANY, SERVER_PORT, server_config.interface);
|
||||
if (server_socket < 0) {
|
||||
bb_perror_msg("FATAL: cannot create server socket");
|
||||
return 2;
|
||||
}
|
||||
}
|
||||
|
||||
max_sock = udhcp_sp_fd_set(&rfds, server_socket);
|
||||
if (server_config.auto_time) {
|
||||
|
Loading…
Reference in New Issue
Block a user