diff options
author | Treehugger Robot <treehugger-gerrit@google.com> | 2022-11-23 02:17:57 +0000 |
---|---|---|
committer | Gerrit Code Review <noreply-gerritcodereview@google.com> | 2022-11-23 02:17:57 +0000 |
commit | 2d107902352d22149b05ac72e54036b930df105c (patch) | |
tree | 55b88a718ccc7445e5e9f52afeca4ba9415f7545 | |
parent | 112ba5eb71016019181ea95e6eb0e08683646114 (diff) | |
parent | 0ffa311c79645863beb9a1a15268e9cbf4f36cba (diff) | |
download | wmediumd-2d107902352d22149b05ac72e54036b930df105c.tar.gz |
Merge "Add LCI and CIVICLOC support"
-rw-r--r-- | wmediumd/api.h | 35 | ||||
-rw-r--r-- | wmediumd/config.c | 3 | ||||
-rw-r--r-- | wmediumd/wmediumd.c | 127 | ||||
-rw-r--r-- | wmediumd/wmediumd.h | 2 |
4 files changed, 153 insertions, 14 deletions
diff --git a/wmediumd/api.h b/wmediumd/api.h index 8fa8fe0..c887755 100644 --- a/wmediumd/api.h +++ b/wmediumd/api.h @@ -75,6 +75,16 @@ enum wmediumd_message { * Set position of station. */ WMEDIUMD_MSG_SET_POSITION, + + /* + * Set LCI of station + */ + WMEDIUMD_MSG_SET_LCI, + + /* + * Set CIVIC loc of station + */ + WMEDIUMD_MSG_SET_CIVICLOC, }; struct wmediumd_message_header { @@ -141,6 +151,14 @@ struct wmediumd_station_info { double x; double y; + /* + * Offsets to the null-terminating string data. + * They point outside of the struct wmediumd_station_info, + * and even struct wmediumd_station_infos for multiple stations. + */ + int lci_offset; + int civicloc_offset; + int tx_power; }; @@ -157,6 +175,23 @@ struct wmediumd_set_position { /* Y position of station */ double y; }; + +struct wmediumd_set_lci { + /* MAC address */ + uint8_t mac[6]; + + /* LCI */ + char lci[0]; +}; + +struct wmediumd_set_civicloc { + /* MAC address */ + uint8_t mac[6]; + + /* CIVIC location */ + char civicloc[0]; +}; + #pragma pack(pop) #endif /* _WMEDIUMD_API_H */ diff --git a/wmediumd/config.c b/wmediumd/config.c index 0500949..e0317ec 100644 --- a/wmediumd/config.c +++ b/wmediumd/config.c @@ -703,6 +703,9 @@ int clear_config(struct wmediumd *ctx) { struct station, list); list_del(&station->list); + + free(station->lci); + free(station->civicloc); free(station); } diff --git a/wmediumd/wmediumd.c b/wmediumd/wmediumd.c index 31f2ce3..a935f03 100644 --- a/wmediumd/wmediumd.c +++ b/wmediumd/wmediumd.c @@ -58,6 +58,23 @@ enum { HWSIM_NUM_VQS, }; +static char *stpcpy_safe(char *dst, const char *src) { + if (dst == NULL) { + return NULL; + } + + if (src == NULL) { + *dst = '\0'; + return dst; + } + + return stpcpy(dst, src); +} + +static int strlen_safe(const char *src) { + return src == NULL ? 0 : strlen(src); +} + static inline int div_round(int a, int b) { return (a + b - 1) / b; @@ -1115,18 +1132,33 @@ static int process_reload_current_config_message(struct wmediumd *ctx) { static int process_get_stations_message(struct wmediumd *ctx, ssize_t *response_len, unsigned char **response_data) { struct station *station; int station_count = 0; + int extra_data_len = 0; + // *reponse_data contains struct wmediumd_station_infos + // and then lci and civiclocs for each station follows afterwards. list_for_each_entry(station, &ctx->stations, list) { if (station->client != NULL) { ++station_count; + extra_data_len += strlen_safe(station->lci) + 1; + extra_data_len += strlen_safe(station->civicloc) + 1; } } - *response_len = sizeof(uint32_t) + sizeof(struct wmediumd_station_info) * station_count; - struct wmediumd_station_infos *station_infos = malloc(*response_len); + int station_len = sizeof(uint32_t) + sizeof(struct wmediumd_station_info) * station_count; + *response_len = station_len + extra_data_len; + *response_data = malloc(*response_len); + + if (*response_data == NULL) { + w_logf(ctx, LOG_ERR, "%s: failed allocate response data\n", __func__); + return -1; + } + struct wmediumd_station_infos *station_infos = (struct wmediumd_station_infos *)*response_data; station_infos->count = station_count; int station_index = 0; + // Pointer to the memory after structs wmediumd_station_infos + // to write lci and civicloc for each station. + char *extra_data_cursor = (char *)&(station_infos->stations[station_count]); list_for_each_entry(station, &ctx->stations, list) { if (station->client != NULL) { @@ -1136,15 +1168,15 @@ static int process_get_stations_message(struct wmediumd *ctx, ssize_t *response_ station_info->x = station->x; station_info->y = station->y; - + station_info->lci_offset = extra_data_cursor - (char *)station_info; + extra_data_cursor = stpcpy_safe(extra_data_cursor, station->lci) + 1; + station_info->civicloc_offset = extra_data_cursor - (char *)station_info; + extra_data_cursor = stpcpy_safe(extra_data_cursor, station->civicloc) + 1; station_info->tx_power = station->tx_power; - station_index++; } } - *response_data = (unsigned char *)station_infos; - return 0; } @@ -1163,6 +1195,44 @@ static int process_set_position_message(struct wmediumd *ctx, struct wmediumd_se return 0; } +static int process_set_lci_message(struct wmediumd *ctx, struct wmediumd_set_lci *set_lci, size_t data_len) { + struct station *node = get_station_by_addr(ctx, set_lci->mac); + + if (node == NULL) { + return -1; + } + int expected_len = data_len - offsetof(struct wmediumd_set_lci, lci) - 1; + if (set_lci->lci[expected_len] != '\0') { + return -1; + } + + if (node->lci) { + free(node->lci); + } + node->lci = strdup(set_lci->lci); + + return node->lci != NULL; +} + +static int process_set_civicloc_message(struct wmediumd *ctx, struct wmediumd_set_civicloc *set_civicloc, size_t data_len) { + struct station *node = get_station_by_addr(ctx, set_civicloc->mac); + + if (node == NULL) { + return -1; + } + int expected_len = data_len - offsetof(struct wmediumd_set_civicloc, civicloc) - 1; + if (set_civicloc->civicloc[expected_len] != '\0') { + return -1; + } + + if (node->civicloc) { + free(node->civicloc); + } + node->civicloc = strdup(set_civicloc->civicloc); + + return node->civicloc != NULL; +} + static const struct usfstl_vhost_user_ops wmediumd_vu_ops = { .connected = wmediumd_vu_connected, .handle = wmediumd_vu_handle, @@ -1196,20 +1266,31 @@ static void wmediumd_api_handler(struct usfstl_loop_entry *entry) ssize_t len; len = read(entry->fd, &hdr, sizeof(hdr)); - if (len != sizeof(hdr)) + if (len != sizeof(hdr)) { + if (len > 0) { + // Skipping log if the fd is closed. + w_logf(ctx, LOG_ERR, "%s: failed to read header\n", __func__); + } goto disconnect; + } /* safety valve */ - if (hdr.data_len > 1024 * 1024) + if (hdr.data_len > 1024 * 1024) { + w_logf(ctx, LOG_ERR, "%s: too large data\n", __func__); goto disconnect; + } data = malloc(hdr.data_len); - if (!data) + if (!data) { + w_logf(ctx, LOG_ERR, "%s: failed to malloc\n", __func__); goto disconnect; + } len = read(entry->fd, data, hdr.data_len); - if (len != hdr.data_len) + if (len != hdr.data_len) { + w_logf(ctx, LOG_ERR, "%s: failed to read data\n", __func__); goto disconnect; + } switch (hdr.type) { case WMEDIUMD_MSG_REGISTER: @@ -1264,18 +1345,18 @@ static void wmediumd_api_handler(struct usfstl_loop_entry *entry) case WMEDIUMD_MSG_SET_SNR: if (process_set_snr_message(ctx, (struct wmediumd_set_snr *)data) < 0) { response = WMEDIUMD_MSG_INVALID; - } + } break; case WMEDIUMD_MSG_RELOAD_CONFIG: if (process_reload_config_message(ctx, (struct wmediumd_reload_config *)data) < 0) { response = WMEDIUMD_MSG_INVALID; - } + } break; case WMEDIUMD_MSG_RELOAD_CURRENT_CONFIG: if (process_reload_current_config_message(ctx) < 0) { response = WMEDIUMD_MSG_INVALID; - } + } break; case WMEDIUMD_MSG_START_PCAP: init_pcapng(ctx, ((struct wmediumd_start_pcap *)data)->pcap_path); @@ -1288,6 +1369,20 @@ static void wmediumd_api_handler(struct usfstl_loop_entry *entry) response = WMEDIUMD_MSG_INVALID; } break; + case WMEDIUMD_MSG_SET_LCI: + if (process_set_lci_message(ctx, + (struct wmediumd_set_lci *)data, + hdr.data_len) < 0) { + response = WMEDIUMD_MSG_INVALID; + } + break; + case WMEDIUMD_MSG_SET_CIVICLOC: + if (process_set_civicloc_message(ctx, + (struct wmediumd_set_civicloc *)data, + hdr.data_len) < 0) { + response = WMEDIUMD_MSG_INVALID; + } + break; case WMEDIUMD_MSG_ACK: assert(client->wait_for_ack == true); assert(hdr.data_len == 0); @@ -1295,6 +1390,7 @@ static void wmediumd_api_handler(struct usfstl_loop_entry *entry) /* don't send a response to a response, of course */ return; default: + w_logf(ctx, LOG_ERR, "%s: unknown message\n", __func__); response = WMEDIUMD_MSG_INVALID; break; } @@ -1303,8 +1399,10 @@ static void wmediumd_api_handler(struct usfstl_loop_entry *entry) hdr.type = response; hdr.data_len = response_len; len = write(entry->fd, &hdr, sizeof(hdr)); - if (len != sizeof(hdr)) + if (len != sizeof(hdr)) { + w_logf(ctx, LOG_ERR, "%s: failed to write response header\n", __func__); goto disconnect; + } if (response_data != NULL) { if (response_len != 0) { @@ -1312,6 +1410,7 @@ static void wmediumd_api_handler(struct usfstl_loop_entry *entry) if (len != response_len) { free(response_data); + w_logf(ctx, LOG_ERR, "%s: failed to write response data\n", __func__); goto disconnect; } } diff --git a/wmediumd/wmediumd.h b/wmediumd/wmediumd.h index f8bc395..111c879 100644 --- a/wmediumd/wmediumd.h +++ b/wmediumd/wmediumd.h @@ -155,6 +155,8 @@ struct station { u8 addr[ETH_ALEN]; /* virtual interface mac address */ u8 hwaddr[ETH_ALEN]; /* hardware address of hwsim radio */ double x, y; /* position of the station [m] */ + char *lci; /* LCI */ + char *civicloc; /* CIVIC */ double dir_x, dir_y; /* direction of the station [meter per MOVE_INTERVAL] */ int tx_power; /* transmission power [dBm] */ struct wqueue queues[IEEE80211_NUM_ACS]; |