# Add virtual interface
@SBIN_DIR@/iw dev $WLAN_INTERFACE set type managed
@SBIN_DIR@/ifconfig $WLAN_INTERFACE up
- @SBIN_DIR@/iw dev $WLAN_INTERFACE interface add $MESH_INTERFACE type mp mesh_id $MESH_ID
- @SBIN_DIR@/iw dev $MESH_INTERFACE set channel $MESH_CHANNEL
+ @SBIN_DIR@/iw dev $WLAN_INTERFACE interface add $MESH_INTERFACE type mp
@SBIN_DIR@/ifconfig $WLAN_INTERFACE down
@SBIN_DIR@/ifconfig $MESH_INTERFACE up
- # Set bridge with ethernet
+ # Create bridge with mesh network
/bin/echo " setting bridge.."
@SBIN_DIR@/brctl addbr $BRIDGE_INTERFACE
@SBIN_DIR@/brctl stp $BRIDGE_INTERFACE on
- @SBIN_DIR@/brctl setfd $BRIDGE_INTERFACE 0
- @SBIN_DIR@/brctl addif $BRIDGE_INTERFACE $ETHER_INTERFACE
+ #@SBIN_DIR@/brctl setfd $BRIDGE_INTERFACE 0
@SBIN_DIR@/brctl addif $BRIDGE_INTERFACE $MESH_INTERFACE
@SBIN_DIR@/ifconfig $MESH_INTERFACE down
- @SBIN_DIR@/ifconfig $ETHER_INTERFACE down
@SBIN_DIR@/ifconfig $MESH_INTERFACE 0.0.0.0 up
- @SBIN_DIR@/ifconfig $ETHER_INTERFACE 0.0.0.0 up
@SBIN_DIR@/ifconfig $BRIDGE_INTERFACE up
+ # Join(create) specific mesh network
+ # NOTICE: [iw dev ## set channel] should be performed before join
+ @SBIN_DIR@/iw dev $MESH_INTERFACE set channel $MESH_CHANNEL
+ @SBIN_DIR@/iw dev $MESH_INTERFACE mesh join $MESH_ID
+
+ # Add external network into bridge
+ @SBIN_DIR@/brctl addif $BRIDGE_INTERFACE $ETHER_INTERFACE
+ @SBIN_DIR@/ifconfig $ETHER_INTERFACE down
+ @SBIN_DIR@/ifconfig $ETHER_INTERFACE 0.0.0.0 up
+
# Get MAC address from eth0
ETH_MAC_ADDR=`@SBIN_DIR@/ifconfig $ETHER_INTERFACE | /usr/bin/sed -n '/ether/p' | /usr/bin/awk "{print \\$2}"`
echo "========================"
/bin/echo " setting mesh interface.."
@SBIN_DIR@/iw dev $WLAN_INTERFACE set type managed
@SBIN_DIR@/ifconfig $WLAN_INTERFACE up
- @SBIN_DIR@/iw dev $WLAN_INTERFACE interface add $MESH_INTERFACE type mp mesh_id $MESH_ID
- @SBIN_DIR@/iw dev $MESH_INTERFACE set channel $MESH_CHANNEL
+ @SBIN_DIR@/iw dev $WLAN_INTERFACE interface add $MESH_INTERFACE type mp
@SBIN_DIR@/ifconfig $WLAN_INTERFACE down
@SBIN_DIR@/ifconfig $MESH_INTERFACE up
- # Prepare bridge for Soft AP
+ # Create bridge with mesh network
/bin/echo " setting bridge.."
@SBIN_DIR@/brctl addbr $BRIDGE_INTERFACE
@SBIN_DIR@/brctl stp $BRIDGE_INTERFACE on
@SBIN_DIR@/ifconfig $MESH_INTERFACE 0.0.0.0 up
@SBIN_DIR@/ifconfig $BRIDGE_INTERFACE up
+ # Join(create) specific mesh network
+ # NOTICE: [iw dev ## set channel] should be performed before join
+ @SBIN_DIR@/iw dev $MESH_INTERFACE set channel $MESH_CHANNEL
+ @SBIN_DIR@/iw dev $MESH_INTERFACE mesh join $MESH_ID
+
# Set Soft AP interface
if [ "wlan0" == "$WLAN_INTERFACE" ]; then
# Use wlan0 as mesh interface
#define MESH_PARAM_HWMP_ROOTMODE "mesh_hwmp_rootmode"
#define MESH_PARAM_GATE_ANNOUNCE "mesh_gate_announcements"
#define MESH_PARAM_STR_LEN_MAX 23
+#define MESH_ELEMENT_ID 114
#define MAX_MAC_ADDR_LEN 18
typedef enum {
struct nl_cb *s_cb;
gchar* scanning_interface;
+ bool error_occured;
} mesh_nl_state;
typedef struct {
{
mesh_nl_state *state = (mesh_nl_state *)arg;
state->callback_state = MESH_NL_CALLBACK_FINISHED;
+ state->error_occured = TRUE;
NOTUSED(nla);
MESH_LOGD("error_handler");
state->nl80211_id = -1;
state->callback_state = MESH_NL_CALLBACK_TRYING;
state->scanning_interface = g_strdup(scan_if_name);
+ state->error_occured = FALSE;
return state;
}
static int _send_nl_set_type_managed(const char* base_if_name)
{
- mesh_nl_state state = { -1, MESH_NL_CALLBACK_TRYING, 0,
- NULL, NULL, NULL, NULL, NULL};
+ mesh_nl_state state = {
+ .nl80211_id = -1,
+ .callback_state = MESH_NL_CALLBACK_TRYING,
+ .event_source = 0,
+ .nl_socket = NULL,
+ .msg = NULL,
+ .cb = NULL,
+ .s_cb = NULL,
+ .scanning_interface = NULL,
+ .error_occured = FALSE,
+ };
enum nl80211_iftype type;
int err = MESHD_ERROR_NONE;
int device_index = 0;
static int _send_nl_create_mesh_interface(const char* base_if_name,
const char* mesh_if_name, const char* mesh_id)
{
- mesh_nl_state state = { -1, MESH_NL_CALLBACK_TRYING, 0,
- NULL, NULL, NULL, NULL, NULL};
+ mesh_nl_state state = {
+ .nl80211_id = -1,
+ .callback_state = MESH_NL_CALLBACK_TRYING,
+ .event_source = 0,
+ .nl_socket = NULL,
+ .msg = NULL,
+ .cb = NULL,
+ .s_cb = NULL,
+ .scanning_interface = NULL,
+ .error_occured = FALSE,
+ };
enum nl80211_iftype type;
int err = MESHD_ERROR_NONE;
int device_index = 0;
static int _send_nl_delete_mesh_interface(const char* mesh_if_name)
{
- mesh_nl_state state = { -1, MESH_NL_CALLBACK_TRYING, 0,
- NULL, NULL, NULL, NULL, NULL};
+ mesh_nl_state state = {
+ .nl80211_id = -1,
+ .callback_state = MESH_NL_CALLBACK_TRYING,
+ .event_source = 0,
+ .nl_socket = NULL,
+ .msg = NULL,
+ .cb = NULL,
+ .s_cb = NULL,
+ .scanning_interface = NULL,
+ .error_occured = FALSE,
+ };
int err = MESHD_ERROR_NONE;
int device_index = 0;
int ret;
arg[0], arg[1], arg[2], arg[3], arg[4], arg[5]);
}
+// ASCII
+static void print_ssid_escaped(const uint8_t len, const uint8_t *data)
+{
+ int i;
+ char buf[64] = {0, };
+
+ for (i = 0; i < len; i++) {
+ if (/*isprint(data[i]) && */data[i] != ' ' && data[i] != '\\')
+ //printf("%c", data[i]);
+ buf[i] = data[i];
+ else if (data[i] == ' ' &&
+ (i != 0 && i != len -1))
+ //printf(" ");
+ buf[i] = ' ';
+ else
+ //printf("\\x%.2x", data[i]);
+ buf[i] = '?';
+ }
+ MESH_LOGD(" : %s", buf);
+}
+
static int _on_receive_bss_information(struct nl_msg *msg, void *arg)
{
struct nlattr *tb[NL80211_ATTR_MAX + 1];
int signal_mbm = 0;
unsigned char signal_un = 0;
int frequency;
+ int is_mesh_bss = FALSE;
static struct nla_policy bss_policy[NL80211_BSS_MAX + 1] = {
[NL80211_BSS_BSSID] = { .type = NLA_UNSPEC },
[NL80211_BSS_FREQUENCY] = { .type = NLA_U32 },
[NL80211_BSS_SIGNAL_MBM] = { .type = NLA_U32 },
[NL80211_BSS_SIGNAL_UNSPEC] = { .type = NLA_U8 },
+ [NL80211_BSS_INFORMATION_ELEMENTS] = { .type = NLA_UNSPEC },
+ [NL80211_BSS_BEACON_IES] = { .type = NLA_UNSPEC },
};
NOTUSED(state);
- MESH_LOGD("_on_receive_bss_information");
nla_parse(tb, NL80211_ATTR_MAX,
genlmsg_attrdata(general_header, 0),
goto FINISH;
}
- if (!bss[NL80211_BSS_BSSID])
+ /* BSS information elements */
+ if (bss[NL80211_BSS_INFORMATION_ELEMENTS]) {
+ uint8_t *ie = nla_data(bss[NL80211_BSS_INFORMATION_ELEMENTS]);
+ int ielen = nla_len(bss[NL80211_BSS_INFORMATION_ELEMENTS]);
+ uint8_t len = ie[1];
+
+ while (ielen >= 2 && ielen >= ie[1]) {
+ len = ie[1];
+ switch (ie[0]) {
+ case MESH_ELEMENT_ID: /* MESH ID */
+ MESH_LOGD("MESH ID");
+ print_ssid_escaped(len, ie+2);
+ is_mesh_bss = TRUE;
+ break;
+ default:
+ break;
+ }
+ ielen -= ie[1] + 2;
+ ie += ie[1] + 2;
+ }
+ }
+ if (FALSE == is_mesh_bss) {
+ /* This is not an mesh bss */
goto FINISH;
+ }
/* Get BSS */
mac_addr_n2a(mac_addr, nla_data(bss[NL80211_BSS_BSSID]));
int device_index = 0;
int ret;
int test = 0;
+ unsigned char mesh_ie[2];
GIOChannel *recv_channel = NULL;
if (scan_in_progress) {
ret = __initialize_nl80211(state);
if (MESHD_ERROR_NONE != ret) {
MESH_LOGE("Failed to initialize nl80211");
+ scan_in_progress = FALSE;
return ret;
}
NLA_PUT(ssids, 1, 0, "");
nla_put_nested(state->msg, NL80211_ATTR_SCAN_SSIDS, ssids);
+ /* IMPORTANT: Add mesh_id to get mesh bss properly */
+ mesh_ie[0] = MESH_ELEMENT_ID; /* Mesh element ID */
+ mesh_ie[1] = 0;
+ NLA_PUT(state->msg, NL80211_ATTR_IE, 2, mesh_ie);
+
/* Set callbacks for scan */
nl_cb_set(state->cb, NL_CB_VALID, NL_CB_CUSTOM, valid_handler, state);
nl_cb_err(state->cb, NL_CB_CUSTOM, error_handler, state);
}
/* Register I/O callback to wait asynchronously */
- recv_channel = g_io_channel_unix_new(nl_socket_get_fd(state->nl_socket));
- state->event_source = g_io_add_watch(recv_channel,
- (G_IO_IN | G_IO_ERR), _on_socket_io_received, state);
- g_io_channel_unref(recv_channel);
+ if (FALSE == state->error_occured) {
+ recv_channel = g_io_channel_unix_new(nl_socket_get_fd(state->nl_socket));
+ state->event_source = g_io_add_watch(recv_channel,
+ (G_IO_IN | G_IO_ERR), _on_socket_io_received, state);
+ g_io_channel_unref(recv_channel);
+ } else {
+ MESH_LOGE("Error responded. do not wait for scan done event");
+ goto DESTROY;
+ }
if (ssids)
nlmsg_free(ssids);
int i = 1;
int test = 0;
unsigned int freq = 0;
+ unsigned char mesh_ie[2];
GIOChannel *recv_channel = NULL;
if (scan_in_progress) {
ret = __initialize_nl80211(state);
if (MESHD_ERROR_NONE != ret) {
MESH_LOGE("Failed to initialize nl80211");
+ scan_in_progress = FALSE;
return ret;
}
else
NLA_PUT(ssids, 1, 0, "");
-
/* Set frequency and SSID into message */
nla_put_nested(state->msg, NL80211_ATTR_SCAN_FREQUENCIES, freqs);
nla_put_nested(state->msg, NL80211_ATTR_SCAN_SSIDS, ssids);
+ /* IMPORTANT: Add mesh_id to get mesh bss properly */
+ mesh_ie[0] = MESH_ELEMENT_ID; /* Mesh element ID */
+ mesh_ie[1] = 0;
+ NLA_PUT(state->msg, NL80211_ATTR_IE, 2, mesh_ie);
+
+ /* Set callbacks for scan */
+ nl_cb_set(state->cb, NL_CB_VALID, NL_CB_CUSTOM, valid_handler, state);
+ nl_cb_err(state->cb, NL_CB_CUSTOM, error_handler, state);
+ nl_cb_set(state->cb, NL_CB_FINISH, NL_CB_CUSTOM, finish_handler, state);
+ nl_cb_set(state->cb, NL_CB_ACK, NL_CB_CUSTOM, ack_handler, state);
+ nl_cb_set(state->cb, NL_CB_SEQ_CHECK, NL_CB_CUSTOM, no_seq_check, NULL); // No sequence checking for multicast messages.
+
/* Send message into kernel */
ret = nl_send_auto(state->nl_socket, state->msg);
if (ret < 0) {
}
/* Register I/O callback to wait asynchronously */
- recv_channel = g_io_channel_unix_new(nl_socket_get_fd(state->nl_socket));
- state->event_source = g_io_add_watch(recv_channel,
- (G_IO_IN | G_IO_ERR), _on_socket_io_received, state);
- g_io_channel_unref(recv_channel);
+ if (FALSE == state->error_occured) {
+ recv_channel = g_io_channel_unix_new(nl_socket_get_fd(state->nl_socket));
+ state->event_source = g_io_add_watch(recv_channel,
+ (G_IO_IN | G_IO_ERR), _on_socket_io_received, state);
+ g_io_channel_unref(recv_channel);
+ } else {
+ MESH_LOGE("Error responded. do not wait for scan done event");
+ goto DESTROY;
+ }
if (ssids)
nlmsg_free(ssids);
static int _send_nl_abort_scan(const char* mesh_if_name)
{
- mesh_nl_state state = { -1, MESH_NL_CALLBACK_TRYING, 0,
- NULL, NULL, NULL, NULL, NULL};
+ mesh_nl_state state = {
+ .nl80211_id = -1,
+ .callback_state = MESH_NL_CALLBACK_TRYING,
+ .event_source = 0,
+ .nl_socket = NULL,
+ .msg = NULL,
+ .cb = NULL,
+ .s_cb = NULL,
+ .scanning_interface = NULL,
+ .error_occured = FALSE,
+ };
int err = MESHD_ERROR_NONE;
int device_index = 0;
int ret;
static int _send_nl_set_mesh_channel(const char* mesh_if_name, int channel)
{
- mesh_nl_state state = { -1, MESH_NL_CALLBACK_TRYING, 0,
- NULL, NULL, NULL, NULL, NULL};
+ mesh_nl_state state = {
+ .nl80211_id = -1,
+ .callback_state = MESH_NL_CALLBACK_TRYING,
+ .event_source = 0,
+ .nl_socket = NULL,
+ .msg = NULL,
+ .cb = NULL,
+ .s_cb = NULL,
+ .scanning_interface = NULL,
+ .error_occured = FALSE,
+ };
enum nl80211_band band;
int err = MESHD_ERROR_NONE;
static int _send_nl_set_mesh_parameter(const char* mesh_if_name,
const char* param_name, unsigned int value)
{
- mesh_nl_state state = { -1, MESH_NL_CALLBACK_TRYING, 0,
- NULL, NULL, NULL, NULL, NULL};
+ mesh_nl_state state = {
+ .nl80211_id = -1,
+ .callback_state = MESH_NL_CALLBACK_TRYING,
+ .event_source = 0,
+ .nl_socket = NULL,
+ .msg = NULL,
+ .cb = NULL,
+ .s_cb = NULL,
+ .scanning_interface = NULL,
+ .error_occured = FALSE,
+ };
struct nlattr *container;
int err = MESHD_ERROR_NONE;