summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLuiz Amaral <email@luiz.eng.br>2024-05-05 13:52:31 +0200
committerLuiz Amaral <email@luiz.eng.br>2024-05-05 13:52:31 +0200
commit9eff72d3a5bdebd6ee41b1891460ca6c5a2fb0fb (patch)
treeb0fdae1d914e46baa3b40a65da2535546e99ee1d
parent55de7e2b5260cab8432c494b7bcd2debb5c2ebab (diff)
downloadaccel-ppp-9eff72d3a5bdebd6ee41b1891460ca6c5a2fb0fb.tar.gz
accel-ppp-9eff72d3a5bdebd6ee41b1891460ca6c5a2fb0fb.zip
ipv6_dhcp: Add RFC6334 AFTR-Name option support
-rw-r--r--accel-pppd/accel-ppp.conf.58
-rw-r--r--accel-pppd/ipv6/dhcpv6.c61
-rw-r--r--accel-pppd/ipv6/dhcpv6.h2
-rw-r--r--accel-pppd/ipv6/dhcpv6_packet.c20
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;