diff options
Diffstat (limited to 'accel-pppd/ppp')
-rw-r--r-- | accel-pppd/ppp/ipcp_opt_ipaddr.c | 102 | ||||
-rw-r--r-- | accel-pppd/ppp/ipv6_nd.c | 207 | ||||
-rw-r--r-- | accel-pppd/ppp/ipv6cp_opt_intfid.c | 49 | ||||
-rw-r--r-- | accel-pppd/ppp/ppp.h | 9 |
4 files changed, 212 insertions, 155 deletions
diff --git a/accel-pppd/ppp/ipcp_opt_ipaddr.c b/accel-pppd/ppp/ipcp_opt_ipaddr.c index ac45ac7c..f3870691 100644 --- a/accel-pppd/ppp/ipcp_opt_ipaddr.c +++ b/accel-pppd/ppp/ipcp_opt_ipaddr.c @@ -30,36 +30,36 @@ static void ipaddr_print(void (*print)(const char *fmt,...),struct ipcp_option_t struct ipaddr_option_t { struct ipcp_option_t opt; - struct ipv4db_item_t *ip; + struct ppp_t *ppp; int started:1; }; -static struct ipcp_option_handler_t ipaddr_opt_hnd= -{ - .init=ipaddr_init, - .send_conf_req=ipaddr_send_conf_req, - .send_conf_nak=ipaddr_send_conf_nak, - .recv_conf_req=ipaddr_recv_conf_req, - .free=ipaddr_free, - .print=ipaddr_print, +static struct ipcp_option_handler_t ipaddr_opt_hnd = { + .init = ipaddr_init, + .send_conf_req = ipaddr_send_conf_req, + .send_conf_nak = ipaddr_send_conf_nak, + .recv_conf_req = ipaddr_recv_conf_req, + .free = ipaddr_free, + .print = ipaddr_print, }; static struct ipcp_option_t *ipaddr_init(struct ppp_ipcp_t *ipcp) { - struct ipaddr_option_t *ipaddr_opt=_malloc(sizeof(*ipaddr_opt)); - memset(ipaddr_opt,0,sizeof(*ipaddr_opt)); - ipaddr_opt->opt.id=CI_ADDR; - ipaddr_opt->opt.len=6; + struct ipaddr_option_t *ipaddr_opt = _malloc(sizeof(*ipaddr_opt)); + memset(ipaddr_opt, 0, sizeof(*ipaddr_opt)); + ipaddr_opt->opt.id = CI_ADDR; + ipaddr_opt->opt.len = 6; + ipaddr_opt->ppp = ipcp->ppp; return &ipaddr_opt->opt; } static void ipaddr_free(struct ppp_ipcp_t *ipcp, struct ipcp_option_t *opt) { - struct ipaddr_option_t *ipaddr_opt=container_of(opt,typeof(*ipaddr_opt),opt); + struct ipaddr_option_t *ipaddr_opt = container_of(opt, typeof(*ipaddr_opt), opt); - if (ipaddr_opt->ip) - ipdb_put_ipv4(ipcp->ppp, ipaddr_opt->ip); + if (ipcp->ppp->ipv4) + ipdb_put_ipv4(ipcp->ppp, ipcp->ppp->ipv4); _free(ipaddr_opt); } @@ -71,8 +71,8 @@ static int check_exists(struct ppp_t *self_ppp, in_addr_t addr) pthread_rwlock_rdlock(&ppp_lock); list_for_each_entry(ppp, &ppp_list, entry) { - if (!ppp->terminating && ppp->peer_ipaddr == addr && ppp != self_ppp) { - log_ppp_warn("ppp:ipcp: requested IP already assigned to %s\n", ppp->ifname); + if (!ppp->terminating && ppp->ipv4 && ppp->ipv4->peer_addr == addr && ppp != self_ppp) { + log_ppp_warn("ppp: requested IPv4 address already assigned to %s\n", ppp->ifname); r = 1; break; } @@ -84,74 +84,63 @@ static int check_exists(struct ppp_t *self_ppp, in_addr_t addr) static int ipaddr_send_conf_req(struct ppp_ipcp_t *ipcp, struct ipcp_option_t *opt, uint8_t *ptr) { - struct ipaddr_option_t *ipaddr_opt=container_of(opt,typeof(*ipaddr_opt),opt); - struct ipcp_opt32_t *opt32=(struct ipcp_opt32_t*)ptr; + struct ipaddr_option_t *ipaddr_opt = container_of(opt, typeof(*ipaddr_opt), opt); + struct ipcp_opt32_t *opt32 = (struct ipcp_opt32_t *)ptr; - if (!ipaddr_opt->ip) { - ipaddr_opt->ip = ipdb_get_ipv4(ipcp->ppp); - if (!ipaddr_opt->ip) { - log_ppp_warn("ppp:ipcp: no free IP address\n"); + if (!ipcp->ppp->ipv4) { + ipcp->ppp->ipv4 = ipdb_get_ipv4(ipcp->ppp); + if (!ipcp->ppp->ipv4) { + log_ppp_warn("ppp: no free IPv4 address\n"); return -1; } } - if (iprange_tunnel_check(ipaddr_opt->ip->peer_addr)) { + if (iprange_tunnel_check(ipcp->ppp->ipv4->peer_addr)) { log_ppp_warn("ppp:ipcp: to avoid kernel soft lockup requested IP cannot be assigned (%i.%i.%i.%i)\n", - ipaddr_opt->ip->peer_addr&0xff, - (ipaddr_opt->ip->peer_addr >> 8)&0xff, - (ipaddr_opt->ip->peer_addr >> 16)&0xff, - (ipaddr_opt->ip->peer_addr >> 24)&0xff); + ipcp->ppp->ipv4->peer_addr&0xff, + (ipcp->ppp->ipv4->peer_addr >> 8)&0xff, + (ipcp->ppp->ipv4->peer_addr >> 16)&0xff, + (ipcp->ppp->ipv4->peer_addr >> 24)&0xff); return -1; } - if (conf_check_exists && check_exists(ipcp->ppp, ipaddr_opt->ip->peer_addr)) + if (conf_check_exists && check_exists(ipcp->ppp, ipcp->ppp->ipv4->peer_addr)) return -1; - ipcp->ppp->ipaddr = ipaddr_opt->ip->addr; - ipcp->ppp->peer_ipaddr = ipaddr_opt->ip->peer_addr; - - opt32->hdr.id=CI_ADDR; - opt32->hdr.len=6; - opt32->val=ipaddr_opt->ip->addr; + opt32->hdr.id = CI_ADDR; + opt32->hdr.len = 6; + opt32->val = ipcp->ppp->ipv4->addr; return 6; } static int ipaddr_send_conf_nak(struct ppp_ipcp_t *ipcp, struct ipcp_option_t *opt, uint8_t *ptr) { - struct ipaddr_option_t *ipaddr_opt=container_of(opt,typeof(*ipaddr_opt),opt); - struct ipcp_opt32_t *opt32=(struct ipcp_opt32_t*)ptr; - opt32->hdr.id=CI_ADDR; - opt32->hdr.len=6; - opt32->val=ipaddr_opt->ip->peer_addr; + struct ipaddr_option_t *ipaddr_opt = container_of(opt, typeof(*ipaddr_opt), opt); + struct ipcp_opt32_t *opt32 = (struct ipcp_opt32_t *)ptr; + opt32->hdr.id = CI_ADDR; + opt32->hdr.len = 6; + opt32->val = ipcp->ppp->ipv4->peer_addr; return 6; } static int ipaddr_recv_conf_req(struct ppp_ipcp_t *ipcp, struct ipcp_option_t *opt, uint8_t *ptr) { - struct ipaddr_option_t *ipaddr_opt = container_of(opt,typeof(*ipaddr_opt), opt); - struct ipcp_opt32_t *opt32 = (struct ipcp_opt32_t*)ptr; + struct ipaddr_option_t *ipaddr_opt = container_of(opt, typeof(*ipaddr_opt), opt); + struct ipcp_opt32_t *opt32 = (struct ipcp_opt32_t *)ptr; if (opt32->hdr.len != 6) return IPCP_OPT_REJ; - if (ipaddr_opt->ip->peer_addr == opt32->val) { - //ipcp->ppp->ipaddr = ipaddr_opt->ip->addr; - //ipcp->ppp->peer_ipaddr = ipaddr_opt->ip->peer_addr; + if (ipcp->ppp->ipv4->peer_addr == opt32->val) { ipcp->delay_ack = ccp_ipcp_started(ipcp->ppp); return IPCP_OPT_ACK; } - /*if (!ipaddr_opt->peer_addr) { - ipaddr_opt->peer_addr = opt32->val; - goto ack; - }*/ - return IPCP_OPT_NAK; } static void if_up(struct ppp_t *ppp) { - struct ipaddr_option_t *ipaddr_opt = container_of(ipcp_find_option(ppp, &ipaddr_opt_hnd), typeof(*ipaddr_opt), opt); struct ifreq ifr; struct sockaddr_in addr; struct npioctl np; @@ -162,13 +151,13 @@ static void if_up(struct ppp_t *ppp) strcpy(ifr.ifr_name, ppp->ifname); addr.sin_family = AF_INET; - addr.sin_addr.s_addr = ipaddr_opt->ip->addr; + addr.sin_addr.s_addr = ppp->ipv4->addr; memcpy(&ifr.ifr_addr,&addr,sizeof(addr)); if (ioctl(sock_fd, SIOCSIFADDR, &ifr)) log_ppp_error("ipcp: failed to set PA address: %s\n", strerror(errno)); - addr.sin_addr.s_addr = ipaddr_opt->ip->peer_addr; + addr.sin_addr.s_addr = ppp->ipv4->peer_addr; memcpy(&ifr.ifr_dstaddr,&addr,sizeof(addr)); if (ioctl(sock_fd, SIOCSIFDSTADDR, &ifr)) @@ -205,8 +194,8 @@ static void ipaddr_print(void (*print)(const char *fmt,...),struct ipcp_option_t if (ptr) in.s_addr = opt32->val; - else if (ipaddr_opt->ip) - in.s_addr = ipaddr_opt->ip->addr; + else if (ipaddr_opt->ppp->ipv4) + in.s_addr = ipaddr_opt->ppp->ipv4->addr; print("<addr %s>",inet_ntoa(in)); } @@ -229,3 +218,4 @@ static void ipaddr_opt_init() } DEFINE_INIT(4, ipaddr_opt_init); + diff --git a/accel-pppd/ppp/ipv6_nd.c b/accel-pppd/ppp/ipv6_nd.c index bec0ea3c..e0ec842e 100644 --- a/accel-pppd/ppp/ipv6_nd.c +++ b/accel-pppd/ppp/ipv6_nd.c @@ -7,18 +7,50 @@ #include <pthread.h> #include <netinet/in.h> #include <netinet/icmp6.h> +#include <arpa/inet.h> #include <sys/socket.h> #include <sys/ioctl.h> #include "log.h" #include "ppp.h" #include "events.h" +#include "mempool.h" +#include "ipdb.h" #include "memdebug.h" +#define MAX_DNS_COUNT 3 + static int conf_init_ra = 3; static int conf_init_ra_interval = 1; static int conf_ra_interval = 60; +static int conf_router_lifetime = 300; +static int conf_rdnss_lifetime = 300; +static struct in6_addr conf_dns[MAX_DNS_COUNT]; +static int conf_dns_count; + +#undef ND_OPT_ROUTE_INFORMATION +#define ND_OPT_ROUTE_INFORMATION 24 +struct nd_opt_route_info_local /* route information */ +{ + uint8_t nd_opt_ri_type; + uint8_t nd_opt_ri_len; + uint8_t nd_opt_ri_prefix_len; + uint8_t nd_opt_ri_flags_reserved; + uint32_t nd_opt_ri_lifetime; + struct in6_addr nd_opt_ri_prefix; +}; + +#undef ND_OPT_RDNSS_INFORMATION +#define ND_OPT_RDNSS_INFORMATION 25 +struct nd_opt_rdnss_info_local +{ + uint8_t nd_opt_rdnssi_type; + uint8_t nd_opt_rdnssi_len; + uint16_t nd_opt_rdnssi_pref_flag_reserved; + uint32_t nd_opt_rdnssi_lifetime; + struct in6_addr nd_opt_rdnssi[0]; +}; struct ipv6_nd_handler_t { @@ -32,84 +64,112 @@ struct ipv6_nd_handler_t static void *pd_key; #define BUF_SIZE 1024 +static mempool_t buf_pool; -static void ipv6_nd_send_ra(struct ipv6_nd_handler_t *h) +static void ipv6_nd_send_ra(struct ipv6_nd_handler_t *h, struct sockaddr_in6 *addr) { - void *buf = _malloc(BUF_SIZE); + void *buf = mempool_alloc(buf_pool), *endptr; struct nd_router_advert *adv = buf; struct nd_opt_prefix_info *pinfo; - //struct nd_opt_route_info *rinfo; - //struct nd_opt_rdnss_info_local *rdnssinfo; + struct nd_opt_route_info_local *rinfo; + struct nd_opt_rdnss_info_local *rdnssinfo; + struct in6_addr *rdnss_addr; //struct nd_opt_mtu *mtu; - struct sockaddr_in6 addr; + struct ipv6db_addr_t *a; + int i; + + if (!buf) { + log_emerg("out of memory\n"); + return; + } memset(adv, 0, sizeof(*adv)); adv->nd_ra_type = ND_ROUTER_ADVERT; adv->nd_ra_curhoplimit = 64; - adv->nd_ra_router_lifetime = htons(1); + adv->nd_ra_router_lifetime = htons(conf_router_lifetime); //adv->nd_ra_reachable = 0; //adv->nd_ra_retransmit = 0; pinfo = (struct nd_opt_prefix_info *)(adv + 1); - memset(pinfo, 0, sizeof(*pinfo)); - pinfo->nd_opt_pi_type = ND_OPT_PREFIX_INFORMATION; - pinfo->nd_opt_pi_len = 4; - pinfo->nd_opt_pi_prefix_len = h->ppp->ipv6_prefix_len; - pinfo->nd_opt_pi_flags_reserved = ND_OPT_PI_FLAG_ONLINK | ND_OPT_PI_FLAG_AUTO; - pinfo->nd_opt_pi_valid_time = 0xffffffff; - pinfo->nd_opt_pi_preferred_time = 0xffffffff; - memcpy(&pinfo->nd_opt_pi_prefix, &h->ppp->ipv6_addr, 8); + list_for_each_entry(a, &h->ppp->ipv6->addr_list, entry) { + memset(pinfo, 0, sizeof(*pinfo)); + pinfo->nd_opt_pi_type = ND_OPT_PREFIX_INFORMATION; + pinfo->nd_opt_pi_len = 4; + pinfo->nd_opt_pi_prefix_len = a->prefix_len; + pinfo->nd_opt_pi_flags_reserved = ND_OPT_PI_FLAG_ONLINK | ND_OPT_PI_FLAG_AUTO; + pinfo->nd_opt_pi_valid_time = 0xffffffff; + pinfo->nd_opt_pi_preferred_time = 0xffffffff; + memcpy(&pinfo->nd_opt_pi_prefix, &a->addr, 8); + pinfo++; + } + + rinfo = (struct nd_opt_route_info_local *)pinfo; + list_for_each_entry(a, &h->ppp->ipv6->route_list, entry) { + memset(rinfo, 0, sizeof(*rinfo)); + rinfo->nd_opt_ri_type = ND_OPT_ROUTE_INFORMATION; + rinfo->nd_opt_ri_len = 3; + rinfo->nd_opt_ri_prefix_len = a->prefix_len; + rinfo->nd_opt_ri_lifetime = 0xffffffff; + memcpy(&rinfo->nd_opt_ri_prefix, &a->addr, 8); + rinfo++; + } + + if (conf_dns_count) { + rdnssinfo = (struct nd_opt_rdnss_info_local *)rinfo; + memset(rdnssinfo, 0, sizeof(*rdnssinfo)); + rdnssinfo->nd_opt_rdnssi_type = ND_OPT_RDNSS_INFORMATION; + rdnssinfo->nd_opt_rdnssi_len = 1 + 2 * conf_dns_count; + rdnssinfo->nd_opt_rdnssi_lifetime = htonl(conf_rdnss_lifetime); + rdnss_addr = (struct in6_addr *)rdnssinfo->nd_opt_rdnssi; + for (i = 0; i < conf_dns_count; i++) { + memcpy(rdnss_addr, &conf_dns[i], sizeof(*rdnss_addr)); + rdnss_addr++; + } + } else + rdnss_addr = (struct in6_addr *)rinfo; + + endptr = rdnss_addr; - memset(&addr, 0, sizeof(addr)); - addr.sin6_family = AF_INET6; - addr.sin6_addr.s6_addr32[0] = htonl(0xff020000); - addr.sin6_addr.s6_addr32[3] = htonl(0x1); - addr.sin6_scope_id = h->ppp->ifindex; - sendto(h->hnd.fd, buf, (void *)(pinfo + 1) - buf, 0, (struct sockaddr *)&addr, sizeof(addr)); + sendto(h->hnd.fd, buf, endptr - buf, 0, (struct sockaddr *)addr, sizeof(*addr)); - _free(buf); + mempool_free(buf); } static void send_ra_timer(struct triton_timer_t *t) { struct ipv6_nd_handler_t *h = container_of(t, typeof(*h), timer); + struct sockaddr_in6 addr; + + memset(&addr, 0, sizeof(addr)); + addr.sin6_family = AF_INET6; + addr.sin6_addr.s6_addr32[0] = htonl(0xff020000); + addr.sin6_addr.s6_addr32[3] = htonl(0x1); + addr.sin6_scope_id = h->ppp->ifindex; if (h->ra_sent++ == conf_init_ra) { h->timer.period = conf_ra_interval * 1000; triton_timer_mod(t, 0); } - ipv6_nd_send_ra(h); + ipv6_nd_send_ra(h, &addr); } static int ipv6_nd_read(struct triton_md_handler_t *_h) { struct ipv6_nd_handler_t *h = container_of(_h, typeof(*h), hnd); - struct msghdr mhdr; - int chdr_len; - struct iovec iov; - struct cmsghdr *chdr, *cmsg; - struct in6_pktinfo *pkt_info; - struct icmp6_hdr *icmph; - void *buf; + struct icmp6_hdr *icmph = mempool_alloc(buf_pool); int n; + struct sockaddr_in6 addr; + socklen_t addr_len = sizeof(addr); - chdr_len = CMSG_SPACE(sizeof(struct in6_pktinfo)) + CMSG_SPACE(sizeof(int)); - chdr = _malloc(chdr_len); - buf = _malloc(BUF_SIZE); - - iov.iov_len = BUF_SIZE; - iov.iov_base = buf; - - memset(&mhdr, 0, sizeof(mhdr)); - mhdr.msg_iov = &iov; - mhdr.msg_iovlen = 1; - mhdr.msg_control = chdr; - mhdr.msg_controllen = chdr_len; + if (!icmph) { + log_emerg("out of memory\n"); + return 0; + } while (1) { - n = recvmsg(h->hnd.fd, &mhdr, 0); + n = recvfrom(h->hnd.fd, icmph, BUF_SIZE, 0, &addr, &addr_len); if (n == -1) { if (errno == EAGAIN) break; @@ -117,50 +177,30 @@ static int ipv6_nd_read(struct triton_md_handler_t *_h) continue; } - pkt_info = NULL; - for (cmsg = CMSG_FIRSTHDR(&mhdr); cmsg != NULL; cmsg = CMSG_NXTHDR(&mhdr, cmsg)) { - if (cmsg->cmsg_level == IPPROTO_IPV6 && - cmsg->cmsg_type == IPV6_PKTINFO) { - if (cmsg->cmsg_len != CMSG_LEN(sizeof(*pkt_info))) - log_ppp_warn("ipv6_nd: received invalid IPV6_PKTINFO\n"); - else - pkt_info = (struct in6_pktinfo *)CMSG_DATA(cmsg); - break; - } - } - - if (!pkt_info) { - log_ppp_warn("ipv6_nd: no IPV6_PKTINFO\n"); - continue; - } - if (n < sizeof(*icmph)) { log_ppp_warn("ipv6_nd: received short icmp packet (%i)\n", n); continue; } - icmph = buf; - if (icmph->icmp6_type != ND_ROUTER_SOLICIT) { log_ppp_warn("ipv6_nd: received unexcpected icmp packet (%i)\n", icmph->icmp6_type); continue; } - /*if (!IN6_IS_ADDR_LINKLOCAL(&pkt_info->ipi6_addr)) { + if (!IN6_IS_ADDR_LINKLOCAL(&addr.sin6_addr)) { log_ppp_warn("ipv6_nd: received icmp packet from non link-local address\n"); continue; - }*/ + } - /*if (*(uint64_t *)(pkt_info->ipi6_addr.s6_addr + 8) != *(uint64_t *)(h->ppp->ipv6_addr.s6_addr + 8)) { + /*if (*(uint64_t *)(addr.sin6_addr.s6_addr + 8) != *(uint64_t *)(h->ppp->ipv6_addr.s6_addr + 8)) { log_ppp_warn("ipv6_nd: received icmp packet from unknown address\n"); continue; }*/ - ipv6_nd_send_ra(h); + ipv6_nd_send_ra(h, &addr); } - _free(chdr); - _free(buf); + mempool_free(icmph); return 0; } @@ -192,12 +232,6 @@ int ppp_ipv6_nd_start(struct ppp_t *ppp, uint64_t intf_id) goto out_err; } - val = 1; - if (setsockopt(sock, IPPROTO_IPV6, IPV6_RECVPKTINFO, &val, sizeof(val))) { - log_ppp_error("ipv6_nd: setsockopt(IPV6_PKTINFO): %s\n", strerror(errno)); - goto out_err; - } - val = 2; if (setsockopt(sock, IPPROTO_RAW, IPV6_CHECKSUM, &val, sizeof(val))) { log_ppp_error("ipv6_nd: setsockopt(IPV6_CHECKSUM): %s\n", strerror(errno)); @@ -299,10 +333,35 @@ static void ev_ppp_finishing(struct ppp_t *ppp) _free(h); } +static void load_config(void) +{ + struct conf_sect_t *s = conf_get_section("dnsv6"); + struct conf_option_t *opt; + + if (!s) + return; + + conf_dns_count = 0; + + list_for_each_entry(opt, &s->items, entry) { + if (inet_pton(AF_INET6, opt->name, &conf_dns[conf_dns_count]) == 0) { + log_error("dnsv6: faild to parse '%s'\n", opt->name); + continue; + } + if (++conf_dns_count == MAX_DNS_COUNT) + break; + } +} + static void init(void) { + buf_pool = mempool_create(BUF_SIZE); + + load_config(); + + triton_event_register_handler(EV_CONFIG_RELOAD, (triton_event_func)load_config); triton_event_register_handler(EV_PPP_STARTED, (triton_event_func)ev_ppp_started); triton_event_register_handler(EV_PPP_FINISHING, (triton_event_func)ev_ppp_finishing); } -DEFINE_INIT(0, init); +DEFINE_INIT(5, init); diff --git a/accel-pppd/ppp/ipv6cp_opt_intfid.c b/accel-pppd/ppp/ipv6cp_opt_intfid.c index b55d3fff..9a9b9e37 100644 --- a/accel-pppd/ppp/ipv6cp_opt_intfid.c +++ b/accel-pppd/ppp/ipv6cp_opt_intfid.c @@ -45,7 +45,6 @@ struct ipaddr_option_t { struct ipv6cp_option_t opt; uint64_t intf_id; - struct ipv6db_item_t *ip; int started:1; }; @@ -87,25 +86,33 @@ static void ipaddr_free(struct ppp_ipv6cp_t *ipv6cp, struct ipv6cp_option_t *opt _free(ipaddr_opt); } -static int check_exists(struct ppp_t *self_ppp, struct in6_addr *addr) +static int check_exists(struct ppp_t *self_ppp) { struct ppp_t *ppp; + struct ipv6db_addr_t *a1, *a2; int r = 0; pthread_rwlock_rdlock(&ppp_lock); list_for_each_entry(ppp, &ppp_list, entry) { if (ppp->terminating) continue; + if (!ppp->ipv6) + continue; if (ppp == self_ppp) continue; - if (addr->s6_addr32[0] == ppp->ipv6_addr.s6_addr32[0] && - addr->s6_addr32[1] == ppp->ipv6_addr.s6_addr32[1]) { - log_ppp_warn("ppp:ipv6cp: requested IP already assigned to %s\n", ppp->ifname); - r = 1; - break; + list_for_each_entry(a1, &ppp->ipv6->addr_list, entry) { + list_for_each_entry(a2, &self_ppp->ipv6->addr_list, entry) { + if (a1->addr.s6_addr32[0] == a2->addr.s6_addr32[0] && + a1->addr.s6_addr32[1] == a2->addr.s6_addr32[1]) { + log_ppp_warn("ppp: requested IPv6 address already assigned to %s\n", ppp->ifname); + r = 1; + goto out; + } + } } } +out: pthread_rwlock_unlock(&ppp_lock); return r; @@ -116,20 +123,17 @@ static int ipaddr_send_conf_req(struct ppp_ipv6cp_t *ipv6cp, struct ipv6cp_optio struct ipaddr_option_t *ipaddr_opt = container_of(opt, typeof(*ipaddr_opt), opt); struct ipv6cp_opt64_t *opt64 = (struct ipv6cp_opt64_t *)ptr; - if (!ipaddr_opt->ip) { - ipaddr_opt->ip = ipdb_get_ipv6(ipv6cp->ppp); - if (!ipaddr_opt->ip) { - log_ppp_warn("ppp:ipv6cp: no free IP address\n"); + if (!ipv6cp->ppp->ipv6) { + ipv6cp->ppp->ipv6 = ipdb_get_ipv6(ipv6cp->ppp); + if (!ipv6cp->ppp->ipv6) { + log_ppp_warn("ppp: no free IPv6 address\n"); return -1; } } - if (conf_check_exists && check_exists(ipv6cp->ppp, &ipaddr_opt->ip->addr)) + if (conf_check_exists && check_exists(ipv6cp->ppp)) return -1; - ipv6cp->ppp->ipv6_addr = ipaddr_opt->ip->addr; - ipv6cp->ppp->ipv6_prefix_len = ipaddr_opt->ip->prefix_len; - opt64->hdr.id = CI_INTFID; opt64->hdr.len = 10; opt64->val = ipaddr_opt->intf_id; @@ -142,7 +146,7 @@ static int ipaddr_send_conf_nak(struct ppp_ipv6cp_t *ipv6cp, struct ipv6cp_optio struct ipv6cp_opt64_t *opt64 = (struct ipv6cp_opt64_t *)ptr; opt64->hdr.id = CI_INTFID; opt64->hdr.len = 10; - opt64->val = *(uint64_t *)(&ipaddr_opt->ip->addr.s6_addr32[2]); + opt64->val = ipv6cp->ppp->ipv6->intf_id; return 10; } @@ -151,11 +155,12 @@ static int ipaddr_recv_conf_req(struct ppp_ipv6cp_t *ipv6cp, struct ipv6cp_optio struct ipaddr_option_t *ipaddr_opt = container_of(opt, typeof(*ipaddr_opt), opt); struct ipv6cp_opt64_t *opt64 = (struct ipv6cp_opt64_t* )ptr; struct in6_ifreq ifr6; + struct ipv6db_addr_t *a; if (opt64->hdr.len != 10) return IPV6CP_OPT_REJ; - if (*(uint64_t *)(&ipaddr_opt->ip->addr.s6_addr32[2]) == opt64->val) + if (ipv6cp->ppp->ipv6->intf_id == opt64->val) goto ack; return IPV6CP_OPT_NAK; @@ -188,11 +193,13 @@ ack: return IPV6CP_OPT_REJ; } - memcpy(ifr6.ifr6_addr.s6_addr, ipaddr_opt->ip->addr.s6_addr, 8); + list_for_each_entry(a, &ipv6cp->ppp->ipv6->addr_list, entry) { + memcpy(ifr6.ifr6_addr.s6_addr, a->addr.s6_addr, 8); - if (ioctl(sock6_fd, SIOCSIFADDR, &ifr6)) { - log_ppp_error("ppp:ipv6cp: ioctl(SIOCSIFADDR): %s\n", strerror(errno)); - return IPV6CP_OPT_REJ; + if (ioctl(sock6_fd, SIOCSIFADDR, &ifr6)) { + log_ppp_error("ppp:ipv6cp: ioctl(SIOCSIFADDR): %s\n", strerror(errno)); + return IPV6CP_OPT_REJ; + } } if (ppp_ipv6_nd_start(ipv6cp->ppp, ipaddr_opt->intf_id)) diff --git a/accel-pppd/ppp/ppp.h b/accel-pppd/ppp/ppp.h index 4708578e..f95893ab 100644 --- a/accel-pppd/ppp/ppp.h +++ b/accel-pppd/ppp/ppp.h @@ -62,6 +62,9 @@ struct ppp_t; +struct ipv4db_item_t; +struct ipv6db_item_t; + struct ppp_ctrl_t { struct triton_context_t *ctx; @@ -100,10 +103,8 @@ struct ppp_t time_t start_time; time_t stop_time; char *username; - in_addr_t ipaddr; - in_addr_t peer_ipaddr; - struct in6_addr ipv6_addr; - int ipv6_prefix_len; + struct ipv4db_item_t *ipv4; + struct ipv6db_item_t *ipv6; struct ppp_ctrl_t *ctrl; |