X-Git-Url: http://git.openwrt.org/?a=blobdiff_plain;f=src%2Fodhcp6c.c;h=dbe15ffd29b6c809ad459baad15334228b305882;hb=49305e6847efa43e008d0bebdc176e1833120947;hp=b055b70bed13cc1b8cd05c8cfb4c0675ee65e253;hpb=d57346128e86418dc6a69140482073c3c7ab34ba;p=project%2Fodhcp6c.git diff --git a/src/odhcp6c.c b/src/odhcp6c.c index b055b70..dbe15ff 100644 --- a/src/odhcp6c.c +++ b/src/odhcp6c.c @@ -87,31 +87,79 @@ static struct odhcp6c_opt opts[] = { { .code = DHCPV6_OPT_INTERFACE_ID, .flags = OPT_INTERNAL, .str = NULL }, { .code = DHCPV6_OPT_RECONF_MESSAGE, .flags = OPT_INTERNAL, .str = NULL }, { .code = DHCPV6_OPT_RECONF_ACCEPT, .flags = OPT_INTERNAL | OPT_NO_PASSTHRU, .str = NULL }, - { .code = DHCPV6_OPT_DNS_SERVERS, .flags = OPT_IP6 | OPT_ARRAY, .str = "dns" }, - { .code = DHCPV6_OPT_DNS_DOMAIN, .flags = OPT_DNS_STR, .str = "search" }, + { .code = DHCPV6_OPT_SIP_SERVER_D, .flags = OPT_DNS_STR | OPT_ORO, .str = "sipserver_d" }, + { .code = DHCPV6_OPT_SIP_SERVER_A, .flags = OPT_IP6 | OPT_ARRAY | OPT_ORO, .str = "sipserver_a" }, + { .code = DHCPV6_OPT_DNS_SERVERS, .flags = OPT_IP6 | OPT_ARRAY | OPT_ORO, .str = "dns" }, + { .code = DHCPV6_OPT_DNS_DOMAIN, .flags = OPT_DNS_STR | OPT_ORO, .str = "search" }, { .code = DHCPV6_OPT_IA_PD, .flags = OPT_INTERNAL | OPT_NO_PASSTHRU, .str = NULL }, { .code = DHCPV6_OPT_IA_PREFIX, .flags = OPT_INTERNAL, .str = NULL }, - { .code = DHCPV6_OPT_SNTP_SERVERS, .flags = OPT_IP6 | OPT_ARRAY, .str = "sntpservers" }, - { .code = DHCPV6_OPT_INFO_REFRESH, .flags = OPT_INTERNAL | OPT_NO_PASSTHRU, .str = NULL }, - { .code = DHCPV6_OPT_FQDN, .flags = OPT_INTERNAL | OPT_NO_PASSTHRU, .str = NULL }, - { .code = DHCPV6_OPT_NTP_SERVER, .flags = OPT_U8, .str = "ntpserver" }, - { .code = DHCPV6_OPT_SIP_SERVER_D, .flags = OPT_DNS_STR, .str = "sipserver_d" }, - { .code = DHCPV6_OPT_SIP_SERVER_A, .flags = OPT_IP6 | OPT_ARRAY, .str = "sipserver_a" }, - { .code = DHCPV6_OPT_AFTR_NAME, .flags = OPT_INTERNAL | OPT_NO_PASSTHRU, .str = NULL }, - { .code = DHCPV6_OPT_PD_EXCLUDE, .flags = OPT_INTERNAL, .str = NULL }, - { .code = DHCPV6_OPT_SOL_MAX_RT, .flags = OPT_INTERNAL | OPT_NO_PASSTHRU, .str = NULL }, - { .code = DHCPV6_OPT_INF_MAX_RT, .flags = OPT_INTERNAL | OPT_NO_PASSTHRU, .str = NULL }, + { .code = DHCPV6_OPT_SNTP_SERVERS, .flags = OPT_IP6 | OPT_ARRAY | OPT_ORO, .str = "sntpservers" }, + { .code = DHCPV6_OPT_INFO_REFRESH, .flags = OPT_INTERNAL | OPT_NO_PASSTHRU | OPT_ORO | OPT_ORO_STATELESS, .str = NULL }, + { .code = DHCPV6_OPT_REMOTE_ID, .flags = OPT_INTERNAL | OPT_NO_PASSTHRU, .str = NULL }, + { .code = DHCPV6_OPT_SUBSCRIBER_ID, .flags = OPT_INTERNAL | OPT_NO_PASSTHRU, .str = NULL }, + { .code = DHCPV6_OPT_FQDN, .flags = OPT_INTERNAL | OPT_NO_PASSTHRU | OPT_ORO, .str = NULL }, + { .code = DHCPV6_OPT_ERO, .flags = OPT_INTERNAL | OPT_NO_PASSTHRU, .str = NULL }, + { .code = DHCPV6_OPT_LQ_QUERY, .flags = OPT_INTERNAL | OPT_NO_PASSTHRU, .str = NULL }, + { .code = DHCPV6_OPT_CLIENT_DATA, .flags = OPT_INTERNAL | OPT_NO_PASSTHRU, .str = NULL }, + { .code = DHCPV6_OPT_CLT_TIME, .flags = OPT_INTERNAL | OPT_NO_PASSTHRU, .str = NULL }, + { .code = DHCPV6_OPT_LQ_RELAY_DATA, .flags = OPT_INTERNAL | OPT_NO_PASSTHRU, .str = NULL }, + { .code = DHCPV6_OPT_LQ_CLIENT_LINK, .flags = OPT_INTERNAL | OPT_NO_PASSTHRU, .str = NULL }, + { .code = DHCPV6_OPT_RELAY_ID, .flags = OPT_INTERNAL | OPT_NO_PASSTHRU, .str = NULL }, + { .code = DHCPV6_OPT_NTP_SERVER, .flags = OPT_U8 | OPT_ORO, .str = "ntpserver" }, + { .code = DHCPV6_OPT_CLIENT_ARCH_TYPE, .flags = OPT_INTERNAL | OPT_NO_PASSTHRU, .str = NULL }, + { .code = DHCPV6_OPT_AFTR_NAME, .flags = OPT_INTERNAL | OPT_NO_PASSTHRU | OPT_ORO, .str = NULL }, + { .code = DHCPV6_OPT_RSOO, .flags = OPT_INTERNAL | OPT_NO_PASSTHRU, .str = NULL }, + { .code = DHCPV6_OPT_PD_EXCLUDE, .flags = OPT_INTERNAL | OPT_ORO | OPT_ORO_STATEFUL, .str = NULL }, + { .code = DHCPV6_OPT_VSS, .flags = OPT_U8, .str = "vss" }, + { .code = DHCPV6_OPT_LINK_LAYER_ADDRESS, .flags = OPT_INTERNAL | OPT_NO_PASSTHRU, .str = NULL }, + { .code = DHCPV6_OPT_LINK_ADDRESS, .flags = OPT_INTERNAL | OPT_NO_PASSTHRU, .str = NULL }, + { .code = DHCPV6_OPT_RADIUS, .flags = OPT_INTERNAL | OPT_NO_PASSTHRU, .str = NULL }, + { .code = DHCPV6_OPT_SOL_MAX_RT, .flags = OPT_INTERNAL | OPT_NO_PASSTHRU | OPT_ORO | OPT_ORO_SOLICIT, .str = NULL }, + { .code = DHCPV6_OPT_INF_MAX_RT, .flags = OPT_INTERNAL | OPT_NO_PASSTHRU | OPT_ORO | OPT_ORO_STATELESS, .str = NULL }, #ifdef EXT_CER_ID { .code = DHCPV6_OPT_CER_ID, .flags = OPT_INTERNAL | OPT_NO_PASSTHRU, .str = NULL }, #endif + { .code = DHCPV6_OPT_DHCPV4_MSG, .flags = OPT_INTERNAL | OPT_NO_PASSTHRU, .str = NULL }, { .code = DHCPV6_OPT_S46_RULE, .flags = OPT_INTERNAL | OPT_NO_PASSTHRU, .str = NULL }, { .code = DHCPV6_OPT_S46_BR, .flags = OPT_INTERNAL | OPT_NO_PASSTHRU, .str = NULL }, { .code = DHCPV6_OPT_S46_DMR, .flags = OPT_INTERNAL | OPT_NO_PASSTHRU, .str = NULL }, { .code = DHCPV6_OPT_S46_V4V6BIND, .flags = OPT_INTERNAL | OPT_NO_PASSTHRU, .str = NULL }, { .code = DHCPV6_OPT_S46_PORTPARAMS, .flags = OPT_INTERNAL | OPT_NO_PASSTHRU, .str = NULL }, - { .code = DHCPV6_OPT_S46_CONT_MAPE, .flags = OPT_INTERNAL | OPT_NO_PASSTHRU, .str = NULL }, - { .code = DHCPV6_OPT_S46_CONT_MAPT, .flags = OPT_INTERNAL | OPT_NO_PASSTHRU, .str = NULL }, - { .code = DHCPV6_OPT_S46_CONT_LW, .flags = OPT_INTERNAL | OPT_NO_PASSTHRU, .str = NULL }, + { .code = DHCPV6_OPT_S46_CONT_MAPE, .flags = OPT_INTERNAL | OPT_NO_PASSTHRU | OPT_ORO, .str = NULL }, + { .code = DHCPV6_OPT_S46_CONT_MAPT, .flags = OPT_INTERNAL | OPT_NO_PASSTHRU | OPT_ORO, .str = NULL }, + { .code = DHCPV6_OPT_S46_CONT_LW, .flags = OPT_INTERNAL | OPT_NO_PASSTHRU | OPT_ORO, .str = NULL }, + { .code = DHCPV6_OPT_LQ_BASE_TIME, .flags = OPT_INTERNAL | OPT_NO_PASSTHRU, .str = NULL }, + { .code = DHCPV6_OPT_LQ_START_TIME, .flags = OPT_INTERNAL | OPT_NO_PASSTHRU, .str = NULL }, + { .code = DHCPV6_OPT_LQ_END_TIME, .flags = OPT_INTERNAL | OPT_NO_PASSTHRU, .str = NULL }, + { .code = DHCPV6_OPT_ANI_ATT, .flags = OPT_INTERNAL | OPT_NO_PASSTHRU, .str = NULL }, + { .code = DHCPV6_OPT_ANI_NETWORK_NAME, .flags = OPT_INTERNAL | OPT_NO_PASSTHRU, .str = NULL }, + { .code = DHCPV6_OPT_ANI_AP_NAME, .flags = OPT_INTERNAL | OPT_NO_PASSTHRU, .str = NULL }, + { .code = DHCPV6_OPT_ANI_AP_BSSID, .flags = OPT_INTERNAL | OPT_NO_PASSTHRU, .str = NULL }, + { .code = DHCPV6_OPT_ANI_OPERATOR_ID, .flags = OPT_INTERNAL | OPT_NO_PASSTHRU, .str = NULL }, + { .code = DHCPV6_OPT_ANI_OPERATOR_REALM, .flags = OPT_INTERNAL | OPT_NO_PASSTHRU, .str = NULL }, + { .code = DHCPV6_OPT_MUD_URL_V6, .flags = OPT_STR | OPT_NO_PASSTHRU, .str = "mud_url_v6" }, + { .code = DHCPV6_OPT_F_BINDING_STATUS, .flags = OPT_INTERNAL | OPT_NO_PASSTHRU, .str = NULL }, + { .code = DHCPV6_OPT_F_CONNECT_FLAGS, .flags = OPT_INTERNAL | OPT_NO_PASSTHRU, .str = NULL }, + { .code = DHCPV6_OPT_F_DNS_REMOVAL_INFO, .flags = OPT_INTERNAL | OPT_NO_PASSTHRU, .str = NULL }, + { .code = DHCPV6_OPT_F_DNS_HOST_NAME, .flags = OPT_INTERNAL | OPT_NO_PASSTHRU, .str = NULL }, + { .code = DHCPV6_OPT_F_DNS_ZONE_NAME, .flags = OPT_INTERNAL | OPT_NO_PASSTHRU, .str = NULL }, + { .code = DHCPV6_OPT_F_DNS_FLAGS, .flags = OPT_INTERNAL | OPT_NO_PASSTHRU, .str = NULL }, + { .code = DHCPV6_OPT_F_EXPIRATION_TIME, .flags = OPT_INTERNAL | OPT_NO_PASSTHRU, .str = NULL }, + { .code = DHCPV6_OPT_F_MAX_UNACKED_BNDUPD, .flags = OPT_INTERNAL | OPT_NO_PASSTHRU, .str = NULL }, + { .code = DHCPV6_OPT_F_MCLT, .flags = OPT_INTERNAL | OPT_NO_PASSTHRU, .str = NULL }, + { .code = DHCPV6_OPT_F_PARTNER_LIFETIME, .flags = OPT_INTERNAL | OPT_NO_PASSTHRU, .str = NULL }, + { .code = DHCPV6_OPT_F_PARTNER_LIFETIME_SENT, .flags = OPT_INTERNAL | OPT_NO_PASSTHRU, .str = NULL }, + { .code = DHCPV6_OPT_F_PARTNER_DOWN_TIME, .flags = OPT_INTERNAL | OPT_NO_PASSTHRU, .str = NULL }, + { .code = DHCPV6_OPT_F_PARTNER_RAW_CLT_TIME, .flags = OPT_INTERNAL | OPT_NO_PASSTHRU, .str = NULL }, + { .code = DHCPV6_OPT_F_PROTOCOL_VERSION, .flags = OPT_INTERNAL | OPT_NO_PASSTHRU, .str = NULL }, + { .code = DHCPV6_OPT_F_KEEPALIVE_TIME, .flags = OPT_INTERNAL | OPT_NO_PASSTHRU, .str = NULL }, + { .code = DHCPV6_OPT_F_RECONFIGURE_DATA, .flags = OPT_INTERNAL | OPT_NO_PASSTHRU, .str = NULL }, + { .code = DHCPV6_OPT_F_RELATIONSHIP_NAME, .flags = OPT_INTERNAL | OPT_NO_PASSTHRU, .str = NULL }, + { .code = DHCPV6_OPT_F_SERVER_FLAGS, .flags = OPT_INTERNAL | OPT_NO_PASSTHRU, .str = NULL }, + { .code = DHCPV6_OPT_F_SERVER_STATE, .flags = OPT_INTERNAL | OPT_NO_PASSTHRU, .str = NULL }, + { .code = DHCPV6_OPT_F_START_TIME_OF_STATE, .flags = OPT_INTERNAL | OPT_NO_PASSTHRU, .str = NULL }, + { .code = DHCPV6_OPT_F_STATE_EXPIRATION_TIME, .flags = OPT_INTERNAL | OPT_NO_PASSTHRU, .str = NULL }, + { .code = DHCPV6_OPT_RELAY_PORT, .flags = OPT_INTERNAL | OPT_NO_PASSTHRU, .str = NULL }, { .code = 0, .flags = 0, .str = NULL }, }; @@ -138,7 +186,7 @@ int main(_unused int argc, char* const argv[]) unsigned int ra_options = RA_RDNSS_DEFAULT_LIFETIME; unsigned int ra_holdoff_interval = RA_MIN_ADV_INTERVAL; - while ((c = getopt(argc, argv, "S::N:V:P:FB:c:i:r:Ru:x:s:kt:m:Lhedp:fav")) != -1) { + while ((c = getopt(argc, argv, "S::N:V:P:FB:c:i:r:Ru:Ux:s:kt:m:Lhedp:fav")) != -1) { switch (c) { case 'S': allow_slaac_only = (optarg) ? atoi(optarg) : -1; @@ -280,6 +328,10 @@ int main(_unused int argc, char* const argv[]) free(o_data); break; + case 'U': + client_options |= DHCPV6_IGNORE_OPT_UNICAST; + break; + case 's': script = optarg; break; @@ -560,6 +612,7 @@ static int usage(void) " -x dns:2001:2001::1,2001:2001::2 - option 23\n" " -x 15:office - option 15 (userclass)\n" " -x 0x1f4:ABBA - option 500\n" + " -x 202:'\"file\"' - option 202\n" " -c Override client-ID (base-16 encoded 16-bit type + value)\n" " -i Use a custom interface identifier for RA handling\n" " -r Options to be requested (comma-separated)\n" @@ -571,6 +624,7 @@ static int usage(void) " -t Maximum timeout for DHCPv6-SOLICIT (120)\n" " -m Minimum time between accepting RA updates (3)\n" " -L Ignore default lifetime for RDNSS records\n" + " -U Ignore Server Unicast option\n" "\nInvocation options:\n" " -p Set pidfile (/var/run/odhcp6c.pid)\n" " -d Daemonize\n" @@ -585,8 +639,9 @@ static int usage(void) // Don't want to pull-in librt and libpthread just for a monotonic clock... uint64_t odhcp6c_get_milli_time(void) { - struct timespec t = {0, 0}; - syscall(SYS_clock_gettime, CLOCK_MONOTONIC, &t); + struct timespec t; + + clock_gettime(CLOCK_MONOTONIC, &t); return ((uint64_t)t.tv_sec) * 1000 + ((uint64_t)t.tv_nsec) / 1000000; } @@ -969,9 +1024,40 @@ static int parse_opt_u8(const char *src, uint8_t **dst) return script_unhexlify(*dst, len, src); } +static int parse_opt_string(const char *src, uint8_t **dst, const bool array) +{ + int o_len = 0; + char *sep = get_sep_pos(src, ARRAY_SEP); + + if (sep && !array) + return -1; + + do { + if (sep) { + *sep = 0; + sep++; + } + + int len = strlen(src); + + *dst = realloc(*dst, o_len + len); + if (!*dst) + return -1; + + memcpy(&((*dst)[o_len]), src, len); + + o_len += len; + src = sep; + + if (sep) + sep = get_sep_pos(src, ARRAY_SEP); + } while (src); + + return o_len; +} + static int parse_opt_dns_string(const char *src, uint8_t **dst, const bool array) { - int i_len = strlen(src); int o_len = 0; char *sep = get_sep_pos(src, ARRAY_SEP); @@ -997,19 +1083,17 @@ static int parse_opt_dns_string(const char *src, uint8_t **dst, const bool array memcpy(&((*dst)[o_len]), tmp, len); o_len += len; - i_len -= strlen(src) + (sep ? 1 : 0); src = sep; - if (src) + if (sep) sep = get_sep_pos(src, ARRAY_SEP); - } while (i_len); + } while (src); return o_len; } static int parse_opt_ip6(const char *src, uint8_t **dst, const bool array) { - int i_len = strlen(src); int o_len = 0; char *sep = get_sep_pos(src, ARRAY_SEP); @@ -1032,19 +1116,17 @@ static int parse_opt_ip6(const char *src, uint8_t **dst, const bool array) return -1; o_len += len; - i_len -= strlen(src) + (sep ? 1 : 0); src = sep; - if (src) + if (sep) sep = get_sep_pos(src, ARRAY_SEP); - } while (i_len); + } while (src); return o_len; } static int parse_opt_user_class(const char *src, uint8_t **dst, const bool array) { - int i_len = strlen(src); int o_len = 0; char *sep = get_sep_pos(src, ARRAY_SEP); @@ -1071,12 +1153,11 @@ static int parse_opt_user_class(const char *src, uint8_t **dst, const bool array memcpy(e->data, src, str_len); o_len += str_len + 2; - i_len -= str_len + (sep ? 1 : 0); src = sep; - if (src) + if (sep) sep = get_sep_pos(src, ARRAY_SEP); - } while (i_len); + } while (src); return o_len; } @@ -1091,6 +1172,10 @@ static int parse_opt_data(const char *data, uint8_t **dst, const unsigned int ty ret = parse_opt_u8(data, dst); break; + case OPT_STR: + ret = parse_opt_string(data, dst, array); + break; + case OPT_DNS_STR: ret = parse_opt_dns_string(data, dst, array); break; @@ -1100,7 +1185,7 @@ static int parse_opt_data(const char *data, uint8_t **dst, const unsigned int ty break; case OPT_USER_CLASS: - ret = parse_opt_user_class(data, dst,array); + ret = parse_opt_user_class(data, dst, array); break; default: @@ -1151,6 +1236,16 @@ static int parse_opt(const char *opt) type = dopt->flags & OPT_MASK_SIZE; array = ((dopt->flags & OPT_ARRAY) == OPT_ARRAY) ? true : false; + } else if (data[0] == '"' || data[0] == '\'') { + char *end = strrchr(data + 1, data[0]); + + if (end && (end == (data + strlen(data) - 1))) { + /* Raw option is specified as a string */ + type = OPT_STR; + data++; + *end = '\0'; + } + } payload_len = parse_opt_data(data, &payload, type, array);