- /* get options */
- while (1) {
- int option_index = 0;
- c = getopt_long(argc, argv, "c:CfbH:h:F:i:np:qr:s:v", arg_options, &option_index);
- if (c == -1) break;
-
- switch (c) {
- case 'c':
- if (no_clientid) show_usage();
- len = strlen(optarg) > 255 ? 255 : strlen(optarg);
- if (client_config.clientid) 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(client_config.clientid + OPT_DATA, optarg, len);
- break;
- case 'C':
- if (client_config.clientid) show_usage();
- no_clientid = 1;
- 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);
- if (client_config.hostname) 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(client_config.hostname + 2, optarg, len);
- break;
- case 'F':
- len = strlen(optarg) > 255 ? 255 : strlen(optarg);
- if (client_config.fqdn) 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(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':
- requested_ip = inet_addr(optarg);
- break;
- case 's':
- client_config.script = optarg;
- break;
- case 'v':
- printf("udhcpcd, version %s\n\n", VERSION);
- return 0;
- break;
- default:
- show_usage();
- }
+ 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,
+ OPT_S = 1 << 18,
+ OPT_A = 1 << 19,
+#if ENABLE_FEATURE_UDHCPC_ARPING
+ OPT_a = 1 << 20,
+ OPT_W = 1 << 21,
+#endif
+ OPT_P = 1 << 22,
+ };
+#if ENABLE_GETOPT_LONG
+ static const char udhcpc_longopts[] ALIGN1 =
+ "clientid\0" Required_argument "c"
+ "clientid-none\0" No_argument "C"
+ "vendorclass\0" Required_argument "V"
+ "foreground\0" No_argument "f"
+ "background\0" No_argument "b"
+ "hostname\0" Required_argument "H"
+ "fqdn\0" Required_argument "F"
+ "interface\0" Required_argument "i"
+ "now\0" No_argument "n"
+ "pidfile\0" Required_argument "p"
+ "quit\0" No_argument "q"
+ "release\0" No_argument "R"
+ "request\0" Required_argument "r"
+ "script\0" Required_argument "s"
+ "timeout\0" Required_argument "T"
+ "version\0" No_argument "v"
+ "retries\0" Required_argument "t"
+ "tryagain\0" Required_argument "A"
+ "syslog\0" No_argument "S"
+#if ENABLE_FEATURE_UDHCPC_ARPING
+ "arping\0" No_argument "a"
+#endif
+ "request-option\0" Required_argument "O"
+#if ENABLE_FEATURE_UDHCP_PORT
+ "client-port\0" Required_argument "P"
+#endif
+ ;
+#endif
+ /* Default options. */
+#if ENABLE_FEATURE_UDHCP_PORT
+ SERVER_PORT = 67;
+ CLIENT_PORT = 68;
+#endif
+ client_config.interface = "eth0";
+ client_config.script = DEFAULT_SCRIPT;
+
+ /* Parse command line */
+ /* Cc: mutually exclusive; O: list; -T,-t,-A take numeric param */
+ opt_complementary = "c--C:C--c:O::T+:t+:A+";
+#if ENABLE_GETOPT_LONG
+ applet_long_options = udhcpc_longopts;
+#endif
+ opt = getopt32(argv, "c:CV:fbH:h:F:i:np:qRr:s:T:t:vSA:"
+ USE_FEATURE_UDHCPC_ARPING("aW:")
+ USE_FEATURE_UDHCP_PORT("P:")
+ "O:"
+ , &str_c, &str_V, &str_h, &str_h, &str_F
+ , &client_config.interface, &client_config.pidfile, &str_r
+ , &client_config.script
+ , &discover_timeout, &discover_retries, &tryagain_timeout
+ USE_FEATURE_UDHCPC_ARPING(, &str_W)
+ USE_FEATURE_UDHCP_PORT(, &str_P)
+ , &list_O
+ );
+
+ if (opt & OPT_c)
+ client_config.clientid = alloc_dhcp_option(DHCP_CLIENT_ID, str_c, 0);
+ //if (opt & OPT_C)
+ 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|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) discover_timeout = xatoi_u(str_T);
+ // if (opt & OPT_t) discover_retries = xatoi_u(str_t);
+ // if (opt & OPT_A) tryagain_timeout = xatoi_u(str_A);
+ if (opt & OPT_v) {
+ puts("version "BB_VER);
+ return 0;
+ }
+ if (opt & OPT_S) {
+ openlog(applet_name, LOG_PID, LOG_LOCAL0);
+ logmode |= LOGMODE_SYSLOG;
+ }
+#if ENABLE_FEATURE_UDHCP_PORT
+ if (opt & OPT_P) {
+ CLIENT_PORT = xatou16(str_P);
+ SERVER_PORT = CLIENT_PORT - 1;
+ }
+#endif
+ while (list_O) {
+ int n = index_in_strings(dhcp_option_strings, list_O->data);
+ if (n < 0)
+ bb_error_msg_and_die("unknown option '%s'", list_O->data);
+ n = dhcp_options[n].code;
+ client_config.opt_mask[n >> 3] |= 1 << (n & 7);
+ list_O = list_O->link;