diff options
Diffstat (limited to 'accel-pppd/ipv6')
-rw-r--r-- | accel-pppd/ipv6/dhcpv6.c | 109 | ||||
-rw-r--r-- | accel-pppd/ipv6/dhcpv6_packet.c | 4 | ||||
-rw-r--r-- | accel-pppd/ipv6/nd.c | 9 |
3 files changed, 52 insertions, 70 deletions
diff --git a/accel-pppd/ipv6/dhcpv6.c b/accel-pppd/ipv6/dhcpv6.c index c43cadc..2227342 100644 --- a/accel-pppd/ipv6/dhcpv6.c +++ b/accel-pppd/ipv6/dhcpv6.c @@ -30,10 +30,15 @@ #define BUF_SIZE 65536 #define MAX_DNS_COUNT 3 +static struct { + struct dhcpv6_opt_serverid hdr; + uint64_t u64; +} __packed serverid; + static int conf_verbose; static int conf_pref_lifetime = 604800; static int conf_valid_lifetime = 2592000; -static struct dhcpv6_opt_serverid conf_serverid; +static struct dhcpv6_opt_serverid *conf_serverid = &serverid.hdr; static int conf_route_via_gw = 1; static struct in6_addr conf_dns[MAX_DNS_COUNT]; @@ -52,7 +57,6 @@ struct dhcpv6_pd { }; static void *pd_key; -static struct in6_addr null_addr; static int dhcpv6_read(struct triton_md_handler_t *h); @@ -69,7 +73,7 @@ static void ev_ses_started(struct ap_session *ses) return; a = list_entry(ses->ipv6->addr_list.next, typeof(*a), entry); - if (a->prefix_len == 0 || memcmp(a->addr.s6_addr, null_addr.s6_addr, sizeof(null_addr)) == 0) + if (a->prefix_len == 0 || IN6_IS_ADDR_UNSPECIFIED(&a->addr)) return; sock = net->socket(AF_INET6, SOCK_DGRAM, 0); @@ -163,22 +167,8 @@ static void ev_ses_finished(struct ap_session *ses) _free(pd); } -static void build_addr(struct ipv6db_addr_t *a, uint64_t intf_id, struct in6_addr *addr) -{ - memcpy(addr, &a->addr, sizeof(*addr)); - - if (a->prefix_len == 128) - return; - - if (a->prefix_len <= 64) - *(uint64_t *)(addr->s6_addr + 8) = intf_id; - else - *(uint64_t *)(addr->s6_addr + 8) |= intf_id & htobe64((1 << (128 - a->prefix_len)) - 1); -} - static void insert_dp_routes(struct ap_session *ses, struct dhcpv6_pd *pd) { - struct ipv6db_addr_t *a; struct ipv6db_addr_t *p; struct in6_rtmsg rt6; char str1[INET6_ADDRSTRLEN]; @@ -189,37 +179,27 @@ static void insert_dp_routes(struct ap_session *ses, struct dhcpv6_pd *pd) rt6.rtmsg_ifindex = ses->ifindex; rt6.rtmsg_flags = RTF_UP; + if (conf_route_via_gw) { + rt6.rtmsg_flags |= RTF_GATEWAY; + rt6.rtmsg_gateway.s6_addr32[0] = htonl(0xfe800000); + memcpy(rt6.rtmsg_gateway.s6_addr + 8, &ses->ipv6->peer_intf_id, 8); + } + list_for_each_entry(p, &ses->ipv6_dp->prefix_list, entry) { memcpy(&rt6.rtmsg_dst, &p->addr, sizeof(p->addr)); rt6.rtmsg_dst_len = p->prefix_len; - rt6.rtmsg_metric = 1; - - if (conf_route_via_gw) { - rt6.rtmsg_flags |= RTF_GATEWAY; - list_for_each_entry(a, &ses->ipv6->addr_list, entry) { - build_addr(a, ses->ipv6->peer_intf_id, &rt6.rtmsg_gateway); - if (net->sock6_ioctl(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: route add %s/%i via %s: %s\n", str1, p->prefix_len, str2, strerror(err)); - } else if (conf_verbose) { - inet_ntop(AF_INET6, &p->addr, str1, sizeof(str1)); - inet_ntop(AF_INET6, &rt6.rtmsg_gateway, str2, sizeof(str2)); - log_ppp_info2("dhcpv6: route add %s/%i via %s\n", str1, p->prefix_len, str2); - } - rt6.rtmsg_metric++; - } - } else { - if (net->sock6_ioctl(SIOCADDRT, &rt6)) { - err = errno; - inet_ntop(AF_INET6, &p->addr, str1, sizeof(str1)); - log_ppp_error("dhcpv6: route add %s/%i: %s\n", - str1, p->prefix_len, strerror(err)); - } else if (conf_verbose) { - inet_ntop(AF_INET6, &p->addr, str1, sizeof(str1)); - log_ppp_info2("dhcpv6: route add %s/%i\n", str1, p->prefix_len); - } + + if (net->sock6_ioctl(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: route add %s/%i%s%s: %s\n", str1, p->prefix_len, + conf_route_via_gw ? " via " : "", str2, strerror(err)); + } else if (conf_verbose) { + inet_ntop(AF_INET6, &p->addr, str1, sizeof(str1)); + inet_ntop(AF_INET6, &rt6.rtmsg_gateway, str2, sizeof(str2)); + log_ppp_info2("dhcpv6: route add %s/%i%s%s\n", str1, p->prefix_len, + conf_route_via_gw ? " via " : "", str2); } } @@ -308,7 +288,7 @@ static void dhcpv6_send_reply(struct dhcpv6_packet *req, struct dhcpv6_pd *pd, i opt2 = dhcpv6_nested_option_alloc(reply, opt1, D6_OPTION_IAADDR, sizeof(*ia_addr) - sizeof(struct dhcpv6_opt_hdr)); ia_addr = (struct dhcpv6_opt_ia_addr *)opt2->hdr; - build_addr(a, ses->ipv6->peer_intf_id, &ia_addr->addr); + build_ip6_addr(a, ses->ipv6->peer_intf_id, &ia_addr->addr); ia_addr->pref_lifetime = htonl(conf_pref_lifetime); ia_addr->valid_lifetime = htonl(conf_valid_lifetime); @@ -322,8 +302,9 @@ static void dhcpv6_send_reply(struct dhcpv6_packet *req, struct dhcpv6_pd *pd, i memcpy(peer_addr.s6_addr + 8, &ses->ipv6->peer_intf_id, 8); ip6addr_add_peer(ses->ifindex, &addr, &peer_addr); } else { - memcpy(addr.s6_addr, &a->addr, 8); - memcpy(addr.s6_addr + 8, &ses->ipv6->intf_id, 8); + build_ip6_addr(a, ses->ipv6->intf_id, &addr); + if (memcmp(&addr, &ia_addr->addr, sizeof(addr)) == 0) + build_ip6_addr(a, ~ses->ipv6->intf_id, &addr); ip6addr_add(ses->ifindex, &addr, a->prefix_len); } a->installed = 1; @@ -340,7 +321,7 @@ static void dhcpv6_send_reply(struct dhcpv6_packet *req, struct dhcpv6_pd *pd, i f1 = 0; list_for_each_entry(a, &ses->ipv6->addr_list, entry) { - build_addr(a, ses->ipv6->peer_intf_id, &addr); + build_ip6_addr(a, ses->ipv6->peer_intf_id, &addr); if (memcmp(&addr, &ia_addr->addr, sizeof(addr))) continue; f1 = 1; @@ -451,10 +432,10 @@ static void dhcpv6_send_reply(struct dhcpv6_packet *req, struct dhcpv6_pd *pd, i insert_status(reply, opt1, D6_STATUS_NoAddrsAvail); // Option Request - } else if (ntohs(opt->hdr->code) == D6_OPTION_ORO) { + } else if (ntohs(opt->hdr->code) == D6_OPTION_ORO) { insert_oro(reply, opt); - } else if (ntohs(opt->hdr->code) == D6_OPTION_RAPID_COMMIT) { + } else if (ntohs(opt->hdr->code) == D6_OPTION_RAPID_COMMIT) { if (req->hdr->type == D6_SOLICIT) dhcpv6_option_alloc(reply, D6_OPTION_RAPID_COMMIT, 0); } @@ -515,7 +496,7 @@ static void dhcpv6_send_reply2(struct dhcpv6_packet *req, struct dhcpv6_pd *pd, if (!f) { list_for_each_entry(a, &ses->ipv6->addr_list, entry) { - build_addr(a, ses->ipv6->peer_intf_id, &addr); + build_ip6_addr(a, ses->ipv6->peer_intf_id, &addr); if (memcmp(&addr, &ia_addr->addr, sizeof(addr))) continue; f1 = 1; @@ -608,7 +589,7 @@ static void dhcpv6_send_reply2(struct dhcpv6_packet *req, struct dhcpv6_pd *pd, f2 = 1; } // Option Request - } else if (ntohs(opt->hdr->code) == D6_OPTION_ORO) + } else if (ntohs(opt->hdr->code) == D6_OPTION_ORO) insert_oro(reply, opt); } @@ -643,7 +624,7 @@ static void dhcpv6_recv_solicit(struct dhcpv6_packet *req) return; } - req->serverid = &conf_serverid; + req->serverid = conf_serverid; if (req->rapid_commit) { if (!pd->clientid) { @@ -697,8 +678,8 @@ static void dhcpv6_recv_renew(struct dhcpv6_packet *req) return; } - if (req->serverid->hdr.len != conf_serverid.hdr.len || - memcmp(req->serverid, &conf_serverid, ntohs(conf_serverid.hdr.len) + sizeof(struct dhcpv6_opt_hdr))) { + if (req->serverid->hdr.len != conf_serverid->hdr.len || + memcmp(req->serverid, conf_serverid, ntohs(conf_serverid->hdr.len) + sizeof(struct dhcpv6_opt_hdr))) { log_ppp_error("dhcpv6: unmatched Server-ID option\n"); return; } @@ -726,7 +707,7 @@ static void dhcpv6_recv_information_request(struct dhcpv6_packet *req) return; } - req->serverid = &conf_serverid; + req->serverid = conf_serverid; dhcpv6_send_reply(req, pd, D6_REPLY); } @@ -752,7 +733,7 @@ static void dhcpv6_recv_rebind(struct dhcpv6_packet *req) return; } - req->serverid = &conf_serverid; + req->serverid = conf_serverid; dhcpv6_send_reply2(req, pd, D6_REPLY); } @@ -926,7 +907,7 @@ static uint64_t parse_serverid(const char *opt) union { uint64_t u64; uint16_t u16[4]; - } u; + } __packed u; int n[4]; int i; @@ -974,12 +955,12 @@ static void load_config(void) else id = htobe64(1); - conf_serverid.hdr.code = htons(D6_OPTION_SERVERID); - conf_serverid.hdr.len = htons(12); - conf_serverid.duid.type = htons(DUID_LL); - conf_serverid.duid.u.ll.htype = htons(27); + conf_serverid->hdr.code = htons(D6_OPTION_SERVERID); + conf_serverid->hdr.len = htons(12); + conf_serverid->duid.type = htons(DUID_LL); + conf_serverid->duid.u.ll.htype = htons(27); //conf_serverid.duid.u.llt.time = htonl(t - t0); - *(uint64_t *)conf_serverid.duid.u.ll.addr = id; + memcpy(conf_serverid->duid.u.ll.addr, &id, sizeof(id)); load_dns(); } diff --git a/accel-pppd/ipv6/dhcpv6_packet.c b/accel-pppd/ipv6/dhcpv6_packet.c index fa18ac6..664a116 100644 --- a/accel-pppd/ipv6/dhcpv6_packet.c +++ b/accel-pppd/ipv6/dhcpv6_packet.c @@ -329,14 +329,14 @@ static void print_ia_na(struct dhcpv6_option *opt, void (*print)(const char *fmt { struct dhcpv6_opt_ia_na *o = (struct dhcpv6_opt_ia_na *)opt->hdr; - print(" %x T1=%i T2=%i", o->iaid, ntohl(o->T1), ntohl(o->T2)); + print(" %x T1=%i T2=%i", ntohl(o->iaid), ntohl(o->T1), ntohl(o->T2)); } static void print_ia_ta(struct dhcpv6_option *opt, void (*print)(const char *fmt, ...)) { struct dhcpv6_opt_ia_ta *o = (struct dhcpv6_opt_ia_ta *)opt->hdr; - print(" %x", o->iaid); + print(" %x", ntohl(o->iaid)); } static void print_ia_addr(struct dhcpv6_option *opt, void (*print)(const char *fmt, ...)) diff --git a/accel-pppd/ipv6/nd.c b/accel-pppd/ipv6/nd.c index a93724c..4dd9d5a 100644 --- a/accel-pppd/ipv6/nd.c +++ b/accel-pppd/ipv6/nd.c @@ -90,7 +90,6 @@ struct ipv6_nd_handler_t }; static void *pd_key; -static struct in6_addr null_addr; #define BUF_SIZE 1024 static mempool_t buf_pool; @@ -154,8 +153,10 @@ static void ipv6_nd_send_ra(struct ipv6_nd_handler_t *h, struct sockaddr_in6 *ds memcpy(peer_addr.s6_addr + 8, &ses->ipv6->peer_intf_id, 8); ip6addr_add_peer(ses->ifindex, &addr, &peer_addr); } else { - memcpy(addr.s6_addr, &a->addr, 8); - memcpy(addr.s6_addr + 8, &ses->ipv6->intf_id, 8); + build_ip6_addr(a, ses->ipv6->intf_id, &addr); + build_ip6_addr(a, ses->ipv6->peer_intf_id, &peer_addr); + if (memcmp(&addr, &peer_addr, sizeof(addr)) == 0) + build_ip6_addr(a, ~ses->ipv6->intf_id, &addr); ip6addr_add(ses->ifindex, &addr, a->prefix_len); } a->installed = 1; @@ -383,7 +384,7 @@ static void ev_ses_started(struct ap_session *ses) return; list_for_each_entry(a, &ses->ipv6->addr_list, entry) { - if (a->prefix_len && memcmp(a->addr.s6_addr, null_addr.s6_addr, sizeof(null_addr))) { + if (a->prefix_len && !IN6_IS_ADDR_UNSPECIFIED(&a->addr)) { ipv6_nd_start(ses); break; } |