udhcpc: convert to getopt32
diff --git a/networking/udhcp/dhcpc.c b/networking/udhcp/dhcpc.c
index 4ccd8ec..f69b687 100644
--- a/networking/udhcp/dhcpc.c
+++ b/networking/udhcp/dhcpc.c
@@ -33,25 +33,8 @@
#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 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 @@
/* 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);
+ 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 */
udhcp_sp_setup();
@@ -295,7 +267,6 @@
change_mode(LISTEN_RAW);
for (;;) {
-
tv.tv_sec = timeout - uptime();
tv.tv_usec = 0;