diff options
Diffstat (limited to 'accel-pppd')
-rw-r--r-- | accel-pppd/accel-ppp.conf | 15 | ||||
-rw-r--r-- | accel-pppd/accel-ppp.conf.5 | 25 | ||||
-rw-r--r-- | accel-pppd/ctrl/ipoe/ipoe.c | 16 | ||||
-rw-r--r-- | accel-pppd/ctrl/l2tp/l2tp.c | 25 | ||||
-rw-r--r-- | accel-pppd/ctrl/pppoe/pppoe.c | 8 | ||||
-rw-r--r-- | accel-pppd/ctrl/pptp/pptp.c | 8 | ||||
-rw-r--r-- | accel-pppd/ctrl/sstp/sstp.c | 8 | ||||
-rw-r--r-- | accel-pppd/extra/chap-secrets.c | 8 | ||||
-rw-r--r-- | accel-pppd/extra/ipv6pool.c | 304 | ||||
-rw-r--r-- | accel-pppd/include/ap_session.h | 1 | ||||
-rw-r--r-- | accel-pppd/radius/attr_defs.h | 5 | ||||
-rw-r--r-- | accel-pppd/radius/dict.c | 2 | ||||
-rw-r--r-- | accel-pppd/radius/dict/dictionary | 1 | ||||
-rw-r--r-- | accel-pppd/radius/dict/dictionary.rfc6911 | 12 | ||||
-rw-r--r-- | accel-pppd/session.c | 5 |
15 files changed, 395 insertions, 48 deletions
diff --git a/accel-pppd/accel-ppp.conf b/accel-pppd/accel-ppp.conf index a4ece60d..144bf1f4 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 982bbd10..3e6312f8 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 45f66b73..b1504a2f 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 6c108487..0d1ca21a 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 a1f54e71..32dee77a 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 081e9216..1161da5a 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 62e574c7..5bf8fd82 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 92cfb42f..0fadc9cb 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 4f29a280..a2cf30df 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 b2d05327..6a6b9504 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 eb3c5de8..80ae426b 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 fa75dd9c..cb1fb28b 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 de056801..6da511d2 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 00000000..f8d52049 --- /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 bf7d712a..81247d18 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; |