udhcpc6: add support for timezones
Basedon patch by Bernd Holzmüller <bernd.holzmueller@tiggerswelt.net> function old new delta option_to_env 504 580 +76 Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
This commit is contained in:
parent
4add757929
commit
234b82ca19
@ -89,6 +89,9 @@ struct d6_option {
|
|||||||
|
|
||||||
#define D6_OPT_CLIENT_FQDN 39
|
#define D6_OPT_CLIENT_FQDN 39
|
||||||
|
|
||||||
|
#define D6_OPT_TZ_POSIX 41
|
||||||
|
#define D6_OPT_TZ_NAME 42
|
||||||
|
|
||||||
/*** Other shared functions ***/
|
/*** Other shared functions ***/
|
||||||
|
|
||||||
struct client6_data_t {
|
struct client6_data_t {
|
||||||
|
@ -93,7 +93,7 @@ static const char opt_req[] = {
|
|||||||
0, 6,
|
0, 6,
|
||||||
(D6_OPT_DNS_SERVERS >> 8), (D6_OPT_DNS_SERVERS & 0xff),
|
(D6_OPT_DNS_SERVERS >> 8), (D6_OPT_DNS_SERVERS & 0xff),
|
||||||
(D6_OPT_DOMAIN_LIST >> 8), (D6_OPT_DOMAIN_LIST & 0xff),
|
(D6_OPT_DOMAIN_LIST >> 8), (D6_OPT_DOMAIN_LIST & 0xff),
|
||||||
(D6_OPT_CLIENT_FQDN >> 8), (D6_OPT_CLIENT_FQDN & 0xff)
|
(D6_OPT_CLIENT_FQDN >> 8), (D6_OPT_CLIENT_FQDN & 0xff),
|
||||||
};
|
};
|
||||||
|
|
||||||
static const char opt_fqdn_req[] = {
|
static const char opt_fqdn_req[] = {
|
||||||
@ -136,12 +136,6 @@ static void *d6_copy_option(uint8_t *option, uint8_t *option_end, unsigned code)
|
|||||||
return xmemdup(opt, opt[3] + 4);
|
return xmemdup(opt, opt[3] + 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void *d6_store_blob(void *dst, const void *src, unsigned len)
|
|
||||||
{
|
|
||||||
memcpy(dst, src, len);
|
|
||||||
return dst + len;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*** Script execution code ***/
|
/*** Script execution code ***/
|
||||||
|
|
||||||
@ -154,10 +148,10 @@ static char** new_env(void)
|
|||||||
/* put all the parameters into the environment */
|
/* put all the parameters into the environment */
|
||||||
static void option_to_env(uint8_t *option, uint8_t *option_end)
|
static void option_to_env(uint8_t *option, uint8_t *option_end)
|
||||||
{
|
{
|
||||||
char *dlist, *ptr;
|
char *dlist;
|
||||||
/* "length minus 4" */
|
/* "length minus 4" */
|
||||||
int len_m4 = option_end - option - 4;
|
int len_m4 = option_end - option - 4;
|
||||||
int olen, ooff;
|
int addrs, option_offset;
|
||||||
while (len_m4 >= 0) {
|
while (len_m4 >= 0) {
|
||||||
uint32_t v32;
|
uint32_t v32;
|
||||||
char ipv6str[sizeof("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff")];
|
char ipv6str[sizeof("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff")];
|
||||||
@ -165,6 +159,10 @@ static void option_to_env(uint8_t *option, uint8_t *option_end)
|
|||||||
if (option[0] != 0 || option[2] != 0)
|
if (option[0] != 0 || option[2] != 0)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
/* Check if option-length exceeds size of option */
|
||||||
|
if (option[3] > len_m4)
|
||||||
|
break;
|
||||||
|
|
||||||
switch (option[1]) {
|
switch (option[1]) {
|
||||||
//case D6_OPT_CLIENTID:
|
//case D6_OPT_CLIENTID:
|
||||||
//case D6_OPT_SERVERID:
|
//case D6_OPT_SERVERID:
|
||||||
@ -174,7 +172,7 @@ static void option_to_env(uint8_t *option, uint8_t *option_end)
|
|||||||
break;
|
break;
|
||||||
//case D6_OPT_IA_TA:
|
//case D6_OPT_IA_TA:
|
||||||
case D6_OPT_IAADDR:
|
case D6_OPT_IAADDR:
|
||||||
/* 0 1 2 3
|
/* 0 1 2 3
|
||||||
* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
|
* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
|
||||||
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||||
* | OPTION_IAADDR | option-len |
|
* | OPTION_IAADDR | option-len |
|
||||||
@ -236,23 +234,26 @@ static void option_to_env(uint8_t *option, uint8_t *option_end)
|
|||||||
*new_env() = xasprintf("ipv6prefix=%s/%u", ipv6str, (unsigned)(option[4 + 4]));
|
*new_env() = xasprintf("ipv6prefix=%s/%u", ipv6str, (unsigned)(option[4 + 4]));
|
||||||
break;
|
break;
|
||||||
case D6_OPT_DNS_SERVERS:
|
case D6_OPT_DNS_SERVERS:
|
||||||
olen = ((option[2] << 8) | option[3]) / 16;
|
/* Make sure payload-size is a multiple of 16 */
|
||||||
dlist = ptr = malloc (4 + olen * 40 - 1);
|
if ((option[3] & 0x0f) != 0)
|
||||||
|
break;
|
||||||
|
|
||||||
memcpy (ptr, "dns=", 4);
|
/* Get the number of addresses on the option */
|
||||||
ptr += 4;
|
addrs = option[3] >> 4;
|
||||||
ooff = 0;
|
|
||||||
|
|
||||||
while (olen--) {
|
/* Setup environment variable */
|
||||||
sprint_nip6(ptr, option + 4 + ooff);
|
*new_env() = dlist = xmalloc(4 + addrs * 40 - 1);
|
||||||
ptr += 39;
|
dlist = stpcpy(dlist, "dns=");
|
||||||
ooff += 16;
|
option_offset = 0;
|
||||||
if (olen)
|
|
||||||
*ptr++ = ' ';
|
while (addrs--) {
|
||||||
|
sprint_nip6(dlist, option + 4 + option_offset);
|
||||||
|
dlist += 39;
|
||||||
|
option_offset += 16;
|
||||||
|
if (addrs)
|
||||||
|
*dlist++ = ' ';
|
||||||
}
|
}
|
||||||
|
|
||||||
*new_env() = dlist;
|
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case D6_OPT_DOMAIN_LIST:
|
case D6_OPT_DOMAIN_LIST:
|
||||||
dlist = dname_dec(option + 4, (option[2] << 8) | option[3], "search=");
|
dlist = dname_dec(option + 4, (option[2] << 8) | option[3], "search=");
|
||||||
@ -261,24 +262,31 @@ static void option_to_env(uint8_t *option, uint8_t *option_end)
|
|||||||
*new_env() = dlist;
|
*new_env() = dlist;
|
||||||
break;
|
break;
|
||||||
case D6_OPT_CLIENT_FQDN:
|
case D6_OPT_CLIENT_FQDN:
|
||||||
// Work around broken ISC DHCPD6
|
if (option[3] == 0)
|
||||||
|
break;
|
||||||
|
/* Work around broken ISC DHCPD6.
|
||||||
|
* ISC DHCPD6 does not implement RFC 4704 correctly: It says the first
|
||||||
|
* byte of option-payload should contain flags where the bits 7-3 are
|
||||||
|
* reserved for future use and MUST be zero. Instead ISC DHCPD6 just
|
||||||
|
* writes the entire FQDN as string to option-payload. We assume a
|
||||||
|
* broken server here if any of the reserved bits are set.
|
||||||
|
*/
|
||||||
if (option[4] & 0xf8) {
|
if (option[4] & 0xf8) {
|
||||||
olen = ((option[2] << 8) | option[3]);
|
*new_env() = xasprintf("fqdn=%.*s", (int)option[3], (char*)option + 4);
|
||||||
dlist = xmalloc(olen);
|
|
||||||
//fixme:
|
|
||||||
//- explain
|
|
||||||
//- add len error check
|
|
||||||
//- merge two allocs into one
|
|
||||||
memcpy(dlist, option + 4, olen);
|
|
||||||
*new_env() = xasprintf("fqdn=%s", dlist);
|
|
||||||
free(dlist);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
dlist = dname_dec(option + 5, ((option[2] << 8) | option[3]) - 1, "fqdn=");
|
dlist = dname_dec(option + 5, (/*(option[2] << 8) |*/ option[3]) - 1, "fqdn=");
|
||||||
if (!dlist)
|
if (!dlist)
|
||||||
break;
|
break;
|
||||||
*new_env() = dlist;
|
*new_env() = dlist;
|
||||||
break;
|
break;
|
||||||
|
/* RFC 4833 Timezones */
|
||||||
|
case D6_OPT_TZ_POSIX:
|
||||||
|
*new_env() = xasprintf("tz=%.*s", (int)option[3], (char*)option + 4);
|
||||||
|
break;
|
||||||
|
case D6_OPT_TZ_NAME:
|
||||||
|
*new_env() = xasprintf("tz_name=%.*s", (int)option[3], (char*)option + 4);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
len_m4 -= 4 + option[3];
|
len_m4 -= 4 + option[3];
|
||||||
option += 4 + option[3];
|
option += 4 + option[3];
|
||||||
@ -346,7 +354,7 @@ static uint8_t *init_d6_packet(struct d6_packet *packet, char type, uint32_t xid
|
|||||||
packet->d6_msg_type = type;
|
packet->d6_msg_type = type;
|
||||||
|
|
||||||
clientid = (void*)client_config.clientid;
|
clientid = (void*)client_config.clientid;
|
||||||
return d6_store_blob(packet->d6_options, clientid, clientid->len + 2+2);
|
return mempcpy(packet->d6_options, clientid, clientid->len + 2+2);
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint8_t *add_d6_client_options(uint8_t *ptr)
|
static uint8_t *add_d6_client_options(uint8_t *ptr)
|
||||||
@ -483,11 +491,11 @@ static NOINLINE int send_d6_discover(uint32_t xid, struct in6_addr *requested_ip
|
|||||||
iaaddr->len = 16+4+4;
|
iaaddr->len = 16+4+4;
|
||||||
memcpy(iaaddr->data, requested_ipv6, 16);
|
memcpy(iaaddr->data, requested_ipv6, 16);
|
||||||
}
|
}
|
||||||
opt_ptr = d6_store_blob(opt_ptr, client6_data.ia_na, len);
|
opt_ptr = mempcpy(opt_ptr, client6_data.ia_na, len);
|
||||||
|
|
||||||
/* Request additional options */
|
/* Request additional options */
|
||||||
opt_ptr = d6_store_blob(opt_ptr, &opt_req, sizeof(opt_req));
|
opt_ptr = mempcpy(opt_ptr, &opt_req, sizeof(opt_req));
|
||||||
opt_ptr = d6_store_blob(opt_ptr, &opt_fqdn_req, sizeof(opt_fqdn_req));
|
opt_ptr = mempcpy(opt_ptr, &opt_fqdn_req, sizeof(opt_fqdn_req));
|
||||||
|
|
||||||
/* Add options:
|
/* Add options:
|
||||||
* "param req" option according to -O, options specified with -x
|
* "param req" option according to -O, options specified with -x
|
||||||
@ -538,13 +546,13 @@ static NOINLINE int send_d6_select(uint32_t xid)
|
|||||||
opt_ptr = init_d6_packet(&packet, D6_MSG_REQUEST, xid);
|
opt_ptr = init_d6_packet(&packet, D6_MSG_REQUEST, xid);
|
||||||
|
|
||||||
/* server id */
|
/* server id */
|
||||||
opt_ptr = d6_store_blob(opt_ptr, client6_data.server_id, client6_data.server_id->len + 2+2);
|
opt_ptr = mempcpy(opt_ptr, client6_data.server_id, client6_data.server_id->len + 2+2);
|
||||||
/* IA NA (contains requested IP) */
|
/* IA NA (contains requested IP) */
|
||||||
opt_ptr = d6_store_blob(opt_ptr, client6_data.ia_na, client6_data.ia_na->len + 2+2);
|
opt_ptr = mempcpy(opt_ptr, client6_data.ia_na, client6_data.ia_na->len + 2+2);
|
||||||
|
|
||||||
/* Request additional options */
|
/* Request additional options */
|
||||||
opt_ptr = d6_store_blob(opt_ptr, &opt_req, sizeof(opt_req));
|
opt_ptr = mempcpy(opt_ptr, &opt_req, sizeof(opt_req));
|
||||||
opt_ptr = d6_store_blob(opt_ptr, &opt_fqdn_req, sizeof(opt_fqdn_req));
|
opt_ptr = mempcpy(opt_ptr, &opt_fqdn_req, sizeof(opt_fqdn_req));
|
||||||
|
|
||||||
/* Add options:
|
/* Add options:
|
||||||
* "param req" option according to -O, options specified with -x
|
* "param req" option according to -O, options specified with -x
|
||||||
@ -611,9 +619,9 @@ static NOINLINE int send_d6_renew(uint32_t xid, struct in6_addr *server_ipv6, st
|
|||||||
opt_ptr = init_d6_packet(&packet, DHCPREQUEST, xid);
|
opt_ptr = init_d6_packet(&packet, DHCPREQUEST, xid);
|
||||||
|
|
||||||
/* server id */
|
/* server id */
|
||||||
opt_ptr = d6_store_blob(opt_ptr, client6_data.server_id, client6_data.server_id->len + 2+2);
|
opt_ptr = mempcpy(opt_ptr, client6_data.server_id, client6_data.server_id->len + 2+2);
|
||||||
/* IA NA (contains requested IP) */
|
/* IA NA (contains requested IP) */
|
||||||
opt_ptr = d6_store_blob(opt_ptr, client6_data.ia_na, client6_data.ia_na->len + 2+2);
|
opt_ptr = mempcpy(opt_ptr, client6_data.ia_na, client6_data.ia_na->len + 2+2);
|
||||||
|
|
||||||
/* Add options:
|
/* Add options:
|
||||||
* "param req" option according to -O, options specified with -x
|
* "param req" option according to -O, options specified with -x
|
||||||
@ -640,9 +648,9 @@ static int send_d6_release(struct in6_addr *server_ipv6, struct in6_addr *our_cu
|
|||||||
/* Fill in: msg type, client id */
|
/* Fill in: msg type, client id */
|
||||||
opt_ptr = init_d6_packet(&packet, D6_MSG_RELEASE, random_xid());
|
opt_ptr = init_d6_packet(&packet, D6_MSG_RELEASE, random_xid());
|
||||||
/* server id */
|
/* server id */
|
||||||
opt_ptr = d6_store_blob(opt_ptr, client6_data.server_id, client6_data.server_id->len + 2+2);
|
opt_ptr = mempcpy(opt_ptr, client6_data.server_id, client6_data.server_id->len + 2+2);
|
||||||
/* IA NA (contains our current IP) */
|
/* IA NA (contains our current IP) */
|
||||||
opt_ptr = d6_store_blob(opt_ptr, client6_data.ia_na, client6_data.ia_na->len + 2+2);
|
opt_ptr = mempcpy(opt_ptr, client6_data.ia_na, client6_data.ia_na->len + 2+2);
|
||||||
|
|
||||||
bb_error_msg("sending %s", "release");
|
bb_error_msg("sending %s", "release");
|
||||||
return d6_send_kernel_packet(
|
return d6_send_kernel_packet(
|
||||||
|
Loading…
x
Reference in New Issue
Block a user