summaryrefslogtreecommitdiff
path: root/accel-pppd/ppp/ipv6cp_opt_intfid.c
diff options
context:
space:
mode:
Diffstat (limited to 'accel-pppd/ppp/ipv6cp_opt_intfid.c')
-rw-r--r--accel-pppd/ppp/ipv6cp_opt_intfid.c49
1 files changed, 28 insertions, 21 deletions
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))