summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorMikael Magnusson <mikma@users.sourceforge.net>2021-01-14 18:07:43 +0100
committerMikael Magnusson <mikma@users.sourceforge.net>2024-01-13 19:08:01 +0000
commit8e89b1fb27309741b54485d35f6c215f3a1c976d (patch)
tree06999b9312430ac66c8dc90e94a9ae45375d133b
parentd8118f6e76e5519881f9a37137c3a06b3cb60fd2 (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.c14
-rw-r--r--src/odhcpd.h1
-rw-r--r--src/ubus.c57
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,
diff --git a/src/ubus.c b/src/ubus.c
index 45b29a4..c4fbf92 100644
--- a/src/ubus.c
+++ b/src/ubus.c
@@ -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)
{