diff options
author | Luiz Amaral <email@luiz.eng.br> | 2024-05-05 13:52:31 +0200 |
---|---|---|
committer | Luiz Amaral <email@luiz.eng.br> | 2024-05-05 13:52:31 +0200 |
commit | 9eff72d3a5bdebd6ee41b1891460ca6c5a2fb0fb (patch) | |
tree | b0fdae1d914e46baa3b40a65da2535546e99ee1d | |
parent | 55de7e2b5260cab8432c494b7bcd2debb5c2ebab (diff) | |
download | accel-ppp-9eff72d3a5bdebd6ee41b1891460ca6c5a2fb0fb.tar.gz accel-ppp-9eff72d3a5bdebd6ee41b1891460ca6c5a2fb0fb.zip |
ipv6_dhcp: Add RFC6334 AFTR-Name option support
-rw-r--r-- | accel-pppd/accel-ppp.conf.5 | 8 | ||||
-rw-r--r-- | accel-pppd/ipv6/dhcpv6.c | 61 | ||||
-rw-r--r-- | accel-pppd/ipv6/dhcpv6.h | 2 | ||||
-rw-r--r-- | accel-pppd/ipv6/dhcpv6_packet.c | 20 |
4 files changed, 90 insertions, 1 deletions
diff --git a/accel-pppd/accel-ppp.conf.5 b/accel-pppd/accel-ppp.conf.5 index 1086a4ce..1c7fb9fd 100644 --- a/accel-pppd/accel-ppp.conf.5 +++ b/accel-pppd/accel-ppp.conf.5 @@ -73,6 +73,10 @@ IPv4 address assigning module. .br IPv6 address assigning module. .TP +.BI ipv6_dhcp +.br +IPv6 DHCP module. +.TP .BI sigchld Helper module to manage child processes, required by pppd_compat .TP @@ -1148,6 +1152,10 @@ Specifies which Radius attribute contains pool name. .TP .BI "vendor=" vendor If attribute is vendor-specific then specify vendor name in this option. +.SH [ipv6-dhcp] +.TP +.BI "aftr-gw=" name +Specifies the AFTR-Name option value to be returned on DHCPv6 replies upon request from the client. .SH [ipv6-pool] .br Configuration of ipv6pool module. diff --git a/accel-pppd/ipv6/dhcpv6.c b/accel-pppd/ipv6/dhcpv6.c index 158771b1..77fc32f7 100644 --- a/accel-pppd/ipv6/dhcpv6.c +++ b/accel-pppd/ipv6/dhcpv6.c @@ -40,6 +40,9 @@ static int conf_pref_lifetime = 604800; static int conf_valid_lifetime = 2592000; static struct dhcpv6_opt_serverid *conf_serverid = &serverid.hdr; static int conf_route_via_gw = 1; +static uint8_t *conf_aftr_gw; +static int conf_aftr_gw_size; + static struct in6_addr conf_dns[MAX_DNS_COUNT]; static int conf_dns_count; @@ -233,6 +236,11 @@ static void insert_oro(struct dhcpv6_packet *reply, struct dhcpv6_option *opt) opt1 = dhcpv6_option_alloc(reply, D6_OPTION_DOMAIN_LIST, conf_dnssl_size); memcpy(opt1->hdr->data, conf_dnssl, conf_dnssl_size); } + } else if (ntohs(*ptr) == D6_OPTION_AFTR_NAME) { + if (conf_aftr_gw_size) { + opt1 = dhcpv6_option_alloc(reply, D6_OPTION_AFTR_NAME, conf_aftr_gw_size); + memcpy(opt1->hdr->data, conf_aftr_gw, conf_aftr_gw_size); + } } } } @@ -831,6 +839,53 @@ static int dhcpv6_read(struct triton_md_handler_t *h) return 0; } +static void add_aftr_gw(const char *val) +{ + int n = strlen(val); + const char *ptr; + uint8_t *buf; + + if (!val) + return; + + if (val[n - 1] == '.') + n++; + else + n += 2; + + if (n > 255) { + log_error("dnsv6: AFTR-Name '%s' is too long\n", val); + return; + } + + if (!conf_aftr_gw) + conf_aftr_gw = _malloc(n); + else + conf_aftr_gw = _realloc(conf_aftr_gw, conf_aftr_gw_size + n); + + buf = conf_aftr_gw + conf_aftr_gw_size; + + while (1) { + ptr = strchr(val, '.'); + if (!ptr) + ptr = strchr(val, 0); + if (ptr - val > 63) { + log_error("dnsv6: AFTR-Name '%s' is invalid\n", val); + return; + } + *buf = ptr - val; + memcpy(buf + 1, val, ptr - val); + buf += 1 + (ptr - val); + val = ptr + 1; + if (!*ptr || !*val) { + *buf = 0; + break; + } + } + + conf_aftr_gw_size += n; +} + static void add_dnssl(const char *val) { int n = strlen(val); @@ -959,6 +1014,12 @@ static void load_config(void) if (opt) conf_route_via_gw = atoi(opt); + opt = conf_get_opt("ipv6-dhcp", "aftr-gw"); + if (opt) { + add_aftr_gw(opt); + } + + opt = conf_get_opt("ipv6-dhcp", "server-id"); if (opt) id = parse_serverid(opt); diff --git a/accel-pppd/ipv6/dhcpv6.h b/accel-pppd/ipv6/dhcpv6.h index 32ee7154..2326e639 100644 --- a/accel-pppd/ipv6/dhcpv6.h +++ b/accel-pppd/ipv6/dhcpv6.h @@ -34,7 +34,7 @@ #define D6_OPTION_DOMAIN_LIST 24 #define D6_OPTION_IA_PD 25 #define D6_OPTION_IAPREFIX 26 -#define D6_OPTION_IAPREFIX 26 +#define D6_OPTION_AFTR_NAME 64 #define D6_SOLICIT 1 #define D6_ADVERTISE 2 diff --git a/accel-pppd/ipv6/dhcpv6_packet.c b/accel-pppd/ipv6/dhcpv6_packet.c index 4173ba78..1890bc11 100644 --- a/accel-pppd/ipv6/dhcpv6_packet.c +++ b/accel-pppd/ipv6/dhcpv6_packet.c @@ -31,6 +31,7 @@ static void print_status(struct dhcpv6_option *opt, void (*print)(const char *fm static void print_reconf(struct dhcpv6_option *opt, void (*print)(const char *fmt, ...)); static void print_dnssl(struct dhcpv6_option *opt, void (*print)(const char *fmt, ...)); static void print_ia_prefix(struct dhcpv6_option *opt, void (*print)(const char *fmt, ...)); +static void print_aftr_gw(struct dhcpv6_option *opt, void (*print)(const char *fmt, ...)); static struct dict_option known_options[] = { { D6_OPTION_CLIENTID, "Client-ID", 1, 0, print_clientid }, @@ -56,6 +57,7 @@ static struct dict_option known_options[] = { { D6_OPTION_DOMAIN_LIST, "DNSSL", 1, 0, print_dnssl }, { D6_OPTION_IA_PD, "IA-PD", 1, sizeof(struct dhcpv6_opt_ia_na), print_ia_na }, { D6_OPTION_IAPREFIX, "IA-Prefix", 1, sizeof(struct dhcpv6_opt_ia_prefix), print_ia_prefix }, + { D6_OPTION_AFTR_NAME, "AFTR-Name", 1, 0, print_aftr_gw }, { 0 } }; @@ -549,6 +551,24 @@ static void print_dnssl(struct dhcpv6_option *opt, void (*print)(const char *fmt } +static void print_aftr_gw(struct dhcpv6_option *opt, void (*print)(const char *fmt, ...)) { + int len = ntohs(opt->hdr->len); + int offset = 0; + char domain[255]; + uint8_t label_len; + + memset(domain, 0, 255); + while (offset < len) { + label_len = opt->hdr->data[offset]; + if (label_len == 0) + break; + memcpy(&domain[offset], &opt->hdr->data[offset + 1], label_len); + offset += label_len; + domain[offset++] = '.'; + } + print(" %s", domain); +} + static void print_ia_prefix(struct dhcpv6_option *opt, void (*print)(const char *fmt, ...)) { struct dhcpv6_opt_ia_prefix *o = (struct dhcpv6_opt_ia_prefix *)opt->hdr; |