diff --git a/wifimngr.c b/wifimngr.c index 2bdf98225f0bbba2a26cac41d56eebfeca5813d7..df84cb9b2693d2774f054ecd760c63e10ddd61ec 100644 --- a/wifimngr.c +++ b/wifimngr.c @@ -922,6 +922,21 @@ static const struct blobmsg_policy sta_disconnect_policy[__STA_DISCONNECT_MAX] = [STA_DISCONNECT_STA] = { .name = "sta", .type = BLOBMSG_TYPE_STRING } }; +/* sta monitor policy */ +enum { + STA_MONITOR_IFNAME, + STA_MONITOR_ADDR, /* sta mac ':' separated */ + STA_MONITOR_GET, + __STA_MONITOR_MAX, +}; + +static const struct blobmsg_policy sta_monitor_policy[__STA_MONITOR_MAX] = { + [STA_MONITOR_IFNAME] = { .name = "ifname", .type = BLOBMSG_TYPE_STRING }, + [STA_MONITOR_ADDR] = { .name = "sta", .type = BLOBMSG_TYPE_STRING }, + [STA_MONITOR_GET] = { .name = "get", .type = BLOBMSG_TYPE_INT32 }, +}; + + /* add neighbor policy */ enum { NBR_ADD_IFNAME, @@ -1020,6 +1035,75 @@ static int sta_disconnect(struct ubus_context *ctx, struct ubus_object *obj, return UBUS_STATUS_OK; } +static int sta_monitor(struct ubus_context *ctx, struct ubus_object *obj, + struct ubus_request_data *req, const char *method, + struct blob_attr *msg) +{ + struct blob_attr *tb[__STA_MONITOR_MAX]; + struct blob_buf bb; + void *t, *a; + char ifname[16] = {0}; + char sta_str[18] = {0}; + unsigned char sta[6] = {0}; + struct monitor_sta_ioreq { + uint8_t addr[6]; + char rssi[4]; + int last_seen; + } sta_monitor_data, *stamon = NULL; + + + blobmsg_parse(sta_monitor_policy, __STA_MONITOR_MAX, tb, + blob_data(msg), blob_len(msg)); + + if (!(tb[STA_MONITOR_IFNAME])) { + fprintf(stderr, "%s(): ifname not specified!\n", __func__); + return UBUS_STATUS_INVALID_ARGUMENT; + } + + if (!(tb[STA_MONITOR_ADDR])) { + fprintf(stderr, "%s(): sta mac not specified!\n", __func__); + return UBUS_STATUS_INVALID_ARGUMENT; + } + + strncpy(ifname, blobmsg_data(tb[STA_MONITOR_IFNAME]), sizeof(ifname)-1); + strncpy(sta_str, blobmsg_data(tb[STA_MONITOR_ADDR]), sizeof(sta_str)-1); + + memset(&sta_monitor_data, 0, sizeof(sta_monitor_data)); + if (hwaddr_aton(sta_str, sta) == NULL) { + fprintf(stderr, "%s(): Invalid address\n", __func__); + return UBUS_STATUS_INVALID_ARGUMENT; + } + + if ((tb[STA_MONITOR_GET])) + stamon = &sta_monitor_data; + + if (wifi_monitor_sta(ifname, sta, stamon) != 0) + return UBUS_STATUS_UNKNOWN_ERROR; + + if (stamon) { + memset(&bb, 0, sizeof(bb)); + blob_buf_init(&bb, 0); + sprintf(sta_str, "%02x:%02x:%02x:%02x:%02x:%02x", + stamon->addr[0], stamon->addr[1], + stamon->addr[2], stamon->addr[3], + stamon->addr[4], stamon->addr[5]); + t = blobmsg_open_table(&bb, sta_str); + blobmsg_add_u32(&bb, "seen", stamon->last_seen); + a = blobmsg_open_array(&bb, "rssi"); + blobmsg_add_u32(&bb, "", stamon->rssi[0]); + blobmsg_add_u32(&bb, "", stamon->rssi[1]); + blobmsg_add_u32(&bb, "", stamon->rssi[2]); + blobmsg_add_u32(&bb, "", stamon->rssi[3]); + blobmsg_close_array(&bb, a); + blobmsg_close_table(&bb, t); + + ubus_send_reply(ctx, req, bb.head); + blob_buf_free(&bb); + } + + return UBUS_STATUS_OK; +} + static int nbr_add(struct ubus_context *ctx, struct ubus_object *obj, struct ubus_request_data *req, const char *method, struct blob_attr *msg) @@ -1351,6 +1435,7 @@ struct ubus_method wifi_methods[] = { UBUS_METHOD("scan", wl_scan, wl_scan_policy), UBUS_METHOD("scanresults", wl_scanresults, wl_scanres_policy), UBUS_METHOD("disconnect_sta", sta_disconnect, sta_disconnect_policy), + UBUS_METHOD("monitor", sta_monitor, sta_monitor_policy), UBUS_METHOD("add_neighbor", nbr_add, nbr_add_policy), UBUS_METHOD("del_neighbor", nbr_del, nbr_del_policy), UBUS_METHOD("list_neighbor", nbr_list, nbr_list_policy),