mirror of
https://github.com/Telecominfraproject/wlan-ap.git
synced 2025-10-29 17:42:41 +00:00
254 lines
5.9 KiB
C
254 lines
5.9 KiB
C
/*
|
|
* Copyright (C) 2020 John Crispin <john@phrozen.org>
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU Lesser General Public License version 2.1
|
|
* as published by the Free Software Foundation
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*/
|
|
|
|
#include "udevmand.h"
|
|
|
|
static struct ubus_auto_conn conn;
|
|
static struct ubus_subscriber subscriber;
|
|
|
|
enum {
|
|
EVENT_ID,
|
|
EVENT_PATH,
|
|
__EVENT_MAX
|
|
};
|
|
|
|
static const struct blobmsg_policy status_policy[__EVENT_MAX] = {
|
|
[EVENT_ID] = { .name = "id", .type = BLOBMSG_TYPE_INT32 },
|
|
[EVENT_PATH] = { .name = "path", .type = BLOBMSG_TYPE_STRING },
|
|
};
|
|
|
|
static const struct ubus_watch_list {
|
|
const char *path;
|
|
int wildcard;
|
|
} ubus_watch_list[] = {
|
|
{
|
|
.path = "service",
|
|
}, {
|
|
.path = "dnsmasq",
|
|
}, {
|
|
.path = "network.interface",
|
|
}, {
|
|
.path = "network.status",
|
|
},
|
|
};
|
|
|
|
static int
|
|
ubus_mac_cb(struct ubus_context *ctx, struct ubus_object *obj,
|
|
struct ubus_request_data *req, const char *method,
|
|
struct blob_attr *msg)
|
|
{
|
|
if (!mac_dump_all())
|
|
ubus_send_reply(ctx, req, b.head);
|
|
return UBUS_STATUS_OK;
|
|
}
|
|
|
|
/*static int
|
|
ubus_interface_cb(struct ubus_context *ctx, struct ubus_object *obj,
|
|
struct ubus_request_data *req, const char *method,
|
|
struct blob_attr *msg)
|
|
{
|
|
if (!interface_dump())
|
|
ubus_send_reply(ctx, req, b.head);
|
|
return UBUS_STATUS_OK;
|
|
}*/
|
|
|
|
static int
|
|
ubus_port_cb(struct ubus_context *ctx, struct ubus_object *obj,
|
|
struct ubus_request_data *req, const char *method,
|
|
struct blob_attr *msg)
|
|
{
|
|
enum {
|
|
DUMP_DELTA,
|
|
__DUMP_MAX
|
|
};
|
|
|
|
static const struct blobmsg_policy dump_policy[__DUMP_MAX] = {
|
|
[DUMP_DELTA] = { .name = "delta", .type = BLOBMSG_TYPE_INT32 },
|
|
};
|
|
|
|
struct blob_attr *tb[__DUMP_MAX];
|
|
int delta = 0;
|
|
|
|
blobmsg_parse(dump_policy, __DUMP_MAX, tb, blob_data(msg), blob_len(msg));
|
|
|
|
if (tb[DUMP_DELTA])
|
|
delta = blobmsg_get_u32(tb[DUMP_DELTA]);
|
|
|
|
iface_dump(delta);
|
|
ubus_send_reply(ctx, req, b.head);
|
|
|
|
return UBUS_STATUS_OK;
|
|
}
|
|
|
|
static const struct ubus_method topology_methods[] = {
|
|
//UBUS_METHOD_NOARG("interface", ubus_interface_cb),
|
|
UBUS_METHOD_NOARG("mac", ubus_mac_cb),
|
|
UBUS_METHOD_NOARG("port", ubus_port_cb),
|
|
};
|
|
|
|
static struct ubus_object_type ubus_object_type =
|
|
UBUS_OBJECT_TYPE("topology", topology_methods);
|
|
|
|
static struct ubus_object ubus_object = {
|
|
.name = "topology",
|
|
.type = &ubus_object_type,
|
|
.methods = topology_methods,
|
|
.n_methods = ARRAY_SIZE(topology_methods),
|
|
};
|
|
|
|
static int
|
|
ubus_watch_match(const char *path)
|
|
{
|
|
int i;
|
|
|
|
for (i = 0; i < ARRAY_SIZE(ubus_watch_list); i++) {
|
|
int len = strlen(ubus_watch_list[i].path);
|
|
|
|
if (ubus_watch_list[i].wildcard && strncmp(path, ubus_watch_list[i].path, len))
|
|
continue;
|
|
if (!ubus_watch_list[i].wildcard && strcmp(path, ubus_watch_list[i].path))
|
|
continue;
|
|
return 0;
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
enum {
|
|
INTERFACE,
|
|
__INTERFACE_MAX,
|
|
};
|
|
|
|
static const struct blobmsg_policy interface_policy[__INTERFACE_MAX] = {
|
|
[INTERFACE] = { .name = "interface", .type = BLOBMSG_TYPE_ARRAY },
|
|
};
|
|
|
|
static void
|
|
ubus_netifd_dump_cb(struct ubus_request *req,
|
|
int type, struct blob_attr *msg)
|
|
{
|
|
struct blob_attr *tb[__INTERFACE_MAX];
|
|
struct blob_attr *iter;
|
|
int rem;
|
|
|
|
blobmsg_parse(interface_policy, __INTERFACE_MAX, tb, blob_data(msg), blob_len(msg));
|
|
if (!tb[INTERFACE])
|
|
return;
|
|
blobmsg_for_each_attr(iter, tb[INTERFACE], rem)
|
|
interface_update(iter, 0);
|
|
}
|
|
|
|
static int
|
|
ubus_notify_cb(struct ubus_context *ctx, struct ubus_object *obj,
|
|
struct ubus_request_data *req, const char *method,
|
|
struct blob_attr *msg)
|
|
{
|
|
if (0) {
|
|
char *str;
|
|
|
|
str = blobmsg_format_json(msg, true);
|
|
ULOG_INFO("Received ubus notify '%s': %s\n", method, str);
|
|
free(str);
|
|
}
|
|
|
|
if (!strcmp(method, "dhcp.ack"))
|
|
dhcpv4_ack(msg);
|
|
|
|
else if (!strcmp(method, "dhcp.release"))
|
|
dhcpv4_release(msg);
|
|
|
|
else if (!strcmp(method, "interface.update"))
|
|
interface_update(msg, 1);
|
|
|
|
else if (!strcmp(method, "interface.down"))
|
|
interface_down(msg);
|
|
|
|
return 0;
|
|
}
|
|
|
|
static void
|
|
ubus_event_handler_cb(struct ubus_context *ctx, struct ubus_event_handler *ev,
|
|
const char *type, struct blob_attr *msg)
|
|
{
|
|
struct blob_attr *tb[__EVENT_MAX];
|
|
const char *path;
|
|
uint32_t id;
|
|
|
|
if (strcmp("ubus.object.add", type))
|
|
return;
|
|
|
|
if (0) {
|
|
char *str;
|
|
|
|
str = blobmsg_format_json(msg, true);
|
|
ULOG_INFO("Received ubus notify '%s': %s\n", type, str);
|
|
free(str);
|
|
}
|
|
|
|
blobmsg_parse(status_policy, __EVENT_MAX, tb, blob_data(msg), blob_len(msg));
|
|
|
|
if (!tb[EVENT_ID] || !tb[EVENT_PATH])
|
|
return;
|
|
|
|
path = blobmsg_get_string(tb[EVENT_PATH]);
|
|
id = blobmsg_get_u32(tb[EVENT_ID]);
|
|
|
|
if (!ubus_watch_match(path) && !ubus_subscribe(ctx, &subscriber, id))
|
|
ULOG_INFO("Subscribe to %s (%u)\n", path, id);
|
|
}
|
|
|
|
static struct ubus_event_handler ubus_event_handler = { .cb = ubus_event_handler_cb };
|
|
|
|
static void
|
|
receive_list_result(struct ubus_context *ctx, struct ubus_object_data *obj,
|
|
void *priv)
|
|
{
|
|
char *path = strdup(obj->path);
|
|
|
|
if (!ubus_watch_match(path) && !ubus_subscribe(ctx, &subscriber, obj->id))
|
|
ULOG_INFO("Subscribe to %s (%u)\n", path, obj->id);
|
|
free(path);
|
|
}
|
|
|
|
static void
|
|
ubus_connect_handler(struct ubus_context *ctx)
|
|
{
|
|
uint32_t netifd;
|
|
|
|
ubus_add_object(ctx, &ubus_object);
|
|
|
|
ubus_register_event_handler(ctx, &ubus_event_handler, "ubus.object.add");
|
|
ubus_register_event_handler(ctx, &ubus_event_handler, "ubus.object.remove");
|
|
|
|
subscriber.cb = ubus_notify_cb;
|
|
if (ubus_register_subscriber(ctx, &subscriber))
|
|
ULOG_ERR("failed to register ubus subscriber\n");
|
|
|
|
ubus_lookup(ctx, NULL, receive_list_result, NULL);
|
|
|
|
if (!ubus_lookup_id(ctx, "network.interface", &netifd))
|
|
ubus_invoke(ctx, netifd, "dump", NULL, ubus_netifd_dump_cb, NULL, 5000);
|
|
}
|
|
|
|
void
|
|
ubus_init(void)
|
|
{
|
|
conn.cb = ubus_connect_handler;
|
|
ubus_auto_connect(&conn);
|
|
}
|
|
|
|
void
|
|
ubus_uninit(void)
|
|
{
|
|
ubus_auto_shutdown(&conn);
|
|
}
|