mirror of
https://github.com/berlin-open-wireless-lab/DAWN.git
synced 2025-03-09 15:40:12 +00:00
Merge branch 'refactor/hostapd_bindings'
This commit is contained in:
commit
53605593d2
1 changed files with 210 additions and 181 deletions
383
src/utils/ubus.c
383
src/utils/ubus.c
|
@ -57,9 +57,12 @@ struct uloop_timeout channel_utilization_timer = {
|
||||||
#define MAX_HOSTAPD_SOCKETS 10
|
#define MAX_HOSTAPD_SOCKETS 10
|
||||||
#define MAX_INTERFACE_NAME 64
|
#define MAX_INTERFACE_NAME 64
|
||||||
|
|
||||||
struct hostapd_sock_entry{
|
LIST_HEAD(hostapd_sock_list);
|
||||||
|
|
||||||
|
struct hostapd_sock_entry {
|
||||||
|
struct list_head list;
|
||||||
|
|
||||||
uint32_t id;
|
uint32_t id;
|
||||||
uint32_t obj_id;
|
|
||||||
char iface_name[MAX_INTERFACE_NAME];
|
char iface_name[MAX_INTERFACE_NAME];
|
||||||
uint8_t bssid_addr[ETH_ALEN];
|
uint8_t bssid_addr[ETH_ALEN];
|
||||||
char ssid[SSID_MAX_LEN];
|
char ssid[SSID_MAX_LEN];
|
||||||
|
@ -71,6 +74,8 @@ struct hostapd_sock_entry{
|
||||||
int chan_util_num_sample_periods;
|
int chan_util_num_sample_periods;
|
||||||
int chan_util_average;
|
int chan_util_average;
|
||||||
struct ubus_subscriber subscriber;
|
struct ubus_subscriber subscriber;
|
||||||
|
struct ubus_event_handler wait_handler;
|
||||||
|
bool subscribed;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct hostapd_sock_entry* hostapd_sock_arr[MAX_HOSTAPD_SOCKETS];
|
struct hostapd_sock_entry* hostapd_sock_arr[MAX_HOSTAPD_SOCKETS];
|
||||||
|
@ -213,15 +218,10 @@ static const struct blobmsg_policy dawn_umdns_policy[__DAWN_UMDNS_MAX] = {
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Function Definitions */
|
/* Function Definitions */
|
||||||
static void hostapd_handle_remove(struct ubus_context *ctx,
|
|
||||||
struct ubus_subscriber *s, uint32_t id);
|
|
||||||
|
|
||||||
static int hostapd_notify(struct ubus_context *ctx, struct ubus_object *obj,
|
static int hostapd_notify(struct ubus_context *ctx, struct ubus_object *obj,
|
||||||
struct ubus_request_data *req, const char *method,
|
struct ubus_request_data *req, const char *method,
|
||||||
struct blob_attr *msg);
|
struct blob_attr *msg);
|
||||||
|
|
||||||
static int add_subscriber(char *name);
|
|
||||||
|
|
||||||
static int ubus_get_clients();
|
static int ubus_get_clients();
|
||||||
|
|
||||||
static int
|
static int
|
||||||
|
@ -245,89 +245,25 @@ static int handle_set_probe(struct blob_attr *msg);
|
||||||
|
|
||||||
static int parse_add_mac_to_file(struct blob_attr *msg);
|
static int parse_add_mac_to_file(struct blob_attr *msg);
|
||||||
|
|
||||||
int hostapd_array_check_id(uint32_t id);
|
|
||||||
|
|
||||||
void hostapd_array_insert(struct hostapd_sock_entry* entry);
|
|
||||||
|
|
||||||
struct hostapd_sock_entry* hostapd_array_get_entry(uint32_t id);
|
|
||||||
|
|
||||||
struct hostapd_sock_entry* hostapd_array_get_entry_by_object_id(uint32_t id);
|
|
||||||
|
|
||||||
void hostapd_array_delete(uint32_t id);
|
|
||||||
|
|
||||||
static void ubus_add_oject();
|
static void ubus_add_oject();
|
||||||
|
|
||||||
static void respond_to_notify(uint32_t id);
|
static void respond_to_notify(uint32_t id);
|
||||||
|
|
||||||
int handle_uci_config(struct blob_attr *msg);
|
int handle_uci_config(struct blob_attr *msg);
|
||||||
|
|
||||||
|
void subscribe_to_new_interfaces(const char *hostapd_sock_path);
|
||||||
|
|
||||||
|
bool subscriber_to_interface(const char *ifname);
|
||||||
|
|
||||||
|
bool subscribe(struct hostapd_sock_entry *hostapd_entry);
|
||||||
|
|
||||||
void add_client_update_timer(time_t time) {
|
void add_client_update_timer(time_t time) {
|
||||||
uloop_timeout_set(&client_timer, time);
|
uloop_timeout_set(&client_timer, time);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct hostapd_sock_entry* hostapd_array_get_entry_by_object_id(uint32_t id) {
|
static inline int
|
||||||
for (int i = 0; i <= hostapd_sock_last; i++) {
|
subscription_wait(struct ubus_event_handler *handler) {
|
||||||
if (hostapd_sock_arr[i]->subscriber.obj.id == id) {
|
return ubus_register_event_handler(ctx, handler, "ubus.object.add");
|
||||||
return hostapd_sock_arr[i];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct hostapd_sock_entry* hostapd_array_get_entry(uint32_t id) {
|
|
||||||
for (int i = 0; i <= hostapd_sock_last; i++) {
|
|
||||||
if (hostapd_sock_arr[i]->id == id) {
|
|
||||||
return hostapd_sock_arr[i];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
int hostapd_array_check_id(uint32_t id) {
|
|
||||||
for (int i = 0; i <= hostapd_sock_last; i++) {
|
|
||||||
if (hostapd_sock_arr[i]->id == id) {
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void hostapd_array_insert(struct hostapd_sock_entry* entry) {
|
|
||||||
if (hostapd_sock_last < MAX_HOSTAPD_SOCKETS) {
|
|
||||||
hostapd_sock_last++;
|
|
||||||
hostapd_sock_arr[hostapd_sock_last] = entry;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int i = 0; i <= hostapd_sock_last; i++) {
|
|
||||||
printf("%d: %d\n", i, hostapd_sock_arr[i]->id);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void hostapd_array_delete(uint32_t id) {
|
|
||||||
int i = 0;
|
|
||||||
int found_in_array = 0;
|
|
||||||
|
|
||||||
if (hostapd_sock_last == -1) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i = 0; i <= hostapd_sock_last; i++) {
|
|
||||||
if (hostapd_sock_arr[i]->id == id) {
|
|
||||||
found_in_array = 1;
|
|
||||||
|
|
||||||
// in thisfunction we are freeing the struct
|
|
||||||
free(hostapd_sock_arr[i]);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int j = i; j <= hostapd_sock_last; j++) {
|
|
||||||
hostapd_sock_arr[j] = hostapd_sock_arr[j + 1];
|
|
||||||
}
|
|
||||||
|
|
||||||
if (hostapd_sock_last > -1 && found_in_array) {
|
|
||||||
hostapd_sock_last--;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void blobmsg_add_macaddr(struct blob_buf *buf, const char *name, const uint8_t *addr) {
|
void blobmsg_add_macaddr(struct blob_buf *buf, const char *name, const uint8_t *addr) {
|
||||||
|
@ -338,7 +274,6 @@ void blobmsg_add_macaddr(struct blob_buf *buf, const char *name, const uint8_t *
|
||||||
blobmsg_add_string_buffer(buf);
|
blobmsg_add_string_buffer(buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static int decide_function(probe_entry *prob_req, int req_type) {
|
static int decide_function(probe_entry *prob_req, int req_type) {
|
||||||
if (mac_in_maclist(prob_req->client_addr)) {
|
if (mac_in_maclist(prob_req->client_addr)) {
|
||||||
return 1;
|
return 1;
|
||||||
|
@ -367,18 +302,6 @@ static int decide_function(probe_entry *prob_req, int req_type) {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void hostapd_handle_remove(struct ubus_context *ctx,
|
|
||||||
struct ubus_subscriber *s, uint32_t id) {
|
|
||||||
int ret;
|
|
||||||
fprintf(stderr, "Object %08x went away\n", id);
|
|
||||||
ret= ubus_unsubscribe(ctx, s, id);
|
|
||||||
if (ret)
|
|
||||||
fprintf(stderr, "Removing object %08x: %s\n", id, ubus_strerror(ret));
|
|
||||||
|
|
||||||
hostapd_array_delete(id);
|
|
||||||
}
|
|
||||||
|
|
||||||
int parse_to_hostapd_notify(struct blob_attr *msg, hostapd_notify_entry *notify_req) {
|
int parse_to_hostapd_notify(struct blob_attr *msg, hostapd_notify_entry *notify_req) {
|
||||||
struct blob_attr *tb[__HOSTAPD_NOTIFY_MAX];
|
struct blob_attr *tb[__HOSTAPD_NOTIFY_MAX];
|
||||||
|
|
||||||
|
@ -713,73 +636,6 @@ static int hostapd_notify(struct ubus_context *ctx, struct ubus_object *obj,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int add_subscriber(char *name) {
|
|
||||||
|
|
||||||
char subscribe_name[300];
|
|
||||||
int ret;
|
|
||||||
struct hostapd_sock_entry *hostapd_entry;
|
|
||||||
uint32_t id = 0;
|
|
||||||
|
|
||||||
sprintf(subscribe_name, "hostapd.%s", name);
|
|
||||||
|
|
||||||
if (ubus_lookup_id(ctx, subscribe_name, &id)) {
|
|
||||||
fprintf(stderr, "Failed to look up test object for %s\n", subscribe_name);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(hostapd_array_check_id(id))
|
|
||||||
{
|
|
||||||
// entry already existing
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
hostapd_entry = calloc(1, sizeof(struct hostapd_sock_entry));
|
|
||||||
hostapd_entry->id = id;
|
|
||||||
hostapd_entry->subscriber.remove_cb = hostapd_handle_remove;
|
|
||||||
hostapd_entry->subscriber.cb = hostapd_notify;
|
|
||||||
|
|
||||||
strcpy(hostapd_entry->iface_name, name);
|
|
||||||
get_bssid(name, hostapd_entry->bssid_addr);
|
|
||||||
get_ssid(name, hostapd_entry->ssid);
|
|
||||||
|
|
||||||
// TODO: here we need to add ht and vht supported!!!
|
|
||||||
// actually we wanted to use an ubus call but for now we can use libiwinfo
|
|
||||||
hostapd_entry->ht_support = (uint8_t) support_ht(name);
|
|
||||||
hostapd_entry->vht_support = (uint8_t) support_vht(name);
|
|
||||||
|
|
||||||
ret = ubus_register_subscriber(ctx, &hostapd_entry->subscriber);
|
|
||||||
ret = ubus_subscribe( ctx, &hostapd_entry->subscriber, id);
|
|
||||||
|
|
||||||
hostapd_array_insert(hostapd_entry);
|
|
||||||
fprintf(stderr, "Watching object %08x: %s\n", id, ubus_strerror(ret));
|
|
||||||
|
|
||||||
respond_to_notify(id);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int subscribe_to_hostapd_interfaces(const char *hostapd_dir) {
|
|
||||||
DIR *dirp;
|
|
||||||
struct dirent *entry;
|
|
||||||
|
|
||||||
if (ctx == NULL) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
dirp = opendir(hostapd_dir); // error handling?
|
|
||||||
if (!dirp) {
|
|
||||||
fprintf(stderr, "[SUBSCRIBING] No hostapd sockets!\n");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
while ((entry = readdir(dirp)) != NULL) {
|
|
||||||
if (entry->d_type == DT_SOCK) {
|
|
||||||
add_subscriber(entry->d_name);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
closedir(dirp);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int dawn_init_ubus(const char *ubus_socket, const char *hostapd_dir) {
|
int dawn_init_ubus(const char *ubus_socket, const char *hostapd_dir) {
|
||||||
uloop_init();
|
uloop_init();
|
||||||
signal(SIGPIPE, SIG_IGN);
|
signal(SIGPIPE, SIG_IGN);
|
||||||
|
@ -816,7 +672,7 @@ int dawn_init_ubus(const char *ubus_socket, const char *hostapd_dir) {
|
||||||
if (network_config.network_option == 2)
|
if (network_config.network_option == 2)
|
||||||
run_server(network_config.tcp_port);
|
run_server(network_config.tcp_port);
|
||||||
|
|
||||||
subscribe_to_hostapd_interfaces(hostapd_dir_glob);
|
subscribe_to_new_interfaces(hostapd_dir_glob);
|
||||||
|
|
||||||
uloop_run();
|
uloop_run();
|
||||||
|
|
||||||
|
@ -977,6 +833,7 @@ int parse_to_clients(struct blob_attr *msg, int do_kick, uint32_t id) {
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ubus_get_clients_cb(struct ubus_request *req, int type, struct blob_attr *msg) {
|
static void ubus_get_clients_cb(struct ubus_request *req, int type, struct blob_attr *msg) {
|
||||||
|
struct hostapd_sock_entry *sub, *entry = NULL;
|
||||||
|
|
||||||
if (!msg)
|
if (!msg)
|
||||||
return;
|
return;
|
||||||
|
@ -987,10 +844,20 @@ static void ubus_get_clients_cb(struct ubus_request *req, int type, struct blob_
|
||||||
blobmsg_add_u32(&b_domain, "collision_domain", network_config.collision_domain);
|
blobmsg_add_u32(&b_domain, "collision_domain", network_config.collision_domain);
|
||||||
blobmsg_add_u32(&b_domain, "bandwidth", network_config.bandwidth);
|
blobmsg_add_u32(&b_domain, "bandwidth", network_config.bandwidth);
|
||||||
|
|
||||||
struct hostapd_sock_entry *entry = hostapd_array_get_entry(req->peer);
|
list_for_each_entry(sub, &hostapd_sock_list, list)
|
||||||
if(entry->id != req->peer)
|
|
||||||
{
|
{
|
||||||
fprintf(stderr, "Failed to find hostapd sock entry in callback with id %d\n", req->peer);
|
if (sub->id == req->peer) {
|
||||||
|
entry = sub;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (entry == NULL) {
|
||||||
|
fprintf(stderr, "Failed to find interface!\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!entry->subscribed) {
|
||||||
|
fprintf(stderr, "Interface %s is not subscribed!\n", entry->iface_name);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1009,13 +876,19 @@ static void ubus_get_clients_cb(struct ubus_request *req, int type, struct blob_
|
||||||
print_ap_array();
|
print_ap_array();
|
||||||
|
|
||||||
free(data_str);
|
free(data_str);
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int ubus_get_clients() {
|
static int ubus_get_clients() {
|
||||||
int timeout = 1;
|
int timeout = 1;
|
||||||
for (int i = 0; i <= hostapd_sock_last; i++) {
|
struct hostapd_sock_entry *sub;
|
||||||
|
list_for_each_entry(sub, &hostapd_sock_list, list)
|
||||||
|
{
|
||||||
|
if (sub->subscribed) {
|
||||||
blob_buf_init(&b_clients, 0);
|
blob_buf_init(&b_clients, 0);
|
||||||
ubus_invoke(ctx, hostapd_sock_arr[i]->id, "get_clients", b_clients.head, ubus_get_clients_cb, NULL, timeout * 1000);
|
ubus_invoke(ctx, sub->id, "get_clients", b_clients.head, ubus_get_clients_cb, NULL, timeout * 1000);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -1027,16 +900,21 @@ void update_clients(struct uloop_timeout *t) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void update_channel_utilization(struct uloop_timeout *t) {
|
void update_channel_utilization(struct uloop_timeout *t) {
|
||||||
for (int i = 0; i <= hostapd_sock_last; i++) {
|
struct hostapd_sock_entry *sub;
|
||||||
|
|
||||||
hostapd_sock_arr[i]->chan_util_samples_sum += get_channel_utilization(hostapd_sock_arr[i]->iface_name, &hostapd_sock_arr[i]->last_channel_time, &hostapd_sock_arr[i]->last_channel_time_busy);
|
list_for_each_entry(sub, &hostapd_sock_list, list)
|
||||||
hostapd_sock_arr[i]->chan_util_num_sample_periods++;
|
|
||||||
|
|
||||||
if(hostapd_sock_arr[i]->chan_util_num_sample_periods > dawn_metric.chan_util_avg_period)
|
|
||||||
{
|
{
|
||||||
hostapd_sock_arr[i]->chan_util_average = hostapd_sock_arr[i]->chan_util_samples_sum / hostapd_sock_arr[i]->chan_util_num_sample_periods;
|
|
||||||
hostapd_sock_arr[i]->chan_util_samples_sum = 0;
|
if (sub->subscribed) {
|
||||||
hostapd_sock_arr[i]->chan_util_num_sample_periods = 0;
|
sub->chan_util_samples_sum += get_channel_utilization(sub->iface_name, &sub->last_channel_time,
|
||||||
|
&sub->last_channel_time_busy);
|
||||||
|
sub->chan_util_num_sample_periods++;
|
||||||
|
|
||||||
|
if (sub->chan_util_num_sample_periods > dawn_metric.chan_util_avg_period) {
|
||||||
|
sub->chan_util_average = sub->chan_util_samples_sum / sub->chan_util_num_sample_periods;
|
||||||
|
sub->chan_util_samples_sum = 0;
|
||||||
|
sub->chan_util_num_sample_periods = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
uloop_timeout_set(&channel_utilization_timer, timeout_config.update_chan_util * 1000);
|
uloop_timeout_set(&channel_utilization_timer, timeout_config.update_chan_util * 1000);
|
||||||
|
@ -1053,24 +931,30 @@ void start_umdns_update() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void update_hostapd_sockets(struct uloop_timeout *t) {
|
void update_hostapd_sockets(struct uloop_timeout *t) {
|
||||||
subscribe_to_hostapd_interfaces(hostapd_dir_glob);
|
subscribe_to_new_interfaces(hostapd_dir_glob);
|
||||||
uloop_timeout_set(&hostapd_timer, timeout_config.update_hostapd * 1000);
|
uloop_timeout_set(&hostapd_timer, timeout_config.update_hostapd * 1000);
|
||||||
}
|
}
|
||||||
|
|
||||||
void del_client_all_interfaces(const uint8_t *client_addr, uint32_t reason, uint8_t deauth, uint32_t ban_time) {
|
void del_client_all_interfaces(const uint8_t *client_addr, uint32_t reason, uint8_t deauth, uint32_t ban_time) {
|
||||||
|
struct hostapd_sock_entry *sub;
|
||||||
|
|
||||||
blob_buf_init(&b, 0);
|
blob_buf_init(&b, 0);
|
||||||
blobmsg_add_macaddr(&b, "addr", client_addr);
|
blobmsg_add_macaddr(&b, "addr", client_addr);
|
||||||
blobmsg_add_u32(&b, "reason", reason);
|
blobmsg_add_u32(&b, "reason", reason);
|
||||||
blobmsg_add_u8(&b, "deauth", deauth);
|
blobmsg_add_u8(&b, "deauth", deauth);
|
||||||
blobmsg_add_u32(&b, "ban_time", ban_time);
|
blobmsg_add_u32(&b, "ban_time", ban_time);
|
||||||
|
|
||||||
for (int i = 0; i <= hostapd_sock_last; i++) {
|
list_for_each_entry(sub, &hostapd_sock_list, list)
|
||||||
|
{
|
||||||
|
if (sub->subscribed) {
|
||||||
int timeout = 1;
|
int timeout = 1;
|
||||||
ubus_invoke(ctx, hostapd_sock_arr[i]->id, "del_client", b.head, NULL, NULL, timeout * 1000);
|
ubus_invoke(ctx, sub->id, "del_client", b.head, NULL, NULL, timeout * 1000);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void del_client_interface(uint32_t id, const uint8_t *client_addr, uint32_t reason, uint8_t deauth, uint32_t ban_time) {
|
void del_client_interface(uint32_t id, const uint8_t *client_addr, uint32_t reason, uint8_t deauth, uint32_t ban_time) {
|
||||||
|
struct hostapd_sock_entry *sub;
|
||||||
|
|
||||||
blob_buf_init(&b, 0);
|
blob_buf_init(&b, 0);
|
||||||
blobmsg_add_macaddr(&b, "addr", client_addr);
|
blobmsg_add_macaddr(&b, "addr", client_addr);
|
||||||
|
@ -1078,8 +962,15 @@ void del_client_interface(uint32_t id, const uint8_t *client_addr, uint32_t reas
|
||||||
blobmsg_add_u8(&b, "deauth", deauth);
|
blobmsg_add_u8(&b, "deauth", deauth);
|
||||||
blobmsg_add_u32(&b, "ban_time", ban_time);
|
blobmsg_add_u32(&b, "ban_time", ban_time);
|
||||||
|
|
||||||
|
|
||||||
|
list_for_each_entry(sub, &hostapd_sock_list, list)
|
||||||
|
{
|
||||||
|
if (sub->subscribed) {
|
||||||
int timeout = 1;
|
int timeout = 1;
|
||||||
ubus_invoke(ctx, id, "del_client", b.head, NULL, NULL, timeout * 1000);
|
ubus_invoke(ctx, id, "del_client", b.head, NULL, NULL, timeout * 1000);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ubus_umdns_cb(struct ubus_request *req, int type, struct blob_attr *msg) {
|
static void ubus_umdns_cb(struct ubus_request *req, int type, struct blob_attr *msg) {
|
||||||
|
@ -1293,6 +1184,144 @@ static void respond_to_notify(uint32_t id) {
|
||||||
fprintf(stderr, "Failed to invoke: %s\n", ubus_strerror(ret));
|
fprintf(stderr, "Failed to invoke: %s\n", ubus_strerror(ret));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void hostapd_handle_remove(struct ubus_context *ctx,
|
||||||
|
struct ubus_subscriber *s, uint32_t id) {
|
||||||
|
fprintf(stdout, "Object %08x went away\n", id);
|
||||||
|
struct hostapd_sock_entry *hostapd_sock = container_of(s,
|
||||||
|
struct hostapd_sock_entry, subscriber);
|
||||||
|
|
||||||
|
if (hostapd_sock->id != id) {
|
||||||
|
printf("ID NOT THE SAME!\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
hostapd_sock->subscribed = false;
|
||||||
|
subscription_wait(&hostapd_sock->wait_handler);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
bool subscribe(struct hostapd_sock_entry *hostapd_entry) {
|
||||||
|
char subscribe_name[sizeof("hostapd.") + MAX_INTERFACE_NAME + 1];
|
||||||
|
|
||||||
|
if (hostapd_entry->subscribed)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
sprintf(subscribe_name, "hostapd.%s", hostapd_entry->iface_name);
|
||||||
|
|
||||||
|
if (ubus_lookup_id(ctx, subscribe_name, &hostapd_entry->id)) {
|
||||||
|
fprintf(stdout, "Failed to lookup ID!");
|
||||||
|
subscription_wait(&hostapd_entry->wait_handler);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ubus_subscribe(ctx, &hostapd_entry->subscriber, hostapd_entry->id)) {
|
||||||
|
fprintf(stdout, "Failed to register subscriber!");
|
||||||
|
subscription_wait(&hostapd_entry->wait_handler);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
hostapd_entry->subscribed = true;
|
||||||
|
|
||||||
|
get_bssid(hostapd_entry->iface_name, hostapd_entry->bssid_addr);
|
||||||
|
get_ssid(hostapd_entry->iface_name, hostapd_entry->ssid);
|
||||||
|
|
||||||
|
hostapd_entry->ht_support = (uint8_t) support_ht(hostapd_entry->iface_name);
|
||||||
|
hostapd_entry->vht_support = (uint8_t) support_vht(hostapd_entry->iface_name);
|
||||||
|
|
||||||
|
respond_to_notify(hostapd_entry->id);
|
||||||
|
|
||||||
|
printf("Subscribed to: %s\n", hostapd_entry->iface_name);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
wait_cb(struct ubus_context *ctx, struct ubus_event_handler *ev_handler,
|
||||||
|
const char *type, struct blob_attr *msg) {
|
||||||
|
static const struct blobmsg_policy wait_policy = {
|
||||||
|
"path", BLOBMSG_TYPE_STRING
|
||||||
|
};
|
||||||
|
|
||||||
|
struct blob_attr *attr;
|
||||||
|
const char *path;
|
||||||
|
struct hostapd_sock_entry *sub = container_of(ev_handler,
|
||||||
|
struct hostapd_sock_entry, wait_handler);
|
||||||
|
|
||||||
|
if (strcmp(type, "ubus.object.add"))
|
||||||
|
return;
|
||||||
|
|
||||||
|
blobmsg_parse(&wait_policy, 1, &attr, blob_data(msg), blob_len(msg));
|
||||||
|
if (!attr)
|
||||||
|
return;
|
||||||
|
|
||||||
|
path = blobmsg_data(attr);
|
||||||
|
|
||||||
|
path = strchr(path, '.');
|
||||||
|
if (!path)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (strcmp(sub->iface_name, path + 1))
|
||||||
|
return;
|
||||||
|
|
||||||
|
subscribe(sub);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool subscriber_to_interface(const char *ifname) {
|
||||||
|
|
||||||
|
struct hostapd_sock_entry *hostapd_entry;
|
||||||
|
|
||||||
|
hostapd_entry = calloc(1, sizeof(struct hostapd_sock_entry));
|
||||||
|
strcpy(hostapd_entry->iface_name, ifname);
|
||||||
|
hostapd_entry->subscriber.cb = hostapd_notify;
|
||||||
|
hostapd_entry->subscriber.remove_cb = hostapd_handle_remove;
|
||||||
|
hostapd_entry->wait_handler.cb = wait_cb;
|
||||||
|
|
||||||
|
hostapd_entry->subscribed = false;
|
||||||
|
|
||||||
|
if (ubus_register_subscriber(ctx, &hostapd_entry->subscriber)) {
|
||||||
|
fprintf(stderr, "Failed to register subscriber!");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
list_add(&hostapd_entry->list, &hostapd_sock_list);
|
||||||
|
|
||||||
|
return subscribe(hostapd_entry);
|
||||||
|
}
|
||||||
|
|
||||||
|
void subscribe_to_new_interfaces(const char *hostapd_sock_path) {
|
||||||
|
DIR *dirp;
|
||||||
|
struct dirent *entry;
|
||||||
|
struct hostapd_sock_entry *sub = NULL;
|
||||||
|
|
||||||
|
if (ctx == NULL) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
dirp = opendir(hostapd_sock_path); // error handling?
|
||||||
|
if (!dirp) {
|
||||||
|
fprintf(stderr, "[SUBSCRIBING] No hostapd sockets!\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
while ((entry = readdir(dirp)) != NULL) {
|
||||||
|
if (entry->d_type == DT_SOCK) {
|
||||||
|
bool do_subscribe = true;
|
||||||
|
list_for_each_entry(sub, &hostapd_sock_list, list)
|
||||||
|
{
|
||||||
|
if (strncmp(sub->iface_name, entry->d_name, MAX_INTERFACE_NAME) == 0) {
|
||||||
|
do_subscribe = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (do_subscribe) {
|
||||||
|
subscriber_to_interface(entry->d_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
closedir(dirp);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
int uci_send_via_network()
|
int uci_send_via_network()
|
||||||
{
|
{
|
||||||
void *metric, *times;
|
void *metric, *times;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue