diff options
author | Guillaume Nault <g.nault@alphalink.fr> | 2013-07-23 20:35:25 +0200 |
---|---|---|
committer | Dmitry Kozlov <xeb@mail.ru> | 2013-07-24 22:32:08 +0400 |
commit | 31e20f0ce4605b7d7ec416bf88a4e98c90aa6b93 (patch) | |
tree | c5f87f55fcd80f2ed2a92f99ff09fdbd79f64493 | |
parent | 4e6cf832cddf523c233ff0f0f3b244e077d87df3 (diff) | |
download | accel-ppp-31e20f0ce4605b7d7ec416bf88a4e98c90aa6b93.tar.gz accel-ppp-31e20f0ce4605b7d7ec416bf88a4e98c90aa6b93.zip |
ppp: Use link local IPv6 prefix by default during IPv6CP
When no ipdb backend can assign IPv6 addresses during IPv6CP
negociation, generate an ipv6db item with an empty address list.
This allows IPv6CP negociation to continue and assign a link-local
IPv6 address, without the need for an IPv6 pool or special Radius
configuration.
Signed-off-by: Guillaume Nault <g.nault@alphalink.fr>
-rw-r--r-- | accel-pppd/ppp/ipv6cp_opt_intfid.c | 42 |
1 files changed, 40 insertions, 2 deletions
diff --git a/accel-pppd/ppp/ipv6cp_opt_intfid.c b/accel-pppd/ppp/ipv6cp_opt_intfid.c index a46ae17c..11b35ff7 100644 --- a/accel-pppd/ppp/ipv6cp_opt_intfid.c +++ b/accel-pppd/ppp/ipv6cp_opt_intfid.c @@ -37,6 +37,7 @@ static int ipaddr_send_conf_nak(struct ppp_ipv6cp_t *ipv6cp, struct ipv6cp_optio static int ipaddr_recv_conf_req(struct ppp_ipv6cp_t *ipv6cp, struct ipv6cp_option_t *opt, uint8_t *ptr); //static int ipaddr_recv_conf_ack(struct ppp_ipv6cp_t *ipv6cp, struct ipv6cp_option_t *opt, uint8_t *ptr); static void ipaddr_print(void (*print)(const char *fmt,...),struct ipv6cp_option_t*, uint8_t *ptr); +static void put_ipv6_item(struct ap_session *ses, struct ipv6db_item_t *ip6); struct ipaddr_option_t { @@ -55,6 +56,41 @@ static struct ipv6cp_option_handler_t ipaddr_opt_hnd = .print = ipaddr_print, }; +/* ipdb backend used for generating a link-local address when all other + * backends (like radius and ipv6pool) failed to assign IPv6 addresses. + * This backend isn't registered to ipdb as it's only used as a fallback + * during IPv6CP negociation. + */ +static struct ipdb_t ipv6db = { + .put_ipv6 = put_ipv6_item +}; + +static void put_ipv6_item(struct ap_session *ses, struct ipv6db_item_t *ip6) +{ + _free(ip6); +} + +static int gen_ipv6_item(struct ap_session *ses) +{ + struct ipv6db_item_t *ip6 = NULL; + + ip6 = _malloc(sizeof(*ip6)); + if (ip6 == NULL) { + log_ppp_warn("ppp: allocation of IPv6 address failed\n"); + return -1; + } + + memset(ip6, 0, sizeof(*ip6)); + ip6->owner = &ipv6db; + ip6->intf_id = 0; + ip6->peer_intf_id = 0; + INIT_LIST_HEAD(&ip6->addr_list); + + ses->ipv6 = ip6; + + return 0; +} + static struct ipv6cp_option_t *ipaddr_init(struct ppp_ipv6cp_t *ipv6cp) { struct ipaddr_option_t *ipaddr_opt = _malloc(sizeof(*ipaddr_opt)); @@ -165,8 +201,10 @@ static int alloc_ip(struct ppp_t *ppp) { ppp->ses.ipv6 = ipdb_get_ipv6(&ppp->ses); if (!ppp->ses.ipv6) { - log_ppp_warn("ppp: no free IPv6 address\n"); - return IPV6CP_OPT_CLOSE; + if (gen_ipv6_item(&ppp->ses) < 0) { + log_ppp_warn("ppp: no free IPv6 address\n"); + return IPV6CP_OPT_CLOSE; + } } if (!ppp->ses.ipv6->intf_id) |