udhcp: support string user options, closes 10946
function old new delta udhcp_str2optset 536 628 +92 packed_usage 32757 32760 +3 udhcpc_main 2708 2692 -16 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 2/1 up/down: 95/-16) Total: 79 bytes Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
This commit is contained in:
parent
46158dc833
commit
266f6f1973
@ -70,8 +70,9 @@ option domain local
|
|||||||
option lease 864000 # default: 10 days
|
option lease 864000 # default: 10 days
|
||||||
option msstaticroutes 10.0.0.0/8 10.127.0.1 # single static route
|
option msstaticroutes 10.0.0.0/8 10.127.0.1 # single static route
|
||||||
option staticroutes 10.0.0.0/8 10.127.0.1, 10.11.12.0/24 10.11.12.1
|
option staticroutes 10.0.0.0/8 10.127.0.1, 10.11.12.0/24 10.11.12.1
|
||||||
# Arbitrary option in hex form:
|
# Arbitrary option in hex or string form:
|
||||||
option 0x08 01020304 # option 8: "cookie server IP addr: 1.2.3.4"
|
option 0x08 01020304 # option 8: "cookie server IP addr: 1.2.3.4"
|
||||||
|
option 14 "dumpfile"
|
||||||
|
|
||||||
# Currently supported options (for more info, see options.c):
|
# Currently supported options (for more info, see options.c):
|
||||||
#opt lease NUM
|
#opt lease NUM
|
||||||
|
@ -378,23 +378,6 @@ int FAST_FUNC udhcp_str2nip(const char *str, void *arg)
|
|||||||
* Called to parse "udhcpc -x OPTNAME:OPTVAL"
|
* Called to parse "udhcpc -x OPTNAME:OPTVAL"
|
||||||
* and to parse udhcpd.conf's "opt OPTNAME OPTVAL" directives.
|
* and to parse udhcpd.conf's "opt OPTNAME OPTVAL" directives.
|
||||||
*/
|
*/
|
||||||
/* helper for the helper */
|
|
||||||
static char *allocate_tempopt_if_needed(
|
|
||||||
const struct dhcp_optflag *optflag,
|
|
||||||
char *buffer,
|
|
||||||
int *length_p)
|
|
||||||
{
|
|
||||||
char *allocated = NULL;
|
|
||||||
if ((optflag->flags & OPTION_TYPE_MASK) == OPTION_BIN) {
|
|
||||||
const char *end;
|
|
||||||
allocated = xstrdup(buffer); /* more than enough */
|
|
||||||
end = hex2bin(allocated, buffer, 255);
|
|
||||||
if (errno)
|
|
||||||
bb_error_msg_and_die("malformed hex string '%s'", buffer);
|
|
||||||
*length_p = end - allocated;
|
|
||||||
}
|
|
||||||
return allocated;
|
|
||||||
}
|
|
||||||
/* helper: add an option to the opt_list */
|
/* helper: add an option to the opt_list */
|
||||||
static NOINLINE void attach_option(
|
static NOINLINE void attach_option(
|
||||||
struct option_set **opt_list,
|
struct option_set **opt_list,
|
||||||
@ -403,9 +386,16 @@ static NOINLINE void attach_option(
|
|||||||
int length)
|
int length)
|
||||||
{
|
{
|
||||||
struct option_set *existing;
|
struct option_set *existing;
|
||||||
char *allocated;
|
char *allocated = NULL;
|
||||||
|
|
||||||
allocated = allocate_tempopt_if_needed(optflag, buffer, &length);
|
if ((optflag->flags & OPTION_TYPE_MASK) == OPTION_BIN) {
|
||||||
|
const char *end;
|
||||||
|
allocated = xstrdup(buffer); /* more than enough */
|
||||||
|
end = hex2bin(allocated, buffer, 255);
|
||||||
|
if (errno)
|
||||||
|
bb_error_msg_and_die("malformed hex string '%s'", buffer);
|
||||||
|
length = end - allocated;
|
||||||
|
}
|
||||||
#if ENABLE_FEATURE_UDHCP_RFC3397
|
#if ENABLE_FEATURE_UDHCP_RFC3397
|
||||||
if ((optflag->flags & OPTION_TYPE_MASK) == OPTION_DNS_STRING) {
|
if ((optflag->flags & OPTION_TYPE_MASK) == OPTION_DNS_STRING) {
|
||||||
/* reuse buffer and length for RFC1035-formatted string */
|
/* reuse buffer and length for RFC1035-formatted string */
|
||||||
@ -463,12 +453,12 @@ static NOINLINE void attach_option(
|
|||||||
int FAST_FUNC udhcp_str2optset(const char *const_str, void *arg, const struct dhcp_optflag *optflags, const char *option_strings)
|
int FAST_FUNC udhcp_str2optset(const char *const_str, void *arg, const struct dhcp_optflag *optflags, const char *option_strings)
|
||||||
{
|
{
|
||||||
struct option_set **opt_list = arg;
|
struct option_set **opt_list = arg;
|
||||||
char *opt, *val;
|
char *opt;
|
||||||
char *str;
|
char *str;
|
||||||
const struct dhcp_optflag *optflag;
|
const struct dhcp_optflag *optflag;
|
||||||
struct dhcp_optflag bin_optflag;
|
struct dhcp_optflag userdef_optflag;
|
||||||
unsigned optcode;
|
unsigned optcode;
|
||||||
int retval, length;
|
int retval;
|
||||||
/* IP_PAIR needs 8 bytes, STATIC_ROUTES needs 9 max */
|
/* IP_PAIR needs 8 bytes, STATIC_ROUTES needs 9 max */
|
||||||
char buffer[9] ALIGNED(4);
|
char buffer[9] ALIGNED(4);
|
||||||
uint16_t *result_u16 = (uint16_t *) buffer;
|
uint16_t *result_u16 = (uint16_t *) buffer;
|
||||||
@ -476,28 +466,40 @@ int FAST_FUNC udhcp_str2optset(const char *const_str, void *arg, const struct dh
|
|||||||
|
|
||||||
/* Cheat, the only *const* str possible is "" */
|
/* Cheat, the only *const* str possible is "" */
|
||||||
str = (char *) const_str;
|
str = (char *) const_str;
|
||||||
opt = strtok(str, " \t=");
|
opt = strtok(str, " \t=:");
|
||||||
if (!opt)
|
if (!opt)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
optcode = bb_strtou(opt, NULL, 0);
|
optcode = bb_strtou(opt, NULL, 0);
|
||||||
if (!errno && optcode < 255) {
|
if (!errno && optcode < 255) {
|
||||||
/* Raw (numeric) option code */
|
/* Raw (numeric) option code.
|
||||||
bin_optflag.flags = OPTION_BIN;
|
* Initially assume binary (hex-str), but if "str" or 'str'
|
||||||
bin_optflag.code = optcode;
|
* is seen later, switch to STRING.
|
||||||
optflag = &bin_optflag;
|
*/
|
||||||
|
userdef_optflag.flags = OPTION_BIN;
|
||||||
|
userdef_optflag.code = optcode;
|
||||||
|
optflag = &userdef_optflag;
|
||||||
} else {
|
} else {
|
||||||
optflag = &optflags[udhcp_option_idx(opt, option_strings)];
|
optflag = &optflags[udhcp_option_idx(opt, option_strings)];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Loop to handle OPTION_LIST case, else execute just once */
|
||||||
retval = 0;
|
retval = 0;
|
||||||
do {
|
do {
|
||||||
|
int length;
|
||||||
|
char *val;
|
||||||
|
|
||||||
|
if (optflag->flags == OPTION_BIN)
|
||||||
|
val = trim(strtok(NULL, "")); /* do not split "'q w e'" */
|
||||||
|
else
|
||||||
val = strtok(NULL, ", \t");
|
val = strtok(NULL, ", \t");
|
||||||
if (!val)
|
if (!val)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
length = dhcp_option_lengths[optflag->flags & OPTION_TYPE_MASK];
|
length = dhcp_option_lengths[optflag->flags & OPTION_TYPE_MASK];
|
||||||
retval = 0;
|
retval = 0;
|
||||||
opt = buffer; /* new meaning for variable opt */
|
opt = buffer; /* new meaning for variable opt */
|
||||||
|
|
||||||
switch (optflag->flags & OPTION_TYPE_MASK) {
|
switch (optflag->flags & OPTION_TYPE_MASK) {
|
||||||
case OPTION_IP:
|
case OPTION_IP:
|
||||||
retval = udhcp_str2nip(val, buffer);
|
retval = udhcp_str2nip(val, buffer);
|
||||||
@ -510,6 +512,7 @@ int FAST_FUNC udhcp_str2optset(const char *const_str, void *arg, const struct dh
|
|||||||
if (retval)
|
if (retval)
|
||||||
retval = udhcp_str2nip(val, buffer + 4);
|
retval = udhcp_str2nip(val, buffer + 4);
|
||||||
break;
|
break;
|
||||||
|
case_OPTION_STRING:
|
||||||
case OPTION_STRING:
|
case OPTION_STRING:
|
||||||
case OPTION_STRING_HOST:
|
case OPTION_STRING_HOST:
|
||||||
#if ENABLE_FEATURE_UDHCP_RFC3397
|
#if ENABLE_FEATURE_UDHCP_RFC3397
|
||||||
@ -577,12 +580,26 @@ int FAST_FUNC udhcp_str2optset(const char *const_str, void *arg, const struct dh
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case OPTION_BIN: /* handled in attach_option() */
|
case OPTION_BIN:
|
||||||
|
/* Raw (numeric) option code. Is it a string? */
|
||||||
|
if (val[0] == '"' || val[0] == '\'') {
|
||||||
|
char delim = val[0];
|
||||||
|
char *end = last_char_is(val + 1, delim);
|
||||||
|
if (end) {
|
||||||
|
*end = '\0';
|
||||||
|
val++;
|
||||||
|
userdef_optflag.flags = OPTION_STRING;
|
||||||
|
goto case_OPTION_STRING;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* No: hex-str option, handled in attach_option() */
|
||||||
opt = val;
|
opt = val;
|
||||||
retval = 1;
|
retval = 1;
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (retval)
|
if (retval)
|
||||||
attach_option(opt_list, optflag, opt, length);
|
attach_option(opt_list, optflag, opt, length);
|
||||||
} while (retval && (optflag->flags & OPTION_LIST));
|
} while (retval && (optflag->flags & OPTION_LIST));
|
||||||
|
@ -1063,6 +1063,7 @@ static void client_background(void)
|
|||||||
//usage: "\n -x hostname:bbox - option 12"
|
//usage: "\n -x hostname:bbox - option 12"
|
||||||
//usage: "\n -x lease:3600 - option 51 (lease time)"
|
//usage: "\n -x lease:3600 - option 51 (lease time)"
|
||||||
//usage: "\n -x 0x3d:0100BEEFC0FFEE - option 61 (client id)"
|
//usage: "\n -x 0x3d:0100BEEFC0FFEE - option 61 (client id)"
|
||||||
|
//usage: "\n -x 14:'\"dumpfile\"' - option 14 (shell-quoted)"
|
||||||
//usage: IF_UDHCP_VERBOSE(
|
//usage: IF_UDHCP_VERBOSE(
|
||||||
//usage: "\n -v Verbose"
|
//usage: "\n -v Verbose"
|
||||||
//usage: )
|
//usage: )
|
||||||
@ -1155,15 +1156,9 @@ int udhcpc6_main(int argc UNUSED_PARAM, char **argv)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
while (list_x) {
|
while (list_x) {
|
||||||
char *optstr = llist_pop(&list_x);
|
char *optstr = xstrdup(llist_pop(&list_x));
|
||||||
char *colon = strchr(optstr, ':');
|
|
||||||
if (colon)
|
|
||||||
*colon = ' ';
|
|
||||||
/* now it looks similar to udhcpd's config file line:
|
|
||||||
* "optname optval", using the common routine: */
|
|
||||||
udhcp_str2optset(optstr, &client_config.options, d6_optflags, d6_option_strings);
|
udhcp_str2optset(optstr, &client_config.options, d6_optflags, d6_option_strings);
|
||||||
if (colon)
|
free(optstr);
|
||||||
*colon = ':'; /* restore it for NOMMU reexec */
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (d6_read_interface(client_config.interface,
|
if (d6_read_interface(client_config.interface,
|
||||||
|
@ -1224,6 +1224,7 @@ static void client_background(void)
|
|||||||
//usage: "\n -x hostname:bbox - option 12"
|
//usage: "\n -x hostname:bbox - option 12"
|
||||||
//usage: "\n -x lease:3600 - option 51 (lease time)"
|
//usage: "\n -x lease:3600 - option 51 (lease time)"
|
||||||
//usage: "\n -x 0x3d:0100BEEFC0FFEE - option 61 (client id)"
|
//usage: "\n -x 0x3d:0100BEEFC0FFEE - option 61 (client id)"
|
||||||
|
//usage: "\n -x 14:'\"dumpfile\"' - option 14 (shell-quoted)"
|
||||||
//usage: "\n -F NAME Ask server to update DNS mapping for NAME"
|
//usage: "\n -F NAME Ask server to update DNS mapping for NAME"
|
||||||
//usage: "\n -V VENDOR Vendor identifier (default 'udhcp VERSION')"
|
//usage: "\n -V VENDOR Vendor identifier (default 'udhcp VERSION')"
|
||||||
//usage: "\n -C Don't send MAC as client identifier"
|
//usage: "\n -C Don't send MAC as client identifier"
|
||||||
@ -1335,15 +1336,9 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
while (list_x) {
|
while (list_x) {
|
||||||
char *optstr = llist_pop(&list_x);
|
char *optstr = xstrdup(llist_pop(&list_x));
|
||||||
char *colon = strchr(optstr, ':');
|
|
||||||
if (colon)
|
|
||||||
*colon = ' ';
|
|
||||||
/* now it looks similar to udhcpd's config file line:
|
|
||||||
* "optname optval", using the common routine: */
|
|
||||||
udhcp_str2optset(optstr, &client_config.options, dhcp_optflags, dhcp_option_strings);
|
udhcp_str2optset(optstr, &client_config.options, dhcp_optflags, dhcp_option_strings);
|
||||||
if (colon)
|
free(optstr);
|
||||||
*colon = ':'; /* restore it for NOMMU reexec */
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (udhcp_read_interface(client_config.interface,
|
if (udhcp_read_interface(client_config.interface,
|
||||||
|
Loading…
Reference in New Issue
Block a user