diff options
author | Kozlov Dmitry <xeb@mail.ru> | 2011-08-29 00:17:53 +0400 |
---|---|---|
committer | Kozlov Dmitry <xeb@mail.ru> | 2011-08-29 00:17:53 +0400 |
commit | f53638854c99e4b6b4b1c167c44fbb6dbfd0c6e7 (patch) | |
tree | cee88728fb81d74c1aec712cba785ee383829652 | |
parent | 059b8b24df39591b96ef10dba735e9c2ad7e118c (diff) | |
download | accel-ppp-f53638854c99e4b6b4b1c167c44fbb6dbfd0c6e7.tar.gz accel-ppp-f53638854c99e4b6b4b1c167c44fbb6dbfd0c6e7.zip |
ipv6_dhcp: add routes to delegated prefixes
-rw-r--r-- | accel-pppd/ipv6/dhcpv6.c | 47 | ||||
-rw-r--r-- | accel-pppd/ppp/ipv6cp_opt_intfid.c | 6 | ||||
-rw-r--r-- | accel-pppd/ppp/ppp.c | 5 | ||||
-rw-r--r-- | accel-pppd/ppp/ppp.h | 1 | ||||
-rw-r--r-- | accel-pppd/ppp/ppp_ipv6cp.c | 3 |
5 files changed, 56 insertions, 6 deletions
diff --git a/accel-pppd/ipv6/dhcpv6.c b/accel-pppd/ipv6/dhcpv6.c index 0bb72bc7..16d96751 100644 --- a/accel-pppd/ipv6/dhcpv6.c +++ b/accel-pppd/ipv6/dhcpv6.c @@ -10,6 +10,9 @@ #include <arpa/inet.h> #include <netinet/in.h> #include <sys/socket.h> +#include <sys/ioctl.h> +#include <linux/route.h> +#include <linux/ipv6_route.h> #include "triton.h" #include "mempool.h" @@ -41,6 +44,7 @@ struct dhcpv6_pd uint32_t addr_iaid; uint32_t dp_iaid; struct ipv6db_prefix_t *ipv6_dp; + int dp_active:1; }; static struct triton_md_handler_t dhcpv6_hnd; @@ -150,6 +154,44 @@ static void build_addr(struct ipv6db_addr_t *a, uint64_t intf_id, struct in6_add *(uint64_t *)(addr->s6_addr + 8) |= intf_id & ((1 << (128 - a->prefix_len)) - 1); } +static void insert_dp_routes(struct ppp_t *ppp, struct dhcpv6_pd *pd) +{ + struct ipv6db_addr_t *a; + struct ipv6db_addr_t *p; + struct in6_rtmsg rt6; + char str1[INET6_ADDRSTRLEN]; + char str2[INET6_ADDRSTRLEN]; + int err; + + memset(&rt6, 0, sizeof(rt6)); + rt6.rtmsg_ifindex = ppp->ifindex; + rt6.rtmsg_flags = RTF_UP | RTF_GATEWAY; + + list_for_each_entry(p, &pd->ipv6_dp->prefix_list, entry) { + memcpy(&rt6.rtmsg_dst, &p->addr, sizeof(p->addr)); + rt6.rtmsg_dst_len = p->prefix_len; + rt6.rtmsg_metric = 0; + //rt6.rtmsg_flags = RTF_UP; + list_for_each_entry(a, &ppp->ipv6->addr_list, entry) { + build_addr(a, ppp->ipv6->peer_intf_id, &rt6.rtmsg_gateway); + rt6.rtmsg_metric++; + if (ioctl(sock6_fd, SIOCADDRT, &rt6)) { + err = errno; + inet_ntop(AF_INET6, &p->addr, str1, sizeof(str1)); + inet_ntop(AF_INET6, &rt6.rtmsg_gateway, str2, sizeof(str2)); + log_ppp_error("dhcpv6: add route %s/%i via %s: %s\n", str1, p->prefix_len, str2, strerror(err)); + } else { + inet_ntop(AF_INET6, &p->addr, str1, sizeof(str1)); + inet_ntop(AF_INET6, &rt6.rtmsg_gateway, str2, sizeof(str2)); + log_ppp_info2("dhcpv6: add route %s/%i via %s\n", str1, p->prefix_len, str2); + + } + } + } + + pd->dp_active = 1; +} + static void insert_status(struct dhcpv6_packet *pkt, struct dhcpv6_option *opt, int code) { struct dhcpv6_option *opt1; @@ -259,8 +301,11 @@ static void dhcpv6_send_reply(struct dhcpv6_packet *req, struct dhcpv6_pd *pd, i insert_status(reply, opt1, D6_STATUS_NoPrefixAvail); } else { - if (req->hdr->type == D6_REQUEST) + if (req->hdr->type == D6_REQUEST) { pd->dp_iaid = ia_na->iaid; + if (!pd->dp_active) + insert_dp_routes(req->ppp, pd); + } f2 = 1; diff --git a/accel-pppd/ppp/ipv6cp_opt_intfid.c b/accel-pppd/ppp/ipv6cp_opt_intfid.c index cc7ce364..389880a6 100644 --- a/accel-pppd/ppp/ipv6cp_opt_intfid.c +++ b/accel-pppd/ppp/ipv6cp_opt_intfid.c @@ -37,7 +37,6 @@ struct in6_ifreq { }; static int urandom_fd; -static int sock6_fd; static struct ipv6cp_option_t *ipaddr_init(struct ppp_ipv6cp_t *ipv6cp); static void ipaddr_free(struct ppp_ipv6cp_t *ipv6cp, struct ipv6cp_option_t *opt); @@ -372,11 +371,8 @@ static void load_config(void) static void init() { - sock6_fd = socket(AF_INET6, SOCK_DGRAM, 0); - if (!sock6_fd) { - log_warn("ppp:ipv6cp: kernel doesn't support ipv6\n"); + if (sock6_fd < 0) return; - } urandom_fd = open("/dev/urandom", O_RDONLY); diff --git a/accel-pppd/ppp/ppp.c b/accel-pppd/ppp/ppp.c index a0f65f1d..e6d97887 100644 --- a/accel-pppd/ppp/ppp.c +++ b/accel-pppd/ppp/ppp.c @@ -32,6 +32,7 @@ pthread_rwlock_t __export ppp_lock = PTHREAD_RWLOCK_INITIALIZER; __export LIST_HEAD(ppp_list); int __export sock_fd; +int __export sock6_fd; int __export ppp_shutdown; @@ -744,6 +745,10 @@ static void init(void) _exit(EXIT_FAILURE); } + sock6_fd = socket(AF_INET6, SOCK_DGRAM, 0); + if (sock6_fd < 0) + log_warn("ppp: kernel doesn't support ipv6\n"); + opt = conf_get_opt("ppp", "seq-file"); if (!opt) opt = "/var/run/accel-ppp/seq"; diff --git a/accel-pppd/ppp/ppp.h b/accel-pppd/ppp/ppp.h index 4d3fccd6..5246a3e0 100644 --- a/accel-pppd/ppp/ppp.h +++ b/accel-pppd/ppp/ppp.h @@ -200,4 +200,5 @@ extern struct list_head ppp_list; extern struct ppp_stat_t ppp_stat; extern int sock_fd; // internet socket for ioctls +extern int sock6_fd; // internet socket for ioctls #endif diff --git a/accel-pppd/ppp/ppp_ipv6cp.c b/accel-pppd/ppp/ppp_ipv6cp.c index 816abc42..d60575a8 100644 --- a/accel-pppd/ppp/ppp_ipv6cp.c +++ b/accel-pppd/ppp/ppp_ipv6cp.c @@ -811,6 +811,9 @@ static void load_config(void) static void ipv6cp_init(void) { + if (sock6_fd < 0) + return; + load_config(); triton_event_register_handler(EV_CONFIG_RELOAD, (triton_event_func)load_config); |