diff --git a/src/Makefile b/src/Makefile index 62eb124a706410bbae4c0512f27902cf8469c8f5..c9ec84289663280d8ec10bea721cf5981d835f20 100644 --- a/src/Makefile +++ b/src/Makefile @@ -45,17 +45,20 @@ LIBS += -rdynamic -ldl .PHONY: all clean tests -all: i1905d libi1905.so extmods tests +all: libmidgen.so i1905d libi1905.so extmods tests %.o: %.c $(CC) $(CFLAGS) -c -o $@ $< i1905d: $(OBJS) - $(CC) $(LDFLAGS) -o $@ $^ $(LIBS) + $(CC) $(LDFLAGS) -L. -o $@ $^ $(LIBS) -lmidgen libi1905.so: $(LIBOBJS) $(CC) -shared -Wl,-soname,libi1905.so $^ -o $@ $(LIBS) +libmidgen.so: midgen.o + $(CC) -shared -Wl,-soname,libmidgen.so $^ -o $@ -pthread + extmods: @echo "$(extmod_subdirs)" for i in $(extmod_subdirs); do [ -d $$i ] && $(MAKE) -C $$i all; done diff --git a/src/cmdu.c b/src/cmdu.c index 5cb9a0235318ba72fe7daf28e88c568ebf53c9d1..9f35afa11ea3486b40dd3230b8f29a040fcc3438 100644 --- a/src/cmdu.c +++ b/src/cmdu.c @@ -70,25 +70,6 @@ uint16_t tlv_total_length(struct tlv *t) return tlv_length(t) + 3; } - -uint16_t g_mid; - -uint16_t cmdu_init_mid(void) -{ - uint8_t b[2]; - - get_random_bytes(2, b); - g_mid = *(uint16_t *)b; - - return (g_mid == 0) ? g_mid = 1 : g_mid; -} - - -uint16_t cmdu_get_next_mid(void) -{ - return (g_mid % 0xffff == 0) ? g_mid += 2: g_mid++; -} - int is_cmdu_type_valid(uint16_t type) { return (type >= CMDU_TYPE_TOPOLOGY_DISCOVERY && diff --git a/src/cmdu.h b/src/cmdu.h index 5a6a0e8d577f886940f1f43d080d3bf0a5e4b8fd..5730f35d65ad02de799491da183fc48ff0655fc3 100644 --- a/src/cmdu.h +++ b/src/cmdu.h @@ -23,13 +23,13 @@ #include "bufutil.h" #include "hlist.h" - +/** struct cmdu_header - IEEE1905 CMDU header */ struct cmdu_header { uint8_t version; - uint8_t rsvd; + uint8_t rsvd; /**< reserved */ uint16_t type; - uint16_t mid; - uint8_t fid; + uint16_t mid; /**< message id */ + uint8_t fid; /**< fragment id */ uint8_t flag; } __attribute__ ((packed)); @@ -57,7 +57,21 @@ struct cmdu_frag { uint16_t len; struct list_head list; }; - +/** + * @struct cmdu_buff + * @brief control structure for a CMDU buffer + * + * This control structure abstracts out a CMDU frame. In addition to holding + * pointer to the actual CMDU frame, it holds meta information about the CMDU, + * viz. for a receive CMDU which interface it arrived on, sender's macaddress + * etc. + * + * APIs are provided for working with cmdu_buff. Function for iterating through + * TLVs in a CMDU, adding TLV, getting size of CMDU frame etc. + * + * On the transmit and receive path, it is possible to achieve zero-memcpy for + * CMDU manipulation including inserting/extracting the ethernet frame header. + */ struct cmdu_buff { uint8_t *head; uint8_t *data; @@ -74,10 +88,14 @@ struct cmdu_buff { struct list_head list; }; +/** + * @enum tlv_presence + * @brief defines the policy for occurrences of a TLV in a CMDU frame. + */ enum tlv_presence { TLV_PRESENT_UNDEFINED, - TLV_PRESENT_ONE, - TLV_PRESENT_MORE, + TLV_PRESENT_ONE, /**< only one tlv of this type present */ + TLV_PRESENT_MORE, /**< one or more tlv of the same type present */ TLV_PRESENT_NUM, }; @@ -88,14 +106,23 @@ struct tlv_policy { enum tlv_presence present; }; +/** + * @struct tlv + * @brief defines a IEEE1905 TLV + */ struct tlv { uint8_t type; uint16_t len; uint8_t data[]; } __attribute__ ((packed)); - - +/** + * Allocates a TLV + * @param[in] datalen length of tlv data in bytes + * @param[out] band band struct wifi_band type + * + * @return newly allocated tlv on success, or NULL if failed. + */ struct tlv *tlv_alloc(uint16_t datalen); void tlv_zero(struct tlv *t); int tlv_ok(struct tlv *t, int rem); diff --git a/src/cmdu_output.c b/src/cmdu_output.c index 56c4c66298c510f25d53b4ed1f73ad70a982e3bd..c7ebfb39d28b200ba3895c859a3fbafb50121189 100644 --- a/src/cmdu_output.c +++ b/src/cmdu_output.c @@ -39,6 +39,7 @@ #include <easy/easy.h> +#include "debug.h" #include "worker.h" #include "bufutil.h" #include "util.h" @@ -761,7 +762,7 @@ int i1905_send_ap_autoconfig_search(struct i1905_private *priv, uint8_t freqband if (freqband > IEEE80211_FREQUENCY_BAND_60_GHZ) { - fprintf(stderr, "Invalid band %u in ap-autoconfig\n", freqband); + err("Invalid band %u in ap-autoconfig\n", freqband); return -1; } @@ -774,7 +775,7 @@ int i1905_send_ap_autoconfig_search(struct i1905_private *priv, uint8_t freqband frm = cmdu_alloc_simple(CMDU_TYPE_AP_AUTOCONFIGURATION_SEARCH, &mid); if (!frm) { - fprintf(stderr, "%s: -ENOMEM\n", __func__); + err("%s: -ENOMEM\n", __func__); return -1; } @@ -793,7 +794,7 @@ int i1905_send_ap_autoconfig_search(struct i1905_private *priv, uint8_t freqband ret = cmdu_put_tlv(frm, t); if (ret) { - fprintf(stderr, "%s: error: cmdu_put_tlv()\n", __func__); + dbg("%s: error: cmdu_put_tlv()\n", __func__); cmdu_free(frm); return -1; } @@ -809,7 +810,7 @@ int i1905_send_ap_autoconfig_search(struct i1905_private *priv, uint8_t freqband t->data[0] = 0x00; ret = cmdu_put_tlv(frm, t); if (ret) { - fprintf(stderr, "%s: error: cmdu_put_tlv()\n", __func__); + dbg("%s: error: cmdu_put_tlv()\n", __func__); cmdu_free(frm); return -1; } @@ -826,18 +827,18 @@ int i1905_send_ap_autoconfig_search(struct i1905_private *priv, uint8_t freqband ret = cmdu_put_tlv(frm, t); if (ret) { - fprintf(stderr, "%s: error: cmdu_put_tlv()\n", __func__); + dbg("%s: error: cmdu_put_tlv()\n", __func__); cmdu_free(frm); return -1; } cmdu_put_eom(frm); - fprintf(stderr, "%s:%d: ifname = %s\n", __func__, __LINE__, ifs->ifname); + loud("%s: ifname = %s\n", __func__, ifs->ifname); ret = i1905_send_cmdu(ifs->priv, MCAST_1905, ifs->aladdr, ETHERTYPE_1905, frm); if (ret) { - fprintf(stderr, "Error sending AP_AUTOCONFIG_SEARCH\n"); + dbg("Error sending AP_AUTOCONFIG_SEARCH\n"); } cmdu_free(frm); @@ -867,7 +868,7 @@ int i1905_send_ap_autoconfig_renew(struct i1905_private *priv, uint8_t freqband) if (freqband > IEEE80211_FREQUENCY_BAND_60_GHZ) { - fprintf(stderr, "Invalid band %u in ap-autoconf renew\n", freqband); + err("Invalid band %u in ap-autoconf renew\n", freqband); return -EINVAL; } @@ -883,7 +884,7 @@ int i1905_send_ap_autoconfig_renew(struct i1905_private *priv, uint8_t freqband) frm = cmdu_alloc_simple(CMDU_TYPE_AP_AUTOCONFIGURATION_RENEW, &mid); if (!frm) { - fprintf(stderr, "%s: -ENOMEM\n", __func__); + err("%s: -ENOMEM\n", __func__); return -1; } diff --git a/src/midgen.c b/src/midgen.c new file mode 100644 index 0000000000000000000000000000000000000000..b5c31710d141e21458bd2fa969768ae3023dbb11 --- /dev/null +++ b/src/midgen.c @@ -0,0 +1,61 @@ +/* + * midgen.c - 1905 CMDU mid generator + * + * Copyright (C) 2021 IOPSYS Software Solutions AB. All rights reserved. + * + * See LICENSE file for license related information. + * + */ + +#include <stdio.h> +#include <stdint.h> +#include <pthread.h> + +uint16_t g_mid; +pthread_mutex_t g_mid_lock = PTHREAD_MUTEX_INITIALIZER; + +static void get_randombytes(uint8_t *buf, int num) +{ + unsigned int seed = (unsigned int)time(NULL); + int i; + + srand(seed); + for (i = 0; i < num; i++) + buf[i] = rand_r(&seed) & 0xff; +} + +uint16_t cmdu_init_mid(void) +{ + uint8_t b[2]; + uint16_t mid; + + get_randombytes(b, 2); + pthread_mutex_lock(&g_mid_lock); + g_mid = *(uint16_t *)b; + if (g_mid == 0) + g_mid = 1; + + mid = g_mid; + pthread_mutex_unlock(&g_mid_lock); + + return mid; +} + +uint16_t cmdu_get_next_mid(void) +{ + uint16_t mid; + + pthread_mutex_lock(&g_mid_lock); + g_mid++; + if (g_mid == 0xffff) + g_mid++; + mid = g_mid; + pthread_mutex_unlock(&g_mid_lock); + + return mid; +} + +void __attribute__ ((constructor)) libmidgen_init(void) +{ + cmdu_init_mid(); +}