aboutgitcodebugslistschat
path: root/dhcpv6.c
diff options
context:
space:
mode:
Diffstat (limited to 'dhcpv6.c')
-rw-r--r--dhcpv6.c66
1 files changed, 31 insertions, 35 deletions
diff --git a/dhcpv6.c b/dhcpv6.c
index 7dcca2a..0523bba 100644
--- a/dhcpv6.c
+++ b/dhcpv6.c
@@ -296,45 +296,42 @@ static struct opt_hdr *dhcpv6_opt(const struct pool *p, size_t *offset,
static struct opt_hdr *dhcpv6_ia_notonlink(const struct pool *p,
struct in6_addr *la)
{
+ int ia_types[2] = { OPT_IA_NA, OPT_IA_TA }, *ia_type;
+ const struct opt_ia_addr *opt_addr;
char buf[INET6_ADDRSTRLEN];
struct in6_addr req_addr;
- struct opt_hdr *ia, *h;
+ const struct opt_hdr *h;
+ struct opt_hdr *ia;
size_t offset;
- int ia_type;
- ia_type = OPT_IA_NA;
-ia_ta:
- offset = 0;
- while ((ia = dhcpv6_opt(p, &offset, ia_type))) {
- if (ntohs(ia->l) < OPT_VSIZE(ia_na))
- return NULL;
+ foreach(ia_type, ia_types) {
+ offset = 0;
+ while ((ia = dhcpv6_opt(p, &offset, *ia_type))) {
+ if (ntohs(ia->l) < OPT_VSIZE(ia_na))
+ return NULL;
- offset += sizeof(struct opt_ia_na);
+ offset += sizeof(struct opt_ia_na);
- while ((h = dhcpv6_opt(p, &offset, OPT_IAAADR))) {
- struct opt_ia_addr *opt_addr = (struct opt_ia_addr *)h;
+ while ((h = dhcpv6_opt(p, &offset, OPT_IAAADR))) {
+ if (ntohs(h->l) != OPT_VSIZE(ia_addr))
+ return NULL;
- if (ntohs(h->l) != OPT_VSIZE(ia_addr))
- return NULL;
+ opt_addr = (const struct opt_ia_addr *)h;
+ req_addr = opt_addr->addr;
+ if (!IN6_ARE_ADDR_EQUAL(la, &req_addr))
+ goto err;
- memcpy(&req_addr, &opt_addr->addr, sizeof(req_addr));
- if (!IN6_ARE_ADDR_EQUAL(la, &req_addr)) {
- info("DHCPv6: requested address %s not on link",
- inet_ntop(AF_INET6, &req_addr,
- buf, sizeof(buf)));
- return ia;
+ offset += sizeof(struct opt_ia_addr);
}
-
- offset += sizeof(struct opt_ia_addr);
}
}
- if (ia_type == OPT_IA_NA) {
- ia_type = OPT_IA_TA;
- goto ia_ta;
- }
-
return NULL;
+
+err:
+ info("DHCPv6: requested address %s not on link",
+ inet_ntop(AF_INET6, &req_addr, buf, sizeof(buf)));
+ return ia;
}
/**
@@ -363,7 +360,7 @@ static size_t dhcpv6_dns_fill(const struct ctx *c, char *buf, int offset)
srv->hdr.l = 0;
}
- memcpy(&srv->addr[i], &c->ip6.dns[i], sizeof(srv->addr[i]));
+ srv->addr[i] = c->ip6.dns[i];
srv->hdr.l += sizeof(srv->addr[i]);
offset += sizeof(srv->addr[i]);
}
@@ -426,11 +423,11 @@ search:
int dhcpv6(struct ctx *c, const struct pool *p,
const struct in6_addr *saddr, const struct in6_addr *daddr)
{
- struct opt_hdr *ia, *bad_ia, *client_id;
- const struct opt_hdr *server_id;
+ const struct opt_hdr *client_id, *server_id, *ia;
const struct in6_addr *src;
const struct msg_hdr *mh;
const struct udphdr *uh;
+ struct opt_hdr *bad_ia;
size_t mlen, n;
uh = packet_get(p, 0, 0, sizeof(*uh), &mlen);
@@ -451,10 +448,7 @@ int dhcpv6(struct ctx *c, const struct pool *p,
c->ip6.addr_ll_seen = *saddr;
- if (IN6_IS_ADDR_LINKLOCAL(&c->ip6.gw))
- src = &c->ip6.gw;
- else
- src = &c->ip6.addr_ll;
+ src = &c->ip6.our_tap_ll;
mh = packet_get(p, 0, sizeof(*uh), sizeof(*mh), NULL);
if (!mh)
@@ -574,8 +568,10 @@ void dhcpv6_init(const struct ctx *c)
resp.server_id.duid_time = duid_time;
resp_not_on_link.server_id.duid_time = duid_time;
- memcpy(resp.server_id.duid_lladdr, c->mac, sizeof(c->mac));
- memcpy(resp_not_on_link.server_id.duid_lladdr, c->mac, sizeof(c->mac));
+ memcpy(resp.server_id.duid_lladdr,
+ c->our_tap_mac, sizeof(c->our_tap_mac));
+ memcpy(resp_not_on_link.server_id.duid_lladdr,
+ c->our_tap_mac, sizeof(c->our_tap_mac));
resp.ia_addr.addr = c->ip6.addr;
}