summaryrefslogtreecommitdiff
path: root/accel-pppd/ppp/ipv6cp_opt_intfid.c
diff options
context:
space:
mode:
authorKozlov Dmitry <xeb@mail.ru>2011-08-28 00:37:34 +0400
committerKozlov Dmitry <xeb@mail.ru>2011-08-28 00:37:34 +0400
commit6459c6085f7324404717418448fa8c04ffd46c20 (patch)
tree9c610e3aa4497463caf0c534f725d059229e0db0 /accel-pppd/ppp/ipv6cp_opt_intfid.c
parent2ae178c12aced47699cbb252f6a67defb0d0bbe7 (diff)
downloadaccel-ppp-xebd-6459c6085f7324404717418448fa8c04ffd46c20.tar.gz
accel-ppp-xebd-6459c6085f7324404717418448fa8c04ffd46c20.zip
ipv6: initial dhcpv6 support
Diffstat (limited to 'accel-pppd/ppp/ipv6cp_opt_intfid.c')
-rw-r--r--accel-pppd/ppp/ipv6cp_opt_intfid.c61
1 files changed, 39 insertions, 22 deletions
diff --git a/accel-pppd/ppp/ipv6cp_opt_intfid.c b/accel-pppd/ppp/ipv6cp_opt_intfid.c
index 610f0dc..cc7ce36 100644
--- a/accel-pppd/ppp/ipv6cp_opt_intfid.c
+++ b/accel-pppd/ppp/ipv6cp_opt_intfid.c
@@ -50,8 +50,8 @@ static void ipaddr_print(void (*print)(const char *fmt,...),struct ipv6cp_option
struct ipaddr_option_t
{
struct ipv6cp_option_t opt;
- uint64_t intf_id;
int started:1;
+ struct ppp_t *ppp;
};
static struct ipv6cp_option_handler_t ipaddr_opt_hnd =
@@ -72,16 +72,8 @@ static struct ipv6cp_option_t *ipaddr_init(struct ppp_ipv6cp_t *ipv6cp)
ipaddr_opt->opt.id = CI_INTFID;
ipaddr_opt->opt.len = 10;
+ ipaddr_opt->ppp = ipv6cp->ppp;
- switch (conf_intf_id) {
- case INTF_ID_FIXED:
- ipaddr_opt->intf_id = conf_intf_id_val;
- break;
- case INTF_ID_RANDOM:
- read(urandom_fd, &ipaddr_opt->intf_id, 8);
- break;
- }
-
return &ipaddr_opt->opt;
}
@@ -127,6 +119,23 @@ out:
return r;
}
+static uint64_t generate_intf_id(struct ppp_t *ppp)
+{
+ uint64_t id = 0;
+
+ switch (conf_intf_id) {
+ case INTF_ID_FIXED:
+ return conf_intf_id_val;
+ break;
+ //case INTF_ID_RANDOM:
+ default:
+ read(urandom_fd, &id, 8);
+ break;
+ }
+
+ return id;
+}
+
static uint64_t generate_peer_intf_id(struct ppp_t *ppp)
{
char str[4];
@@ -166,6 +175,9 @@ static int alloc_ip(struct ppp_t *ppp)
log_ppp_warn("ppp: no free IPv6 address\n");
return IPV6CP_OPT_CLOSE;
}
+
+ if (!ppp->ipv6->intf_id)
+ ppp->ipv6->intf_id = generate_intf_id(ppp);
if (conf_check_exists && check_exists(ppp))
return IPV6CP_OPT_FAIL;
@@ -187,7 +199,7 @@ static int ipaddr_send_conf_req(struct ppp_ipv6cp_t *ipv6cp, struct ipv6cp_optio
opt64->hdr.id = CI_INTFID;
opt64->hdr.len = 10;
- opt64->val = ipaddr_opt->intf_id;
+ opt64->val = ipv6cp->ppp->ipv6->intf_id;
return 10;
}
@@ -197,7 +209,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 = ipv6cp->ppp->ipv6->intf_id;
+ opt64->val = ipv6cp->ppp->ipv6->peer_intf_id;
return 10;
}
@@ -219,15 +231,15 @@ static int ipaddr_recv_conf_req(struct ppp_ipv6cp_t *ipv6cp, struct ipv6cp_optio
}
if (conf_accept_peer_intf_id && opt64->val)
- ipv6cp->ppp->ipv6->intf_id = opt64->val;
+ ipv6cp->ppp->ipv6->peer_intf_id = opt64->val;
- if (opt64->val && ipv6cp->ppp->ipv6->intf_id == opt64->val && opt64->val != ipaddr_opt->intf_id) {
+ if (opt64->val && ipv6cp->ppp->ipv6->peer_intf_id == opt64->val && opt64->val != ipv6cp->ppp->ipv6->intf_id) {
ipv6cp->delay_ack = ccp_ipcp_started(ipv6cp->ppp);
goto ack;
}
- ipv6cp->ppp->ipv6->intf_id = generate_peer_intf_id(ipv6cp->ppp);
- if (!ipv6cp->ppp->ipv6->intf_id)
+ ipv6cp->ppp->ipv6->peer_intf_id = generate_peer_intf_id(ipv6cp->ppp);
+ if (!ipv6cp->ppp->ipv6->peer_intf_id)
return IPV6CP_OPT_TERMACK;
return IPV6CP_OPT_NAK;
@@ -251,7 +263,7 @@ ack:
memset(&ifr6, 0, sizeof(ifr6));
ifr6.ifr6_addr.s6_addr32[0] = htons(0xfe80);
- *(uint64_t *)(ifr6.ifr6_addr.s6_addr + 8) = ipaddr_opt->intf_id;
+ *(uint64_t *)(ifr6.ifr6_addr.s6_addr + 8) = ipv6cp->ppp->ipv6->intf_id;
ifr6.ifr6_prefixlen = 64;
ifr6.ifr6_ifindex = ipv6cp->ppp->ifindex;
@@ -261,7 +273,15 @@ ack:
}
list_for_each_entry(a, &ipv6cp->ppp->ipv6->addr_list, entry) {
- memcpy(ifr6.ifr6_addr.s6_addr, a->addr.s6_addr, 8);
+ if (a->prefix_len == 128)
+ continue;
+
+ memcpy(ifr6.ifr6_addr.s6_addr, a->addr.s6_addr, 16);
+
+ if (a->prefix_len <= 64)
+ *(uint64_t *)(ifr6.ifr6_addr.s6_addr + 8) = ipv6cp->ppp->ipv6->intf_id;
+ else
+ *(uint64_t *)(ifr6.ifr6_addr.s6_addr + 8) |= ipv6cp->ppp->ipv6->intf_id & ((1 << (128 - a->prefix_len)) - 1);
if (ioctl(sock6_fd, SIOCSIFADDR, &ifr6)) {
log_ppp_error("ppp:ipv6cp: ioctl(SIOCSIFADDR): %s\n", strerror(errno));
@@ -269,9 +289,6 @@ ack:
}
}
- if (ppp_ipv6_nd_start(ipv6cp->ppp, ipaddr_opt->intf_id))
- return IPV6CP_OPT_REJ;
-
return IPV6CP_OPT_ACK;
}
@@ -284,7 +301,7 @@ static void ipaddr_print(void (*print)(const char *fmt,...), struct ipv6cp_optio
if (ptr)
*(uint64_t *)(a.s6_addr + 8) = opt64->val;
else
- *(uint64_t *)(a.s6_addr + 8) = ipaddr_opt->intf_id;
+ *(uint64_t *)(a.s6_addr + 8) = ipaddr_opt->ppp->ipv6->intf_id;
print("<addr %x:%x:%x:%x>", ntohs(a.s6_addr16[4]), ntohs(a.s6_addr16[5]), ntohs(a.s6_addr16[6]), ntohs(a.s6_addr16[7]));
}