diff options
| author | Felix Fietkau | 2025-01-27 11:39:59 +0000 |
|---|---|---|
| committer | Felix Fietkau | 2025-01-27 11:40:04 +0000 |
| commit | c293afa01c1328ee8a18fc407948d0529353d7eb (patch) | |
| tree | 218751552d0b618f29ccb3731ff5c25a699683a7 | |
| parent | d13752814651c70d2afc71383612fafc835b631b (diff) | |
| download | unetd-c293afa01c1328ee8a18fc407948d0529353d7eb.tar.gz | |
network: add support for the local_network option
This lets unetd automatically query netifd for local addresses in order to
add broadcast addresses as PEX hosts for discovering peers.
Signed-off-by: Felix Fietkau <nbd@nbd.name>
| -rw-r--r-- | network.c | 5 | ||||
| -rw-r--r-- | network.h | 2 | ||||
| -rw-r--r-- | pex.c | 85 | ||||
| -rw-r--r-- | pex.h | 7 | ||||
| -rw-r--r-- | ubus.c | 60 | ||||
| -rw-r--r-- | ubus.h | 5 |
6 files changed, 160 insertions, 4 deletions
@@ -57,6 +57,7 @@ const struct blobmsg_policy network_policy[__NETWORK_ATTR_MAX] = { [NETWORK_ATTR_DOMAIN] = { "domain", BLOBMSG_TYPE_STRING }, [NETWORK_ATTR_UPDATE_CMD] = { "update-cmd", BLOBMSG_TYPE_STRING }, [NETWORK_ATTR_TUNNELS] = { "tunnels", BLOBMSG_TYPE_TABLE }, + [NETWORK_ATTR_LOCAL_NET] = { "local_network", BLOBMSG_TYPE_ARRAY }, [NETWORK_ATTR_AUTH_CONNECT] = { "auth_connect", BLOBMSG_TYPE_ARRAY }, [NETWORK_ATTR_PEER_DATA] = { "peer_data", BLOBMSG_TYPE_ARRAY }, }; @@ -656,6 +657,10 @@ network_set_config(struct network *net, struct blob_attr *config) if ((cur = tb[NETWORK_ATTR_TUNNELS]) != NULL) net->config.tunnels = cur; + if ((cur = tb[NETWORK_ATTR_LOCAL_NET]) != NULL && + blobmsg_check_array(cur, BLOBMSG_TYPE_STRING) > 0) + net->config.local_network = cur; + if ((cur = tb[NETWORK_ATTR_AUTH_CONNECT]) != NULL && blobmsg_check_array(cur, BLOBMSG_TYPE_STRING) > 0) net->config.auth_connect = cur; @@ -37,6 +37,7 @@ struct network { const char *domain; struct blob_attr *tunnels; struct blob_attr *net_data; + struct blob_attr *local_network; struct blob_attr *auth_connect; struct blob_attr *peer_data; } config; @@ -87,6 +88,7 @@ enum { NETWORK_ATTR_KEEPALIVE, NETWORK_ATTR_DOMAIN, NETWORK_ATTR_TUNNELS, + NETWORK_ATTR_LOCAL_NET, NETWORK_ATTR_AUTH_CONNECT, NETWORK_ATTR_PEER_DATA, __NETWORK_ATTR_MAX, @@ -740,8 +740,9 @@ network_pex_fd_cb(struct uloop_fd *fd, unsigned int events) } } -void network_pex_create_host(struct network *net, union network_endpoint *ep, - unsigned int timeout) +struct network_pex_host * +network_pex_create_host(struct network *net, union network_endpoint *ep, + unsigned int timeout) { struct network_pex *pex = &net->pex; struct network_pex_host *host; @@ -768,6 +769,7 @@ void network_pex_create_host(struct network *net, union network_endpoint *ep, out: if (timeout && (new_host || host->timeout)) host->timeout = timeout + unet_gettime(); + return host; } static void @@ -812,6 +814,84 @@ network_pex_open_auth_connect(struct network *net) } +static void +__network_pex_reload_iface(struct network *net, struct blob_attr *data) +{ + static const struct blobmsg_policy policy[] = { + { "address", BLOBMSG_TYPE_STRING }, + { "mask", BLOBMSG_TYPE_INT32 }, + }; + struct network_pex_host *host; + struct blob_attr *tb[2], *cur; + size_t rem; + + if (!data) + return; + + blobmsg_for_each_attr(cur, data, rem) { + union network_endpoint ep = {}; + uint32_t mask; + + blobmsg_parse_attr(policy, ARRAY_SIZE(policy), tb, cur); + if (!tb[0] || !tb[1]) + continue; + + mask = blobmsg_get_u32(tb[1]); + if (mask >= 31 || !mask) + continue; + + if (network_get_endpoint(&ep, AF_INET, blobmsg_get_string(tb[0]), + UNETD_GLOBAL_PEX_PORT, 0) < 0) + continue; + + *(uint32_t *)&ep.in.sin_addr |= htonl((~0U) >> mask); + host = network_pex_create_host(net, &ep, 0); + host->interface = true; + } +} + +static void +__network_pex_reload(struct network *net) +{ + struct network_pex *pex = &net->pex; + struct network_pex_host *host, *tmp; + struct blob_attr *cur; + size_t rem; + + if (!net->config.local_network) + return; + + list_for_each_entry_safe(host, tmp, &pex->hosts, list) + if (host->interface) + network_pex_free_host(net, host); + + blobmsg_for_each_attr(cur, net->config.local_network, rem) { + const char *name = blobmsg_get_string(cur); + struct blob_attr *addrs; + + addrs = unetd_ubus_get_network_addr_list(name); + __network_pex_reload_iface(net, addrs); + } +} + +static void +network_pex_reload_cb(struct uloop_timeout *t) +{ + struct network *net; + + avl_for_each_element(&networks, net, node) + __network_pex_reload(net); +} + +void network_pex_reload(void) +{ + static struct uloop_timeout timer = { + .cb = network_pex_reload_cb, + }; + + uloop_timeout_set(&timer, 1); +} + int network_pex_open(struct network *net) { struct network_host *local_host = net->net_config.local_host; @@ -822,6 +902,7 @@ int network_pex_open(struct network *net) int fd; network_pex_open_auth_connect(net); + __network_pex_reload(net); if (!local_host || !local_host->peer.pex_port) return 0; @@ -18,6 +18,7 @@ struct network_pex_host { uint64_t timeout; uint64_t last_active; uint64_t last_ping; + bool interface; union network_endpoint endpoint; }; @@ -76,11 +77,13 @@ void network_pex_init(struct network *net); int network_pex_open(struct network *net); void network_pex_close(struct network *net); void network_pex_free(struct network *net); +void network_pex_reload(); void network_pex_event(struct network *net, struct network_peer *peer, enum pex_event ev); -void network_pex_create_host(struct network *net, union network_endpoint *ep, - unsigned int timeout); +struct network_pex_host * +network_pex_create_host(struct network *net, union network_endpoint *ep, + unsigned int timeout); void network_stun_init(struct network *net); void network_stun_free(struct network *net); @@ -8,6 +8,7 @@ #include "enroll.h" static struct ubus_auto_conn conn; +static struct ubus_subscriber sub; static struct blob_buf b; static int @@ -446,6 +447,7 @@ ubus_connect_handler(struct ubus_context *ctx) { int ret; + ubus_register_subscriber(ctx, &sub); ret = ubus_add_object(ctx, &unetd_object); if (ret) fprintf(stderr, "Failed to add object: %s\n", ubus_strerror(ret)); @@ -514,6 +516,47 @@ void unetd_ubus_netifd_update(struct blob_attr *data) ubus_invoke(&conn.ctx, id, "notify_proto", data, NULL, NULL, 5000); } +static void +ubus_network_status_cb(struct ubus_request *req, int type, struct blob_attr *msg) +{ + static const struct blobmsg_policy policy = + { "ipv4-address", BLOBMSG_TYPE_ARRAY }; + struct blob_attr *attr, *cur; + size_t rem; + + blobmsg_parse_attr(&policy, 1, &attr, msg); + if (!attr) + return; + + if (blobmsg_check_array(attr, BLOBMSG_TYPE_TABLE) < 0) + return; + + blobmsg_for_each_attr(cur, attr, rem) + blobmsg_add_blob(&b, cur); +} + +struct blob_attr *unetd_ubus_get_network_addr_list(const char *name) +{ + char *objname; + uint32_t id; + size_t len; + + if (strlen(name) > 64) + return NULL; + + len = sizeof("network.interface.") + strlen(name) + 1; + objname = alloca(len); + snprintf(objname, len, "network.interface.%s", name); + + if (ubus_lookup_id(&conn.ctx, objname, &id)) + return NULL; + + blob_buf_init(&b, 0); + ubus_invoke(&conn.ctx, id, "status", b.head, ubus_network_status_cb, NULL, 10000); + + return b.head; +} + void unetd_ubus_netifd_add_route(struct network *net, union network_endpoint *ep) { uint32_t id; @@ -543,8 +586,25 @@ void unetd_ubus_netifd_add_route(struct network *net, union network_endpoint *ep ubus_invoke(&conn.ctx, id, "add_host_route", b.head, NULL, NULL, -1); } +static int +unetd_netifd_sub_cb(struct ubus_context *ctx, struct ubus_object *obj, + struct ubus_request_data *req, + const char *method, struct blob_attr *msg) +{ + network_pex_reload(); + return 0; +} + +static bool +unetd_new_object_sub_cb(struct ubus_context *ctx, struct ubus_subscriber *sub, const char *path) +{ + return path && !strcmp(path, "network.interface"); +} + void unetd_ubus_init(void) { + sub.cb = unetd_netifd_sub_cb; + sub.new_obj_cb = unetd_new_object_sub_cb; conn.cb = ubus_connect_handler; ubus_auto_connect(&conn); } @@ -11,6 +11,7 @@ void unetd_ubus_notify(const char *type, struct blob_attr *data); void unetd_ubus_network_notify(struct network *net); void unetd_ubus_netifd_update(struct blob_attr *data); void unetd_ubus_netifd_add_route(struct network *net, union network_endpoint *ep); +struct blob_attr *unetd_ubus_get_network_addr_list(const char *name); #else static inline void unetd_ubus_init(void) { @@ -27,6 +28,10 @@ static inline void unetd_ubus_netifd_update(struct blob_attr *data) static inline void unetd_ubus_netifd_add_route(struct network *net, union network_endpoint *ep) { } +static inline struct blob_attr *unetd_ubus_get_network_addr_list(const char *name) +{ + return NULL; +} #endif #endif |