summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorxebd <xeb@mail.ru>2020-01-13 12:27:15 +0300
committerGitHub <noreply@github.com>2020-01-13 12:27:15 +0300
commit183ecb17cdb3f3a29912e1eea70603657ad221f0 (patch)
tree2a7558853c2451fed00f3d10ea1c9ed641bacfe0
parent61862862a9fa24db4f16c24db1aed1f1a5f0be19 (diff)
parentf532c72d0cb33b16b9794d83a46969538bdf2596 (diff)
downloadaccel-ppp-183ecb17cdb3f3a29912e1eea70603657ad221f0.tar.gz
accel-ppp-183ecb17cdb3f3a29912e1eea70603657ad221f0.zip
Merge pull request #110 from themiron/ipv6-pool
Add named ipv6 pools support
-rw-r--r--accel-pppd/accel-ppp.conf15
-rw-r--r--accel-pppd/accel-ppp.conf.525
-rw-r--r--accel-pppd/ctrl/ipoe/ipoe.c16
-rw-r--r--accel-pppd/ctrl/l2tp/l2tp.c25
-rw-r--r--accel-pppd/ctrl/pppoe/pppoe.c8
-rw-r--r--accel-pppd/ctrl/pptp/pptp.c8
-rw-r--r--accel-pppd/ctrl/sstp/sstp.c8
-rw-r--r--accel-pppd/extra/chap-secrets.c8
-rw-r--r--accel-pppd/extra/ipv6pool.c304
-rw-r--r--accel-pppd/include/ap_session.h1
-rw-r--r--accel-pppd/radius/attr_defs.h5
-rw-r--r--accel-pppd/radius/dict.c2
-rw-r--r--accel-pppd/radius/dict/dictionary1
-rw-r--r--accel-pppd/radius/dict/dictionary.rfc691112
-rw-r--r--accel-pppd/session.c5
-rw-r--r--rfc/rfc6911.txt843
16 files changed, 1238 insertions, 48 deletions
diff --git a/accel-pppd/accel-ppp.conf b/accel-pppd/accel-ppp.conf
index a4ece60..144bf1f 100644
--- a/accel-pppd/accel-ppp.conf
+++ b/accel-pppd/accel-ppp.conf
@@ -84,6 +84,8 @@ called-sid=mac
#tr101=1
#padi-limit=0
#ip-pool=pppoe
+#ipv6-pool=pppoe
+#ipv6-pool-delegate=pppoe
#ifname=pppoe%d
#sid-uppercase=0
#vlan-mon=eth0,10-200
@@ -107,6 +109,8 @@ verbose=1
#dataseq=allow
#reorder-timeout=0
#ip-pool=l2tp
+#ipv6-pool=l2tp
+#ipv6-pool-delegate=l2tp
#ifname=l2tp%d
[sstp]
@@ -128,6 +132,8 @@ verbose=1
#timeout=60
#hello-interval=60
#ip-pool=sstp
+#ipv6-pool=sstp
+#ipv6-pool-delegate=sstp
#ifname=sstp%d
[ipoe]
@@ -171,6 +177,8 @@ start=dhcpv4
#vlan-timeout=60
#vlan-name=%I.%N
#ip-pool=ipoe
+#ipv6-pool=ipoe
+#ipv6-pool-delegate=ipoe
#idle-timeout=0
#session-timeout=0
#soft-terminate=0
@@ -290,8 +298,15 @@ timeout=60
[ipv6-pool]
#gw-ip6-address=fc00:0:1::1
+#vendor=
+#attr-prefix=Delegated-IPv6-Prefix-Pool
+#attr-address=Stateful-IPv6-Address-Pool
fc00:0:1::/48,64
+fc00:0:2::/48,64,name=pool1
+fc00:0:3::/48,64,name=pool2,next=pool1
delegate=fc00:1::/36,48
+delegate=fc00:2::/36,48,name=pool3
+delegate=fc00:3::/36,48,name=pool4,next=pool3
[ipv6-dns]
#fc00:1::1
diff --git a/accel-pppd/accel-ppp.conf.5 b/accel-pppd/accel-ppp.conf.5
index 982bbd1..3e6312f 100644
--- a/accel-pppd/accel-ppp.conf.5
+++ b/accel-pppd/accel-ppp.conf.5
@@ -1022,27 +1022,34 @@ If attribute is vendor-specific then specify vendor name in this option.
.SH [ipv6-pool]
.br
Configuration of ipv6pool module.
+.TP
+.BI ipv6prefix/mask,prefix_len[,name=pool_name][,next=next_pool_name]
.br
-Format of each row is
-.br
-.B ipv6prefix/mask,prefix_len
-for example:
-.br
-.B fc00:0:1::/48,64
-- specifies pool of address by dividing prefix fc00:0:1::/48 to networks with 64 prefix len, e.g:
+.B fc00:0:1::/48,64 - specifies pool of address by dividing prefix fc00:0:1::/48 to networks with 64 prefix len, e.g:
.br
fc00:0:1:0::/64
.br
fc00:0:1:1::/64
.br
-...
+ ...
+.br
fc00:0:1:ffff::/64
.TP
-.BI "delegate=" ipv6prefix/mask,prefix_len
+.BI "delegate=" ipv6prefix/mask,prefix_len[,name=pool_name][,next=next_pool_name]
Specifies range of prefixes to delegate to clients through DHCPv6 prefix delegation (rfc3633).
Format is same as described above.
+.TP
.BI "gw-ip6-address=" ipv6address
Specifies gateway address (used only for /128 prefixes)
+.TP
+.BI "attr-prefix=" attribute
+Specifies which Radius attribute contains delegated prefix pool name.
+.TP
+.BI "attr-address=" attribute
+Specifies which Radius attribute contains stateful address pool name.
+.TP
+.BI "vendor=" vendor
+If attribute is vendor-specific then specify vendor name in this option.
.SH [connlimit]
.br
This module limits connection rate from single source.
diff --git a/accel-pppd/ctrl/ipoe/ipoe.c b/accel-pppd/ctrl/ipoe/ipoe.c
index 45f66b7..b1504a2 100644
--- a/accel-pppd/ctrl/ipoe/ipoe.c
+++ b/accel-pppd/ctrl/ipoe/ipoe.c
@@ -119,6 +119,8 @@ static int conf_arp;
static int conf_ipv6;
static uint32_t conf_src;
static const char *conf_ip_pool;
+static const char *conf_ipv6_pool;
+static const char *conf_dpv6_pool;
static const char *conf_l4_redirect_pool;
//static int conf_dhcpv6;
static int conf_username;
@@ -1366,6 +1368,10 @@ static struct ipoe_session *ipoe_session_create_dhcpv4(struct ipoe_serv *serv, s
if (conf_ip_pool)
ses->ses.ipv4_pool_name = _strdup(conf_ip_pool);
+ if (conf_ipv6_pool)
+ ses->ses.ipv6_pool_name = _strdup(conf_ipv6_pool);
+ if (conf_dpv6_pool)
+ ses->ses.dpv6_pool_name = _strdup(conf_dpv6_pool);
triton_context_register(&ses->ctx, &ses->ses);
@@ -2073,6 +2079,10 @@ static struct ipoe_session *ipoe_session_create_up(struct ipoe_serv *serv, struc
if (conf_ip_pool)
ses->ses.ipv4_pool_name = _strdup(conf_ip_pool);
+ if (conf_ipv6_pool)
+ ses->ses.ipv6_pool_name = _strdup(conf_ipv6_pool);
+ if (conf_dpv6_pool)
+ ses->ses.dpv6_pool_name = _strdup(conf_dpv6_pool);
ses->ctrl.dont_ifcfg = 1;
@@ -2118,6 +2128,10 @@ static void ipoe_session_create_auto(struct ipoe_serv *serv)
if (conf_ip_pool)
ses->ses.ipv4_pool_name = _strdup(conf_ip_pool);
+ if (conf_ipv6_pool)
+ ses->ses.ipv6_pool_name = _strdup(conf_ipv6_pool);
+ if (conf_dpv6_pool)
+ ses->ses.dpv6_pool_name = _strdup(conf_dpv6_pool);
ses->ctrl.dont_ifcfg = 1;
@@ -3915,6 +3929,8 @@ static void load_config(void)
conf_offer_timeout = 10;
conf_ip_pool = conf_get_opt("ipoe", "ip-pool");
+ conf_ipv6_pool = conf_get_opt("ipoe", "ipv6-pool");
+ conf_dpv6_pool = conf_get_opt("ipoe", "ipv6-pool-delegate");
conf_l4_redirect_pool = conf_get_opt("ipoe", "l4-redirect-ip-pool");
conf_vlan_name = conf_get_opt("ipoe", "vlan-name");
diff --git a/accel-pppd/ctrl/l2tp/l2tp.c b/accel-pppd/ctrl/l2tp/l2tp.c
index 6c10848..0d1ca21 100644
--- a/accel-pppd/ctrl/l2tp/l2tp.c
+++ b/accel-pppd/ctrl/l2tp/l2tp.c
@@ -94,6 +94,8 @@ static int conf_mppe = MPPE_UNSET;
static int conf_dataseq = L2TP_DATASEQ_ALLOW;
static int conf_reorder_timeout = 0;
static const char *conf_ip_pool;
+static const char *conf_ipv6_pool;
+static const char *conf_dpv6_pool;
static const char *conf_ifname;
static unsigned int stat_conn_starting;
@@ -1791,12 +1793,23 @@ static int l2tp_session_start_data_channel(struct l2tp_sess_t *sess)
if (conf_ip_pool) {
sess->ppp.ses.ipv4_pool_name = _strdup(conf_ip_pool);
if (sess->ppp.ses.ipv4_pool_name == NULL) {
+ err_pool:
log_session(log_error, sess,
"impossible to start data channel:"
- " allocation of IPv4 pool name failed\n");
+ " allocation of pool name failed\n");
goto err;
}
}
+ if (conf_ipv6_pool) {
+ sess->ppp.ses.ipv6_pool_name = _strdup(conf_ipv6_pool);
+ if (sess->ppp.ses.ipv6_pool_name == NULL)
+ goto err_pool;
+ }
+ if (conf_dpv6_pool) {
+ sess->ppp.ses.dpv6_pool_name = _strdup(conf_dpv6_pool);
+ if (sess->ppp.ses.dpv6_pool_name == NULL)
+ goto err_pool;
+ }
if (conf_ifname)
sess->ppp.ses.ifname_rename = _strdup(conf_ifname);
@@ -1836,6 +1849,14 @@ err:
_free(sess->ppp.ses.ipv4_pool_name);
sess->ppp.ses.ipv4_pool_name = NULL;
}
+ if (sess->ppp.ses.ipv6_pool_name) {
+ _free(sess->ppp.ses.ipv6_pool_name);
+ sess->ppp.ses.ipv6_pool_name = NULL;
+ }
+ if (sess->ppp.ses.dpv6_pool_name) {
+ _free(sess->ppp.ses.dpv6_pool_name);
+ sess->ppp.ses.dpv6_pool_name = NULL;
+ }
if (sess->ctrl.called_station_id) {
_free(sess->ctrl.called_station_id);
sess->ctrl.called_station_id = NULL;
@@ -4938,6 +4959,8 @@ static void load_config(void)
}
conf_ip_pool = conf_get_opt("l2tp", "ip-pool");
+ conf_ipv6_pool = conf_get_opt("l2tp", "ipv6-pool");
+ conf_dpv6_pool = conf_get_opt("l2tp", "ipv6-pool-delegate");
conf_ifname = conf_get_opt("l2tp", "ifname");
switch (iprange_check_activation()) {
diff --git a/accel-pppd/ctrl/pppoe/pppoe.c b/accel-pppd/ctrl/pppoe/pppoe.c
index a1f54e7..32dee77 100644
--- a/accel-pppd/ctrl/pppoe/pppoe.c
+++ b/accel-pppd/ctrl/pppoe/pppoe.c
@@ -99,6 +99,8 @@ int conf_padi_limit = 0;
int conf_mppe = MPPE_UNSET;
int conf_sid_uppercase = 0;
static const char *conf_ip_pool;
+static const char *conf_ipv6_pool;
+static const char *conf_dpv6_pool;
static const char *conf_ifname;
enum {CSID_MAC, CSID_IFNAME, CSID_IFNAME_MAC};
static int conf_called_sid;
@@ -409,6 +411,10 @@ static struct pppoe_conn_t *allocate_channel(struct pppoe_serv_t *serv, const ui
if (conf_ip_pool)
conn->ppp.ses.ipv4_pool_name = _strdup(conf_ip_pool);
+ if (conf_ipv6_pool)
+ conn->ppp.ses.ipv6_pool_name = _strdup(conf_ipv6_pool);
+ if (conf_dpv6_pool)
+ conn->ppp.ses.dpv6_pool_name = _strdup(conf_dpv6_pool);
if (conf_ifname)
conn->ppp.ses.ifname_rename = _strdup(conf_ifname);
@@ -2028,6 +2034,8 @@ static void load_config(void)
}
conf_ip_pool = conf_get_opt("pppoe", "ip-pool");
+ conf_ipv6_pool = conf_get_opt("pppoe", "ipv6-pool");
+ conf_dpv6_pool = conf_get_opt("pppoe", "ipv6-pool-delegate");
conf_ifname = conf_get_opt("pppoe", "ifname");
conf_called_sid = CSID_MAC;
diff --git a/accel-pppd/ctrl/pptp/pptp.c b/accel-pppd/ctrl/pptp/pptp.c
index 081e921..1161da5 100644
--- a/accel-pppd/ctrl/pptp/pptp.c
+++ b/accel-pppd/ctrl/pptp/pptp.c
@@ -63,6 +63,8 @@ static int conf_echo_failure = 3;
static int conf_verbose = 0;
static int conf_mppe = MPPE_UNSET;
static const char *conf_ip_pool;
+static const char *conf_ipv6_pool;
+static const char *conf_dpv6_pool;
static const char *conf_ifname;
static mempool_t conn_pool;
@@ -713,6 +715,10 @@ static int pptp_connect(struct triton_md_handler_t *h)
if (conf_ip_pool)
conn->ppp.ses.ipv4_pool_name = _strdup(conf_ip_pool);
+ if (conf_ipv6_pool)
+ conn->ppp.ses.ipv6_pool_name = _strdup(conf_ipv6_pool);
+ if (conf_dpv6_pool)
+ conn->ppp.ses.dpv6_pool_name = _strdup(conf_dpv6_pool);
if (conf_ifname)
conn->ppp.ses.ifname_rename = _strdup(conf_ifname);
@@ -802,6 +808,8 @@ static void load_config(void)
}
conf_ip_pool = conf_get_opt("pptp", "ip-pool");
+ conf_ipv6_pool = conf_get_opt("pptp", "ipv6-pool");
+ conf_dpv6_pool = conf_get_opt("pptp", "ipv6-pool-delegate");
conf_ifname = conf_get_opt("pptp", "ifname");
switch (iprange_check_activation()) {
diff --git a/accel-pppd/ctrl/sstp/sstp.c b/accel-pppd/ctrl/sstp/sstp.c
index 62e574c..5bf8fd8 100644
--- a/accel-pppd/ctrl/sstp/sstp.c
+++ b/accel-pppd/ctrl/sstp/sstp.c
@@ -159,6 +159,8 @@ static int conf_hello_interval = SSTP_HELLO_TIMEOUT;
static int conf_verbose = 0;
static int conf_ppp_max_mtu = 1452;
static const char *conf_ip_pool;
+static const char *conf_ipv6_pool;
+static const char *conf_dpv6_pool;
static const char *conf_ifname;
static int conf_proxyproto = 0;
@@ -2276,6 +2278,10 @@ static int sstp_connect(struct triton_md_handler_t *h)
conn->ppp.ses.chan_name = _strdup(addr_buf);
if (conf_ip_pool)
conn->ppp.ses.ipv4_pool_name = _strdup(conf_ip_pool);
+ if (conf_ipv6_pool)
+ conn->ppp.ses.ipv6_pool_name = _strdup(conf_ipv6_pool);
+ if (conf_dpv6_pool)
+ conn->ppp.ses.dpv6_pool_name = _strdup(conf_dpv6_pool);
if (conf_ifname)
conn->ppp.ses.ifname_rename = _strdup(conf_ifname);
@@ -2693,6 +2699,8 @@ static void load_config(void)
conf_ppp_max_mtu = atoi(opt);
conf_ip_pool = conf_get_opt("sstp", "ip-pool");
+ conf_ipv6_pool = conf_get_opt("sstp", "ipv6-pool");
+ conf_dpv6_pool = conf_get_opt("sstp", "ipv6-pool-delegate");
conf_ifname = conf_get_opt("sstp", "ifname");
ipmode = (serv.addr.u.sa.sa_family == AF_INET && !conf_proxyproto) ?
diff --git a/accel-pppd/extra/chap-secrets.c b/accel-pppd/extra/chap-secrets.c
index 92cfb42..0fadc9c 100644
--- a/accel-pppd/extra/chap-secrets.c
+++ b/accel-pppd/extra/chap-secrets.c
@@ -313,6 +313,14 @@ static struct ipv4db_item_t *get_ip(struct ap_session *ses)
if (ses->ipv4_pool_name)
_free(ses->ipv4_pool_name);
ses->ipv4_pool_name = _strdup(pd->pool);
+/* TODO: wrong to use same pool name, but there's no other syntax
+ if (ses->ipv6_pool_name)
+ _free(ses->ipv6_pool_name);
+ ses->ipv6_pool_name = _strdup(pd->pool);
+ if (ses->dpv6_pool_name)
+ _free(ses->dpv6_pool_name);
+ ses->dpv6_pool_name = _strdup(pd->pool);
+*/
return NULL;
} else if (!pd->ip.peer_addr)
return NULL;
diff --git a/accel-pppd/extra/ipv6pool.c b/accel-pppd/extra/ipv6pool.c
index 4f29a28..a2cf30d 100644
--- a/accel-pppd/extra/ipv6pool.c
+++ b/accel-pppd/extra/ipv6pool.c
@@ -8,31 +8,60 @@
#include <arpa/inet.h>
#include <endian.h>
+#include "events.h"
#include "ipdb.h"
#include "list.h"
#include "log.h"
#include "spinlock.h"
+#ifdef RADIUS
+#include "radius.h"
+#endif
+
#include "memdebug.h"
+enum ippool_type
+{
+ IPPOOL_ADDRESS,
+ IPPOOL_PREFIX
+};
+
+struct ippool_t
+{
+ struct list_head entry;
+ char *name;
+ struct list_head gw_list;
+ struct list_head items;
+ struct ippool_t *next;
+ spinlock_t lock;
+};
struct ippool_item_t
{
struct list_head entry;
+ struct ippool_t *pool;
struct ipv6db_item_t it;
};
struct dppool_item_t
{
struct list_head entry;
+ struct ippool_t *pool;
struct ipv6db_prefix_t it;
};
-static LIST_HEAD(ippool);
-static LIST_HEAD(dppool);
-static spinlock_t pool_lock;
+#ifdef RADIUS
+static int conf_vendor = 0;
+static int conf_dppool_attr = 171; // Delegated-IPv6-Prefix-Pool
+static int conf_ippool_attr = 172; // Stateful-IPv6-Address-Pool
+#endif
+
+static LIST_HEAD(ippool_list);
+static LIST_HEAD(dppool_list);
static struct ipdb_t ipdb;
static struct in6_addr conf_gw_addr;
+static struct ippool_t *def_ippool;
+static struct ippool_t *def_dppool;
static void in6_addr_add(struct in6_addr *res, const struct in6_addr *arg)
{
@@ -59,7 +88,40 @@ static int in6_addr_cmp(const struct in6_addr *n1, const struct in6_addr *n2)
return 0;
}
-static void generate_ippool(struct in6_addr *addr, int mask, int prefix_len)
+static struct ippool_t *create_pool(enum ippool_type type, char *name)
+{
+ struct ippool_t *pool = malloc(sizeof(*pool));
+ struct list_head *pool_list = (type == IPPOOL_PREFIX) ? &dppool_list : &ippool_list;
+
+ memset(pool, 0, sizeof(*pool));
+ pool->name = name;
+
+ INIT_LIST_HEAD(&pool->items);
+ spinlock_init(&pool->lock);
+
+ if (name)
+ list_add_tail(&pool->entry, pool_list);
+
+ return pool;
+}
+
+static struct ippool_t *find_pool(enum ippool_type type, char *name, int create)
+{
+ struct ippool_t *pool;
+ struct list_head *pool_list = (type == IPPOOL_PREFIX) ? &dppool_list : &ippool_list;
+
+ list_for_each_entry(pool, pool_list, entry) {
+ if (!strcmp(pool->name, name))
+ return pool;
+ }
+
+ if (create)
+ return create_pool(type, name);
+
+ return NULL;
+}
+
+static void generate_ippool(struct ippool_t *pool, struct in6_addr *addr, int mask, int prefix_len)
{
struct ippool_item_t *it;
struct ipv6db_addr_t *a;
@@ -84,6 +146,7 @@ static void generate_ippool(struct in6_addr *addr, int mask, int prefix_len)
while (in6_addr_cmp(&ip, &end) <= 0) {
it = malloc(sizeof(*it));
memset(it, 0, sizeof(*it));
+ it->pool = pool;
it->it.owner = &ipdb;
INIT_LIST_HEAD(&it->it.addr_list);
a = malloc(sizeof(*a));
@@ -91,12 +154,12 @@ static void generate_ippool(struct in6_addr *addr, int mask, int prefix_len)
memcpy(&a->addr, &ip, sizeof(ip));
a->prefix_len = prefix_len;
list_add_tail(&a->entry, &it->it.addr_list);
- list_add_tail(&it->entry, &ippool);
+ list_add_tail(&it->entry, &pool->items);
in6_addr_add(&ip, &step);
}
}
-static void generate_dppool(struct in6_addr *addr, int mask, int prefix_len)
+static void generate_dppool(struct ippool_t *pool, struct in6_addr *addr, int mask, int prefix_len)
{
struct dppool_item_t *it;
struct in6_addr ip, end, step;
@@ -121,6 +184,7 @@ static void generate_dppool(struct in6_addr *addr, int mask, int prefix_len)
while (in6_addr_cmp(&ip, &end) <= 0) {
it = malloc(sizeof(*it));
memset(it, 0, sizeof(*it));
+ it->pool = pool;
it->it.owner = &ipdb;
INIT_LIST_HEAD(&it->it.prefix_list);
a = malloc(sizeof(*a));
@@ -128,13 +192,12 @@ static void generate_dppool(struct in6_addr *addr, int mask, int prefix_len)
memcpy(&a->addr, &ip, sizeof(ip));
a->prefix_len = prefix_len;
list_add_tail(&a->entry, &it->it.prefix_list);
- list_add_tail(&it->entry, &dppool);
+ list_add_tail(&it->entry, &pool->items);
in6_addr_add(&ip, &step);
}
}
-
-static void add_prefix(int type, const char *_val)
+static void add_prefix(enum ippool_type type, struct ippool_t *pool, const char *_val)
{
char *val = _strdup(_val);
char *ptr1, *ptr2;
@@ -169,10 +232,10 @@ static void add_prefix(int type, const char *_val)
if (prefix_len > 128 || prefix_len < mask)
goto err;
- if (type)
- generate_dppool(&addr, mask, prefix_len);
+ if (type == IPPOOL_PREFIX)
+ generate_dppool(pool, &addr, mask, prefix_len);
else
- generate_ippool(&addr, mask, prefix_len);
+ generate_ippool(pool, &addr, mask, prefix_len);
_free(val);
return;
@@ -186,14 +249,24 @@ static struct ipv6db_item_t *get_ip(struct ap_session *ses)
{
struct ippool_item_t *it;
struct ipv6db_addr_t *a;
+ struct ippool_t *pool;
+
+ if (ses->ipv6_pool_name)
+ pool = find_pool(IPPOOL_ADDRESS, ses->ipv6_pool_name, 0);
+ else
+ pool = def_ippool;
+
+ if (!pool)
+ return NULL;
- spin_lock(&pool_lock);
- if (!list_empty(&ippool)) {
- it = list_entry(ippool.next, typeof(*it), entry);
+again:
+ spin_lock(&pool->lock);
+ if (!list_empty(&pool->items)) {
+ it = list_entry(pool->items.next, typeof(*it), entry);
list_del(&it->entry);
} else
it = NULL;
- spin_unlock(&pool_lock);
+ spin_unlock(&pool->lock);
if (it) {
a = list_entry(it->it.addr_list.next, typeof(*a), entry);
@@ -206,6 +279,9 @@ static struct ipv6db_item_t *get_ip(struct ap_session *ses)
}
return &it->it;
+ } else if (pool->next) {
+ pool = pool->next;
+ goto again;
}
return NULL;
@@ -215,33 +291,47 @@ static void put_ip(struct ap_session *ses, struct ipv6db_item_t *it)
{
struct ippool_item_t *pit = container_of(it, typeof(*pit), it);
- spin_lock(&pool_lock);
- list_add_tail(&pit->entry, &ippool);
- spin_unlock(&pool_lock);
+ spin_lock(&pit->pool->lock);
+ list_add_tail(&pit->entry, &pit->pool->items);
+ spin_unlock(&pit->pool->lock);
}
static struct ipv6db_prefix_t *get_dp(struct ap_session *ses)
{
struct dppool_item_t *it;
+ struct ippool_t *pool;
- spin_lock(&pool_lock);
- if (!list_empty(&dppool)) {
- it = list_entry(dppool.next, typeof(*it), entry);
+ if (ses->ipv6_pool_name)
+ pool = find_pool(IPPOOL_PREFIX, ses->dpv6_pool_name, 0);
+ else
+ pool = def_dppool;
+
+again:
+ spin_lock(&pool->lock);
+ if (!list_empty(&pool->items)) {
+ it = list_entry(pool->items.next, typeof(*it), entry);
list_del(&it->entry);
} else
it = NULL;
- spin_unlock(&pool_lock);
+ spin_unlock(&pool->lock);
- return it ? &it->it : NULL;
+ if (it)
+ return &it->it;
+ else if (pool->next) {
+ pool = pool->next;
+ goto again;
+ }
+
+ return NULL;
}
static void put_dp(struct ap_session *ses, struct ipv6db_prefix_t *it)
{
struct dppool_item_t *pit = container_of(it, typeof(*pit), it);
- spin_lock(&pool_lock);
- list_add_tail(&pit->entry, &dppool);
- spin_unlock(&pool_lock);
+ spin_lock(&pit->pool->lock);
+ list_add_tail(&pit->entry, &pit->pool->items);
+ spin_unlock(&pit->pool->lock);
}
static struct ipdb_t ipdb = {
@@ -251,28 +341,168 @@ static struct ipdb_t ipdb = {
.put_ipv6_prefix = put_dp,
};
-static void ippool_init(void)
+#ifdef RADIUS
+static void ev_radius_access_accept(struct ev_radius_t *ev)
+{
+ struct rad_attr_t *attr;
+ struct ap_session *ses = ev->ses;
+
+ list_for_each_entry(attr, &ev->reply->attrs, entry) {
+ if (attr->attr->type != ATTR_TYPE_STRING)
+ continue;
+ if (attr->vendor && attr->vendor->id != conf_vendor)
+ continue;
+ if (!attr->vendor && conf_vendor)
+ continue;
+
+ if (conf_dppool_attr && conf_dppool_attr == attr->attr->id) {
+ if (ses->dpv6_pool_name)
+ _free(ses->dpv6_pool_name);
+ ses->dpv6_pool_name = _strdup(attr->val.string);
+ } else
+ if (conf_ippool_attr && conf_ippool_attr == attr->attr->id) {
+ if (ses->ipv6_pool_name)
+ _free(ses->ipv6_pool_name);
+ ses->ipv6_pool_name = _strdup(attr->val.string);
+ }
+ }
+}
+
+static int parse_attr_opt(const char *opt)
+{
+ struct rad_dict_attr_t *attr;
+ struct rad_dict_vendor_t *vendor;
+
+ if (conf_vendor)
+ vendor = rad_dict_find_vendor_id(conf_vendor);
+ else
+ vendor = NULL;
+
+ if (conf_vendor) {
+ if (vendor)
+ attr = rad_dict_find_vendor_attr(vendor, opt);
+ else
+ attr = NULL;
+ } else
+ attr = rad_dict_find_attr(opt);
+
+ if (attr)
+ return attr->id;
+
+ return atoi(opt);
+}
+
+static int parse_vendor_opt(const char *opt)
+{
+ struct rad_dict_vendor_t *vendor;
+
+ vendor = rad_dict_find_vendor_name(opt);
+ if (vendor)
+ return vendor->id;
+
+ return atoi(opt);
+}
+#endif
+
+static void parse_options(enum ippool_type type, const char *opt, char **pool_name, struct ippool_t **next)
+{
+ char *ptr1, *ptr2, *tmp;
+
+ ptr1 = strstr(opt, ",name=");
+ if (ptr1) {
+ ptr1 += sizeof(",name=") - 1;
+ ptr2 = strchrnul(ptr1, ',');
+ *pool_name = _strndup(ptr1, ptr2 - ptr1);
+ }
+
+ ptr1 = strstr(opt, ",next=");
+ if (ptr1) {
+ ptr1 += sizeof(",next=") - 1;
+ ptr2 = strchrnul(ptr1, ',');
+ if (*ptr2 == ',') {
+ tmp = alloca(ptr2 - ptr1 + 1);
+ strncpy(tmp, ptr1, ptr2 - ptr1);
+ ptr1 = tmp;
+ }
+ *next = find_pool(type, ptr1, 0);
+ if (!(*next))
+ log_error("ipv6_pool: %s: next pool not found\n", opt);
+ }
+}
+
+static void ippool_init1(void)
+{
+ ipdb_register(&ipdb);
+}
+
+static void ippool_init2(void)
{
struct conf_sect_t *s = conf_get_section("ipv6-pool");
struct conf_option_t *opt;
-
- spinlock_init(&pool_lock);
+ struct ippool_t *pool, *next;
+ char *pool_name, *val;
+ enum ippool_type type;
+#ifdef RADIUS
+ int dppool_attr = 0, ippool_attr = 0;
+#endif
if (!s)
return;
+ def_ippool = create_pool(IPPOOL_ADDRESS, NULL);
+ def_dppool = create_pool(IPPOOL_PREFIX, NULL);
+
list_for_each_entry(opt, &s->items, entry) {
+#ifdef RADIUS
+ if (triton_module_loaded("radius")) {
+ if (!strcmp(opt->name, "vendor")) {
+ conf_vendor = parse_vendor_opt(opt->val);
+ continue;
+ }
+ if (!strcmp(opt->name, "attr-prefix")) {
+ dppool_attr = parse_attr_opt(opt->val);
+ continue;
+ }
+ if (!strcmp(opt->name, "attr-address")) {
+ ippool_attr = parse_attr_opt(opt->val);
+ continue;
+ }
+ }
+#endif
if (!strcmp(opt->name, "gw-ip6-address")) {
if (inet_pton(AF_INET6, opt->val, &conf_gw_addr) == 0)
log_error("ipv6_pool: failed to parse gw-ip6-address\n");
- } else if (!strcmp(opt->name, "delegate"))
- add_prefix(1, opt->val);
- else
- add_prefix(0, opt->name);
+ continue;
+ } else if (!strcmp(opt->name, "delegate")) {
+ type = IPPOOL_PREFIX;
+ val = opt->val;
+ pool = def_dppool;
+ } else {
+ type = IPPOOL_ADDRESS;
+ val = opt->name;
+ pool = def_ippool;
+ }
+
+ pool_name = NULL;
+ parse_options(type, opt->raw, &pool_name, &next);
+
+ if (pool_name)
+ pool = find_pool(type, pool_name, 1);
+ add_prefix(type, pool, val);
+
+ pool->next = next;
}
- ipdb_register(&ipdb);
+#ifdef RADIUS
+ if (triton_module_loaded("radius")) {
+ if (conf_vendor || dppool_attr)
+ conf_dppool_attr = dppool_attr;
+ if (conf_vendor || ippool_attr)
+ conf_ippool_attr = ippool_attr;
+ triton_event_register_handler(EV_RADIUS_ACCESS_ACCEPT, (triton_event_func)ev_radius_access_accept);
+ }
+#endif
}
-DEFINE_INIT(51, ippool_init);
-
+DEFINE_INIT(51, ippool_init1);
+DEFINE_INIT2(52, ippool_init2);
diff --git a/accel-pppd/include/ap_session.h b/accel-pppd/include/ap_session.h
index b2d0532..6a6b950 100644
--- a/accel-pppd/include/ap_session.h
+++ b/accel-pppd/include/ap_session.h
@@ -84,6 +84,7 @@ struct ap_session
struct ipv6db_prefix_t *ipv6_dp;
char *ipv4_pool_name;
char *ipv6_pool_name;
+ char *dpv6_pool_name;
struct ap_net *net;
const struct ap_ctrl *ctrl;
diff --git a/accel-pppd/radius/attr_defs.h b/accel-pppd/radius/attr_defs.h
index eb3c5de..80ae426 100644
--- a/accel-pppd/radius/attr_defs.h
+++ b/accel-pppd/radius/attr_defs.h
@@ -292,3 +292,8 @@
#define Framed_IPv6_Route 99
#define Framed_IPv6_Pool 100
#define Delegated_IPv6_Prefix 123
+#define Framed_IPv6_Address 168
+#define DNS_Server_IPv6_Address 169
+#define Route_IPv6_Information 170
+#define Delegated_IPv6_Prefix_Pool 171
+#define Stateful_IPv6_Address_Pool 172
diff --git a/accel-pppd/radius/dict.c b/accel-pppd/radius/dict.c
index fa75dd9..cb1fb28 100644
--- a/accel-pppd/radius/dict.c
+++ b/accel-pppd/radius/dict.c
@@ -80,7 +80,7 @@ static int dict_load(const char *fname)
f = fopen(fname, "r");
if (!f) {
- log_emerg("radius: open dictioanary '%s': %s\n", fname, strerror(errno));
+ log_emerg("radius: open dictionary '%s': %s\n", fname, strerror(errno));
return -1;
}
diff --git a/accel-pppd/radius/dict/dictionary b/accel-pppd/radius/dict/dictionary
index de05680..6da511d 100644
--- a/accel-pppd/radius/dict/dictionary
+++ b/accel-pppd/radius/dict/dictionary
@@ -74,6 +74,7 @@ $INCLUDE dictionary.rfc4372
$INCLUDE dictionary.rfc4679
$INCLUDE dictionary.rfc4818
$INCLUDE dictionary.rfc5176
+$INCLUDE dictionary.rfc6911
$INCLUDE dictionary.microsoft
$INCLUDE dictionary.cisco
diff --git a/accel-pppd/radius/dict/dictionary.rfc6911 b/accel-pppd/radius/dict/dictionary.rfc6911
new file mode 100644
index 0000000..f8d5204
--- /dev/null
+++ b/accel-pppd/radius/dict/dictionary.rfc6911
@@ -0,0 +1,12 @@
+# -*- text -*-
+# Copyright (C) 2013 The FreeRADIUS Server project and contributors
+#
+# Attributes and values defined in RFC 6911
+# http://www.ietf.org/rfc/rfc6911.txt
+#
+
+ATTRIBUTE Framed-IPv6-Address 168 ipv6addr
+ATTRIBUTE DNS-Server-IPv6-Address 169 ipv6addr
+ATTRIBUTE Route-IPv6-Information 170 ipv6prefix
+ATTRIBUTE Delegated-IPv6-Prefix-Pool 171 string
+ATTRIBUTE Stateful-IPv6-Address-Pool 172 string
diff --git a/accel-pppd/session.c b/accel-pppd/session.c
index bf7d712..81247d1 100644
--- a/accel-pppd/session.c
+++ b/accel-pppd/session.c
@@ -239,6 +239,11 @@ void __export ap_session_finished(struct ap_session *ses)
ses->ipv6_pool_name = NULL;
}
+ if (ses->dpv6_pool_name) {
+ _free(ses->dpv6_pool_name);
+ ses->dpv6_pool_name = NULL;
+ }
+
if (ses->ifname_rename) {
_free(ses->ifname_rename);
ses->ifname_rename = NULL;
diff --git a/rfc/rfc6911.txt b/rfc/rfc6911.txt
new file mode 100644
index 0000000..32b0737
--- /dev/null
+++ b/rfc/rfc6911.txt
@@ -0,0 +1,843 @@
+
+
+
+
+
+
+Internet Engineering Task Force (IETF) W. Dec, Ed.
+Request for Comments: 6911 Cisco Systems, Inc.
+Category: Standards Track B. Sarikaya
+ISSN: 2070-1721 Huawei USA
+ G. Zorn, Ed.
+ Network Zen
+ D. Miles
+ Google
+ B. Lourdelet
+ Juniper Networks
+ April 2013
+
+
+ RADIUS Attributes for IPv6 Access Networks
+
+Abstract
+
+ This document specifies additional IPv6 RADIUS Attributes useful in
+ residential broadband network deployments. The Attributes, which are
+ used for authorization and accounting, enable assignment of a host
+ IPv6 address and an IPv6 DNS server address via DHCPv6, assignment of
+ an IPv6 route announced via router advertisement, assignment of a
+ named IPv6 delegated prefix pool, and assignment of a named IPv6 pool
+ for host DHCPv6 addressing.
+
+Status of This Memo
+
+ This is an Internet Standards Track document.
+
+ This document is a product of the Internet Engineering Task Force
+ (IETF). It represents the consensus of the IETF community. It has
+ received public review and has been approved for publication by the
+ Internet Engineering Steering Group (IESG). Further information on
+ Internet Standards is available in Section 2 of RFC 5741.
+
+ Information about the current status of this document, any errata,
+ and how to provide feedback on it may be obtained at
+ http://www.rfc-editor.org/info/rfc6911.
+
+
+
+
+
+
+
+
+
+
+
+
+
+Dec, et al. Standards Track [Page 1]
+
+RFC 6911 RADIUS IPv6 Access April 2013
+
+
+Copyright Notice
+
+ Copyright (c) 2013 IETF Trust and the persons identified as the
+ document authors. All rights reserved.
+
+ This document is subject to BCP 78 and the IETF Trust's Legal
+ Provisions Relating to IETF Documents
+ (http://trustee.ietf.org/license-info) in effect on the date of
+ publication of this document. Please review these documents
+ carefully, as they describe your rights and restrictions with respect
+ to this document. Code Components extracted from this document must
+ include Simplified BSD License text as described in Section 4.e of
+ the Trust Legal Provisions and are provided without warranty as
+ described in the Simplified BSD License.
+
+Table of Contents
+
+ 1. Introduction . . . . . . . . . . . . . . . . . . . . . . . . 3
+ 1.1. Requirements Language . . . . . . . . . . . . . . . . . . 3
+ 2. Deployment Scenarios . . . . . . . . . . . . . . . . . . . . 3
+ 2.1. IPv6 Address Assignment . . . . . . . . . . . . . . . . . 4
+ 2.2. DNS Servers . . . . . . . . . . . . . . . . . . . . . . . 5
+ 2.3. IPv6 Route Information . . . . . . . . . . . . . . . . . 5
+ 2.4. Delegated IPv6 Prefix Pool . . . . . . . . . . . . . . . 6
+ 2.5. Stateful IPv6 Address Pool . . . . . . . . . . . . . . . 6
+ 3. Attributes . . . . . . . . . . . . . . . . . . . . . . . . . 6
+ 3.1. Framed-IPv6-Address . . . . . . . . . . . . . . . . . . . 6
+ 3.2. DNS-Server-IPv6-Address . . . . . . . . . . . . . . . . . 8
+ 3.3. Route-IPv6-Information . . . . . . . . . . . . . . . . . 9
+ 3.4. Delegated-IPv6-Prefix-Pool . . . . . . . . . . . . . . . 10
+ 3.5. Stateful-IPv6-Address-Pool . . . . . . . . . . . . . . . 11
+ 3.6. Table of Attributes . . . . . . . . . . . . . . . . . . . 11
+ 4. Diameter Considerations . . . . . . . . . . . . . . . . . . . 12
+ 5. Security Considerations . . . . . . . . . . . . . . . . . . . 12
+ 6. IANA Considerations . . . . . . . . . . . . . . . . . . . . . 12
+ 7. Acknowledgments . . . . . . . . . . . . . . . . . . . . . . . 13
+ 8. References . . . . . . . . . . . . . . . . . . . . . . . . . 13
+ 8.1. Normative References . . . . . . . . . . . . . . . . . . 13
+ 8.2. Informative References . . . . . . . . . . . . . . . . . 13
+
+
+
+
+
+
+
+
+
+
+
+
+Dec, et al. Standards Track [Page 2]
+
+RFC 6911 RADIUS IPv6 Access April 2013
+
+
+1. Introduction
+
+ This document specifies additional RADIUS Attributes used to support
+ configuration of DHCPv6 and/or ICMPv6 Router Advertisement (RA)
+ parameters on a per-user basis. The Attributes, which complement
+ those defined in [RFC3162] and [RFC4818], support the following:
+
+ o The assignment of specific IPv6 addresses to hosts via DHCPv6.
+
+ o The assignment of an IPv6 DNS server address, via DHCPv6 or Router
+ Advertisement [RFC6106].
+
+ o The configuration of more specific routes to be announced to the
+ user via the Route Information Option defined in [RFC4191],
+ Section 2.3.
+
+ o The assignment of a named delegated prefix pool for use with "IPv6
+ Prefix Options for Dynamic Host Configuration Protocol (DHCP)
+ version 6" [RFC3633].
+
+ o The assignment of a named stateful address pool for use with
+ DHCPv6 stateful address assignment [RFC3315].
+
+1.1. Requirements Language
+
+ The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT",
+ "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this
+ document are to be interpreted as described in RFC 2119 [RFC2119].
+
+2. Deployment Scenarios
+
+ The extensions in this document are intended to be applicable across
+ a wide variety of network access scenarios in which RADIUS is
+ involved. One such typical network scenario is illustrated in Figure
+ 1. It is composed of an IP Routing Residential Gateway (RG) or host;
+ a Layer 2 Access Node (AN), e.g., a Digital Subscriber Line Access
+ Multiplexer (DSLAM); an IP Network Access Server (NAS) (incorporating
+ an Authentication, Authorization, and Accounting (AAA) client); and a
+ AAA server.
+
+
+
+
+
+
+
+
+
+
+
+
+Dec, et al. Standards Track [Page 3]
+
+RFC 6911 RADIUS IPv6 Access April 2013
+
+
+ +-----+
+ | AAA |
+ | |
+ +--+--+
+ ^
+ .
+ .(RADIUS)
+ .
+ v
+ +------+ +---+---+
+ +------+ | | | |
+ | RG/ +-------| AN +-----------+----------+ NAS |
+ | host | | | | |
+ +------+ (DSL) +------+ (Ethernet) +-------+
+
+ Figure 1
+
+ In the depicted scenario, the NAS may utilize an IP address
+ configuration protocol (e.g., DHCPv6) to handle address assignment to
+ RGs/hosts. The RADIUS server authenticates each RG/host and returns
+ the Attributes used for authorization and accounting. These
+ Attributes can include a host's IPv6 address, a DNS server address,
+ and a set of IPv6 routes to be advertised via any suitable protocol,
+ e.g., ICMPv6 (Neighbor Discovery). The name of a prefix pool to be
+ used for DHCPv6 Prefix Delegation or the name of an address pool to
+ be used for DHCPv6 address assignment can also be Attributes provided
+ to the NAS by the RADIUS AAA server.
+
+ The following subsections discuss how these Attributes are used in
+ more detail.
+
+2.1. IPv6 Address Assignment
+
+ DHCPv6 [RFC3315] provides a mechanism to assign one or more non-
+ temporary IPv6 addresses to hosts. To provide a DHCPv6 server
+ residing on a NAS with one or more IPv6 addresses to be assigned,
+ this document specifies the Framed-IPv6-Address Attribute
+ (Section 3.1).
+
+ While [RFC3162] permits the specification of an IPv6 address via the
+ combination of the Framed-Interface-Id and Framed-IPv6-Prefix
+ Attributes, this separation is more natural for use with PPP's IPv6
+ Control Protocol than it is for use with DHCPv6, and the use of a
+ single IPv6 address Attribute makes for easier processing of
+ accounting records.
+
+
+
+
+
+
+Dec, et al. Standards Track [Page 4]
+
+RFC 6911 RADIUS IPv6 Access April 2013
+
+
+ Because DHCPv6 can be deployed on the same network as ICMPv6
+ stateless address autoconfiguration (SLAAC) [RFC4862], it is possible
+ that the NAS will require both stateful and stateless configuration
+ information. Therefore, it is possible for the Framed-IPv6-Address,
+ Framed-IPv6-Prefix, and Framed-Interface-Id Attributes [RFC3162] to
+ be included within the same packet. To avoid ambiguity in this case,
+ the Framed-IPv6-Address Attribute is intended for authorization and
+ accounting of DHCPv6-assigned addresses, and the Framed-IPv6-Prefix
+ and Framed-Interface-Id Attributes are used for authorization and
+ accounting of addresses assigned via SLAAC.
+
+2.2. DNS Servers
+
+ DHCPv6 provides an option for configuring a host with the IPv6
+ address of a DNS server. The IPv6 address of a DNS server can also
+ be conveyed to the host using ICMPv6 with Router Advertisements, via
+ the Recursive DNS Server Option [RFC6106]. To provide the NAS with
+ the IPv6 address of one or more DNS servers, this document specifies
+ the DNS-Server-IPv6-Address Attribute (Section 3.2).
+
+2.3. IPv6 Route Information
+
+ The IPv6 Route Information Option [RFC4191], is intended to be used
+ to inform a host connected to the NAS that a specific route is
+ reachable via any given NAS.
+
+ This document specifies the Route-IPv6-Information Attribute
+ (Section 3.3) that allows the AAA server to provision the
+ announcement by the NAS of a specific Route Information Option to an
+ accessing host. The NAS may advertise this route using the method
+ defined in RFC 4191 or other equivalent methods. Any other
+ information, such as preference or lifetime values, that is to be
+ present in the actual announcement using a given method is assumed to
+ be determined by the NAS using means not specified by this document
+ (e.g., local configuration on the NAS).
+
+ While the Framed-IPv6-Prefix Attribute ([RFC3162], Section 2.3)
+ allows the route to be advertised in an RA, it cannot be used to
+ configure more specific routes. While the Framed-IPv6-Route
+ Attribute ([RFC3162], Section 2.5) causes the route to be configured
+ on the NAS and potentially to be announced via an IP routing
+ protocol, depending on the value of Framed-Routing, it does not
+ result in the route being announced in an RA.
+
+
+
+
+
+
+
+
+Dec, et al. Standards Track [Page 5]
+
+RFC 6911 RADIUS IPv6 Access April 2013
+
+
+2.4. Delegated IPv6 Prefix Pool
+
+ DHCPv6 Prefix Delegation (DHCPv6-PD) [RFC3633] involves a delegating
+ router selecting a prefix and delegating it on a temporary basis to a
+ requesting router. The delegating router may implement a number of
+ strategies as to how it chooses what prefix is to be delegated to a
+ requesting router, one of them being the use of a local named prefix
+ pool. The Delegated-IPv6-Prefix-Pool Attribute (Section 3.4) allows
+ the RADIUS server to convey a prefix pool name to a NAS that is
+ hosting a DHCPv6-PD server and that is acting as a delegating router.
+
+ Because DHCPv6 Prefix Delegation can be used with SLAAC on the same
+ network, it is possible for the Delegated-IPv6-Prefix-Pool and
+ Framed-IPv6-Pool Attributes to be included within the same packet.
+ To avoid ambiguity in this scenario, use of the Delegated-IPv6-
+ Prefix-Pool Attribute should be restricted to authorization and
+ accounting of prefix pools used in DHCPv6 Prefix Delegation, and the
+ Framed-IPv6-Pool Attribute should be used for authorization and
+ accounting of prefix pools used in SLAAC.
+
+2.5. Stateful IPv6 Address Pool
+
+ DHCPv6 [RFC3315] provides a mechanism to assign one or more non-
+ temporary IPv6 addresses to hosts. Section 3.1 introduces the
+ Framed-IPv6-Address Attribute to be used to provide a DHCPv6 server
+ residing on a NAS with one or more IPv6 addresses to be assigned to
+ the clients. An alternative way to achieve a similar result is for
+ the NAS to select the IPv6 address to be assigned from an address
+ pool configured for this purpose on the NAS. This document specifies
+ the Stateful-IPv6-Address-Pool Attribute (Section 3.5) to allow the
+ RADIUS server to convey a pool name to be used for such stateful
+ DHCPv6-based addressing and for any subsequent accounting.
+
+3. Attributes
+
+ The fields shown in the diagrams below are transmitted from left to
+ right.
+
+3.1. Framed-IPv6-Address
+
+ The Framed-IPv6-Address Attribute indicates an IPv6 address that is
+ assigned to the NAS-facing interface of the RG/host. It MAY be used
+ in Access-Accept packets and MAY appear multiple times. It MAY be
+ used in an Access-Request packet as a hint by the NAS to the RADIUS
+ server that it would prefer this IPv6 address, but the RADIUS server
+ is not required to honor the hint. Because it is assumed that the
+
+
+
+
+
+Dec, et al. Standards Track [Page 6]
+
+RFC 6911 RADIUS IPv6 Access April 2013
+
+
+ NAS will add a route corresponding to the address, it is not
+ necessary for the RADIUS server to also send a host Framed-IPv6-Route
+ Attribute for the same address.
+
+ This Attribute can be used by a DHCPv6 process on the NAS to assign a
+ unique IPv6 address to the RG/host.
+
+ A summary of the Framed-IPv6-Address Attribute format is shown below.
+ The format of the Address field is identical to that of the
+ corresponding field in the NAS-IPv6-Address Attribute [RFC3162].
+
+ 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
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | Type | Length | Address
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ Address (cont)
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ Address (cont)
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ Address (cont)
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ Address (cont) |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+
+ Type
+
+ 168 for Framed-IPv6-Address
+
+ Length
+
+ 18
+
+ Address
+
+ A 128-bit IPv6 address.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Dec, et al. Standards Track [Page 7]
+
+RFC 6911 RADIUS IPv6 Access April 2013
+
+
+3.2. DNS-Server-IPv6-Address
+
+ The DNS-Server-IPv6-Address Attribute contains the IPv6 address of a
+ DNS server. This Attribute MAY be included multiple times in Access-
+ Accept packets when the intention is for a NAS to announce more than
+ one DNS server address to an RG/host. The Attribute MAY be used in
+ an Access-Request packet as a hint by the NAS to the RADIUS server
+ regarding the DNS IPv6 address, but the RADIUS server is not required
+ to honor the hint.
+
+ The content of this Attribute can be copied to an instance of the
+ DHCPv6 DNS Recursive Name Server Option [RFC3646] or to an IPv6
+ Router Advertisement Recursive DNS Server Option [RFC6106]. If more
+ than one DNS-Server-IPv6-Address Attribute is present in the Access-
+ Accept packet, the addresses from the Attributes SHOULD be copied in
+ the same order as received.
+
+ A summary of the DNS-Server-IPv6-Address Attribute format is given
+ below. The format of the Address field is the same as that of the
+ corresponding field in the NAS-IPv6-Address Attribute [RFC3162].
+
+ 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
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | Type | Length | Address
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ Address (cont)
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ Address (cont)
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ Address (cont)
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ Address (cont) |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+
+ Type
+
+ 169 for DNS-Server-IPv6-Address
+
+ Length
+
+ 18
+
+ Address
+
+ The 128-bit IPv6 address of a DNS server.
+
+
+
+
+
+Dec, et al. Standards Track [Page 8]
+
+RFC 6911 RADIUS IPv6 Access April 2013
+
+
+3.3. Route-IPv6-Information
+
+ The Route-IPv6-Information Attribute specifies a prefix (and
+ corresponding route) for the user on the NAS, which is to be
+ announced using the Route Information Option defined in "Default
+ Router Preferences and More Specific Routes" [RFC4191], Section 2.3.
+ It is used in the Access-Accept packet and can appear multiple times.
+ It MAY be used in an Access-Request packet as a hint by the NAS to
+ the RADIUS server, but the RADIUS server is not required to honor the
+ hint. The Route-IPv6-Information Attribute format is depicted below.
+ The format of the prefix is as per [RFC3162].
+
+ 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
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | Type | Length | Reserved | Prefix-Length |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | |
+ . Prefix (variable) .
+ . .
+ | |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+
+ Type
+
+ 170 for Route-IPv6-Information
+
+ Length
+
+ Length, in bytes. At least 4 and no larger than 20; typically, 12
+ or less.
+
+ Prefix Length
+
+ 8-bit unsigned integer. The number of leading bits in the prefix
+ that are valid. The value can range from 0 to 128. The prefix
+ field is 0, 8, or 16 octets depending on Length.
+
+ Prefix
+
+ Variable-length field containing an IP prefix. The prefix length
+ field contains the number of valid leading bits in the prefix.
+ The bits in the prefix after the prefix length, if any, are
+ reserved and MUST be initialized to zero.
+
+
+
+
+
+
+
+Dec, et al. Standards Track [Page 9]
+
+RFC 6911 RADIUS IPv6 Access April 2013
+
+
+3.4. Delegated-IPv6-Prefix-Pool
+
+ The Delegated-IPv6-Prefix-Pool Attribute contains the name of an
+ assigned pool that SHOULD be used to select an IPv6 delegated prefix
+ for the user on the NAS. If a NAS does not support prefix pools, the
+ NAS MUST ignore this Attribute. It MAY be used in an Access-Request
+ packet as a hint by the NAS to the RADIUS server regarding the pool,
+ but the RADIUS server is not required to honor the hint.
+
+ A summary of the Delegated-IPv6-Prefix-Pool Attribute format is shown
+ below.
+
+ 0 1 2
+ 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | Type | Length | String...
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+
+ Type
+
+ 171 for Delegated-IPv6-Prefix-Pool
+
+ Length
+
+ Length, in bytes. At least 3.
+
+ String
+
+ The string field contains the name of an assigned IPv6 prefix pool
+ configured on the NAS. The field is not NULL (hexadecimal 00)
+ terminated.
+
+ Note: The string data type is as documented in [RFC6158] and carries
+ binary data that is external to the RADIUS protocol, e.g., the name
+ of a pool of prefixes configured on the NAS.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Dec, et al. Standards Track [Page 10]
+
+RFC 6911 RADIUS IPv6 Access April 2013
+
+
+3.5. Stateful-IPv6-Address-Pool
+
+ The Stateful-IPv6-Address-Pool Attribute contains the name of an
+ assigned pool that SHOULD be used to select an IPv6 address for the
+ user on the NAS. If a NAS does not support address pools, the NAS
+ MUST ignore this Attribute. A summary of the Stateful-IPv6-Address-
+ Pool Attribute format is shown below. It MAY be used in an Access-
+ Request packet as a hint by the NAS to the RADIUS server regarding
+ the pool, but the RADIUS server is not required to honor the hint.
+
+ 0 1 2
+ 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | Type | Length | String...
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+
+ Type
+
+ 172 for Stateful-IPv6-Address-Pool
+
+ Length
+
+ Length, in bytes. At least 3.
+
+ String
+
+ The string field contains the name of an assigned IPv6 stateful
+ address pool configured on the NAS. The field is not NULL
+ (hexadecimal 00) terminated.
+
+ Note: The string data type is as documented in [RFC6158] and carries
+ binary data that is external to the RADIUS protocol, e.g., the name
+ of a pool of addresses configured on the NAS.
+
+3.6. Table of Attributes
+
+ The following table provides a guide to which Attributes may be found
+ in which kinds of packets, and in what quantity. The optional
+ inclusion of the options in Access Request messages is intended to
+ allow for a NAS to provide the RADIUS server with a hint of the
+ Attributes in advance of user authentication, which may be useful in
+ cases in which a user reconnects or has a static address. The server
+ is under no obligation to honor such hints.
+
+
+
+
+
+
+
+
+Dec, et al. Standards Track [Page 11]
+
+RFC 6911 RADIUS IPv6 Access April 2013
+
+
+ Request Accept Reject Challenge Accounting # Attribute
+ Request
+ 0+ 0+ 0 0 0+ 168 Framed-IPv6-Address
+ 0+ 0+ 0 0 0+ 169 DNS-Server-IPv6-Address
+ 0+ 0+ 0 0 0+ 170 Route-IPv6-Information
+ 0+ 0+ 0 0 0+ 171 Delegated-IPv6-Prefix-Pool
+ 0+ 0+ 0 0 0+ 172 Stateful-IPv6-Address-Pool
+
+4. Diameter Considerations
+
+ Given that the Attributes defined in this document are allocated from
+ the standard RADIUS type space (see Section 6), no special handling
+ is required by Diameter entities.
+
+5. Security Considerations
+
+ This document specifies additional IPv6 RADIUS Attributes useful in
+ residential broadband network deployments. In such networks, the
+ RADIUS protocol may run either over IPv4 or over IPv6, and known
+ security vulnerabilities of the RADIUS protocol, e.g., [SECI], apply
+ to the Attributes defined in this document. A trust relationship
+ between a NAS and RADIUS server is expected to be in place, with
+ communication optionally secured by IPsec or Transport Layer Security
+ (TLS) [RFC6614].
+
+6. IANA Considerations
+
+ IANA has assigned five new RADIUS Attribute types in the "Radius
+ Attribute Types" registry (currently located at
+ http://www.iana.org/assignments/radius-types) for the following
+ Attributes:
+
+ o Framed-IPv6-Address
+
+ o DNS-Server-IPv6-Address
+
+ o Route-IPv6-Information
+
+ o Delegated-IPv6-Prefix-Pool
+
+ o Stateful-IPv6-Address-Pool
+
+
+
+
+
+
+
+
+
+
+Dec, et al. Standards Track [Page 12]
+
+RFC 6911 RADIUS IPv6 Access April 2013
+
+
+7. Acknowledgments
+
+ The authors would like to thank Bernard Aboba, Benoit Claise, Peter
+ Deacon, Alan DeKok, Ralph Droms, Brian Haberman, Alfred Hines,
+ Stephen Farrell, Jouni Korhonen, Roberta Maglione, Pete Resnick, Mark
+ Smith, and Leaf Yeh for their help and comments in reviewing this
+ document.
+
+8. References
+
+8.1. Normative References
+
+ [RFC2119] Bradner, S., "Key words for use in RFCs to Indicate
+ Requirement Levels", BCP 14, RFC 2119, March 1997.
+
+ [RFC4862] Thomson, S., Narten, T., and T. Jinmei, "IPv6 Stateless
+ Address Autoconfiguration", RFC 4862, September 2007.
+
+8.2. Informative References
+
+ [RFC3162] Aboba, B., Zorn, G., and D. Mitton, "RADIUS and IPv6", RFC
+ 3162, August 2001.
+
+ [RFC3315] Droms, R., Bound, J., Volz, B., Lemon, T., Perkins, C.,
+ and M. Carney, "Dynamic Host Configuration Protocol for
+ IPv6 (DHCPv6)", RFC 3315, July 2003.
+
+ [RFC3633] Troan, O. and R. Droms, "IPv6 Prefix Options for Dynamic
+ Host Configuration Protocol (DHCP) version 6", RFC 3633,
+ December 2003.
+
+ [RFC3646] Droms, R., "DNS Configuration options for Dynamic Host
+ Configuration Protocol for IPv6 (DHCPv6)", RFC 3646,
+ December 2003.
+
+ [RFC4191] Draves, R. and D. Thaler, "Default Router Preferences and
+ More-Specific Routes", RFC 4191, November 2005.
+
+ [RFC4818] Salowey, J. and R. Droms, "RADIUS Delegated-IPv6-Prefix
+ Attribute", RFC 4818, April 2007.
+
+ [RFC6106] Jeong, J., Park, S., Beloeil, L., and S. Madanapalli,
+ "IPv6 Router Advertisement Options for DNS Configuration",
+ RFC 6106, November 2010.
+
+ [RFC6158] DeKok, A. and G. Weber, "RADIUS Design Guidelines", BCP
+ 158, RFC 6158, March 2011.
+
+
+
+
+Dec, et al. Standards Track [Page 13]
+
+RFC 6911 RADIUS IPv6 Access April 2013
+
+
+ [RFC6614] Winter, S., McCauley, M., Venaas, S., and K. Wierenga,
+ "Transport Layer Security (TLS) Encryption for RADIUS",
+ RFC 6614, May 2012.
+
+ [SECI] Hill, J., "An Analysis of the RADIUS Authentication
+ Protocol", November 2001, <http://regul.uni-mb.si/~meolic/
+ ptk-seminarske/radius.pdf>.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Dec, et al. Standards Track [Page 14]
+
+RFC 6911 RADIUS IPv6 Access April 2013
+
+
+Authors' Addresses
+
+ Wojciech Dec (editor)
+ Cisco Systems, Inc.
+ Haarlerbergweg 13-19
+ Amsterdam, Noord-Holland 1101 CH
+ Netherlands
+
+ EMail: wdec@cisco.com
+
+
+ Behcet Sarikaya
+ Huawei USA
+ 1700 Alma Drive, Suite 500
+ Plano, TX
+ US
+
+ Phone: +1 972-509-5599
+ EMail: sarikaya@ieee.org
+
+
+ Glen Zorn (editor)
+ Network Zen
+ 227/358 Thanon Sanphawut
+ Bang Na, Bangkok 10260
+ Thailand
+
+ Phone: +66 (0) 8-1000-4155
+ EMail: glenzorn@gmail.com
+
+
+ David Miles
+ Google
+
+ EMail: davidmiles@google.com
+
+
+ Benoit Lourdelet
+ Juniper Networks
+ France
+
+ EMail: blourdel@juniper.net
+
+
+
+
+
+
+
+
+
+Dec, et al. Standards Track [Page 15]
+