[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 },
};
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;
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;
NETWORK_ATTR_KEEPALIVE,
NETWORK_ATTR_DOMAIN,
NETWORK_ATTR_TUNNELS,
+ NETWORK_ATTR_LOCAL_NET,
NETWORK_ATTR_AUTH_CONNECT,
NETWORK_ATTR_PEER_DATA,
__NETWORK_ATTR_MAX,
}
}
-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;
out:
if (timeout && (new_host || host->timeout))
host->timeout = timeout + unet_gettime();
+ return host;
}
static void
}
+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;
int fd;
network_pex_open_auth_connect(net);
+ __network_pex_reload(net);
if (!local_host || !local_host->peer.pex_port)
return 0;
uint64_t timeout;
uint64_t last_active;
uint64_t last_ping;
+ bool interface;
union network_endpoint endpoint;
};
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);
#include "enroll.h"
static struct ubus_auto_conn conn;
+static struct ubus_subscriber sub;
static struct blob_buf b;
static int
{
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));
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;
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);
}
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)
{
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