diff options
author | Mikael Magnusson <mikma@users.sourceforge.net> | 2021-01-14 18:07:43 +0100 |
---|---|---|
committer | Mikael Magnusson <mikma@users.sourceforge.net> | 2024-01-13 19:08:01 +0000 |
commit | 8e89b1fb27309741b54485d35f6c215f3a1c976d (patch) | |
tree | 06999b9312430ac66c8dc90e94a9ae45375d133b | |
parent | d8118f6e76e5519881f9a37137c3a06b3cb60fd2 (diff) |
dhcpv6: broadcast ipv6 events via ubus
Broadcast dhcpv6.ack and dhcpv6.release for IA_NA and IA_PD
assignments.
Include the peer address to allow relating the lease to
a WireGuard peer.
-rw-r--r-- | src/dhcpv6-ia.c | 14 | ||||
-rw-r--r-- | src/odhcpd.h | 1 | ||||
-rw-r--r-- | src/ubus.c | 57 |
3 files changed, 71 insertions, 1 deletions
diff --git a/src/dhcpv6-ia.c b/src/dhcpv6-ia.c index 1fbed44..03656ae 100644 --- a/src/dhcpv6-ia.c +++ b/src/dhcpv6-ia.c @@ -208,7 +208,7 @@ static void dhcpv6_ia_free_assignment(struct dhcp_assignment *a) close(a->managed_sock.fd.fd); } - if ((a->flags & OAF_BOUND) && (a->flags & OAF_DHCPV6_PD)) + if (a->flags & OAF_BOUND) apply_lease(a, false); if (a->reconf_cnt) @@ -591,6 +591,10 @@ void dhcpv6_ia_write_statefile(void) static void __apply_lease(struct dhcp_assignment *a, struct odhcpd_ipaddr *addrs, ssize_t addr_len, bool add) { +#ifdef WITH_UBUS + ubus_bcast_dhcpv6_event(add?"dhcpv6.ack":"dhcpv6.release", a, addrs, addr_len); +#endif + if (a->flags & OAF_DHCPV6_NA) return; @@ -842,6 +846,10 @@ static bool assign_na(struct interface *iface, struct dhcp_assignment *a) list_for_each_entry(c, &iface->ia_assignments, head) { if (!(c->flags & OAF_DHCPV6_NA) || c->assigned_host_id > a->assigned_host_id ) { list_add_tail(&a->head, &c->head); + + if (a->flags & OAF_BOUND) + apply_lease(a, true); + return true; } else if (c->assigned_host_id == a->assigned_host_id) return false; @@ -889,6 +897,10 @@ static bool assign_na(struct interface *iface, struct dhcp_assignment *a) if (!(c->flags & OAF_DHCPV6_NA) || c->assigned_host_id > try) { a->assigned_host_id = try; list_add_tail(&a->head, &c->head); + + if (a->flags & OAF_BOUND) + apply_lease(a, true); + return true; } else if (c->assigned_host_id == try) break; diff --git a/src/odhcpd.h b/src/odhcpd.h index 02b6ac0..ac2dcac 100644 --- a/src/odhcpd.h +++ b/src/odhcpd.h @@ -442,6 +442,7 @@ void ubus_apply_network(void); bool ubus_has_prefix(const char *name, const char *ifname); void ubus_bcast_dhcp_event(const char *type, const uint8_t *mac, const size_t mac_len, const struct in_addr *addr, const char *name, const char *interface); +void ubus_bcast_dhcpv6_event(const char *type, const struct dhcp_assignment *a, const struct odhcpd_ipaddr *addrs, ssize_t addr_len); #endif ssize_t dhcpv6_ia_handle_IAs(uint8_t *buf, size_t buflen, struct interface *iface, @@ -360,6 +360,63 @@ void ubus_bcast_dhcp_event(const char *type, const uint8_t *mac, ubus_notify(ubus, &main_object, type, b.head, -1); } +void ubus_bcast_dhcpv6_event(const char *type, const struct dhcp_assignment *a, const struct odhcpd_ipaddr *addrs, ssize_t addr_len) +{ + char buf[INET6_ADDRSTRLEN] = ""; + + if (!ubus || !main_object.has_subscribers || !type || !a || !addrs || !addr_len) + return; + + blob_buf_init(&b, 0); + + if (a->hostname) + blobmsg_add_string(&b, "name", a->hostname); + + blobmsg_add_string(&b, "type", a->flags & OAF_DHCPV6_NA ? "IA_NA" : "IA_PD"); + + if (a->iaid) + blobmsg_add_u32(&b, "iaid", ntohl(a->iaid)); + + if (a->iface->ifname) + blobmsg_add_string(&b, "interface", a->iface->ifname); + + if (a->clid_data && a->clid_len) { + char *duid = blobmsg_alloc_string_buffer(&b, "duid", a->clid_len * 2 + 1); + odhcpd_hexlify(duid, a->clid_data, a->clid_len); + blobmsg_add_string_buffer(&b); + } + + char *peer = blobmsg_alloc_string_buffer(&b, "peer", INET6_ADDRSTRLEN); + inet_ntop(AF_INET6, &a->peer.sin6_addr, peer, INET6_ADDRSTRLEN); + blobmsg_add_string_buffer(&b); + + void *i = blobmsg_open_array(&b, "ips"); + for (int j=0; j < addr_len; j++) { + const size_t IP_SIZE = sizeof(buf) + 4; + struct in6_addr prefix = addrs[j].addr.in6; + + if (!(a->flags & OAF_DHCPV6_PD)) { + prefix.s6_addr32[2] = htonl(a->assigned_host_id >> 32); + prefix.s6_addr32[3] = htonl(a->assigned_host_id & UINT32_MAX); + } else { + prefix.s6_addr32[1] |= htonl(a->assigned_subnet_id); + prefix.s6_addr32[2] = prefix.s6_addr32[3] = 0; + } + + void *k = blobmsg_open_table(&b, NULL); + + char *ip = blobmsg_alloc_string_buffer(&b, "ip", IP_SIZE); + inet_ntop(AF_INET6, &prefix, buf, INET6_ADDRSTRLEN); + snprintf(ip, IP_SIZE, "%s/%d", buf, a->length); + blobmsg_add_string_buffer(&b); + + blobmsg_close_table(&b, k); + } + blobmsg_close_array(&b, i); + + ubus_notify(ubus, &main_object, type, b.head, -1); +} + static void handle_event(_unused struct ubus_context *ctx, _unused struct ubus_event_handler *ev, _unused const char *type, struct blob_attr *msg) { |