Fix to get mesh scan list properly
authorJiwan Kim <ji-wan.kim@samsung.com>
Fri, 3 Mar 2017 04:29:48 +0000 (13:29 +0900)
committersaerome.kim <saerome.kim@samsung.com>
Mon, 17 Jul 2017 02:35:36 +0000 (11:35 +0900)
- Add NL80211_ATTR_IE (114: Mesh element id)
- Remove invalid pkg dependency(capi-network-mesh)
- Update mesh script

files/mesh.sh.in
packaging/meshd.spec
src/mesh-netlink.c

index 860b6cd..dd99329 100755 (executable)
@@ -41,24 +41,30 @@ start()
                        # 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 "========================"
@@ -86,12 +92,11 @@ start()
                        /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
@@ -101,6 +106,11 @@ start()
                        @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
index 914285e..c565758 100644 (file)
@@ -8,7 +8,6 @@ Source0:        %{name}-%{version}.tar.gz
 Source1:       dbus-meshd.conf
 Source2:       net.mesh.service
 Source3:       meshd.service
-BuildRequires: pkgconfig(capi-network-mesh)
 BuildRequires: pkgconfig(glib-2.0)
 BuildRequires: pkgconfig(gio-2.0)
 BuildRequires: pkgconfig(gio-unix-2.0)
index 2704d59..2dda0cd 100644 (file)
@@ -49,6 +49,7 @@
 #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 {
@@ -68,6 +69,7 @@ typedef struct {
        struct nl_cb *s_cb;
 
        gchar* scanning_interface;
+       bool error_occured;
 } mesh_nl_state;
 
 typedef struct {
@@ -205,6 +207,7 @@ static int error_handler(struct sockaddr_nl *nla, struct nlmsgerr *err,
 {
        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");
@@ -416,6 +419,7 @@ static mesh_nl_state *_create_mesh_nl_state(const char* scan_if_name)
        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;
 }
@@ -618,8 +622,17 @@ static gboolean _handle_nl_response_message(GIOChannel *source,
 
 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;
@@ -692,8 +705,17 @@ nla_put_failure:
 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;
@@ -767,8 +789,17 @@ nla_put_failure:
 
 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;
@@ -836,6 +867,27 @@ static void mac_addr_n2a(char *mac_addr, unsigned char *arg)
                        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];
@@ -847,15 +899,17 @@ static int _on_receive_bss_information(struct nl_msg *msg, void *arg)
        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),
@@ -871,8 +925,31 @@ static int _on_receive_bss_information(struct nl_msg *msg, void *arg)
                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]));
@@ -915,6 +992,7 @@ static int _send_nl_trigger_full_scan(const char* mesh_if_name)
        int device_index = 0;
        int ret;
        int test = 0;
+       unsigned char mesh_ie[2];
        GIOChannel *recv_channel = NULL;
 
        if (scan_in_progress) {
@@ -928,6 +1006,7 @@ static int _send_nl_trigger_full_scan(const char* mesh_if_name)
        ret = __initialize_nl80211(state);
        if (MESHD_ERROR_NONE != ret) {
                MESH_LOGE("Failed to initialize nl80211");
+               scan_in_progress = FALSE;
                return ret;
        }
 
@@ -967,6 +1046,11 @@ static int _send_nl_trigger_full_scan(const char* mesh_if_name)
        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);
@@ -990,10 +1074,15 @@ static int _send_nl_trigger_full_scan(const char* mesh_if_name)
        }
 
        /* 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);
@@ -1108,6 +1197,7 @@ static int _send_nl_trigger_specific_scan(const char* mesh_if_name,
        int i = 1;
        int test = 0;
        unsigned int freq = 0;
+       unsigned char mesh_ie[2];
        GIOChannel *recv_channel = NULL;
 
        if (scan_in_progress) {
@@ -1121,6 +1211,7 @@ static int _send_nl_trigger_specific_scan(const char* mesh_if_name,
        ret = __initialize_nl80211(state);
        if (MESHD_ERROR_NONE != ret) {
                MESH_LOGE("Failed to initialize nl80211");
+               scan_in_progress = FALSE;
                return ret;
        }
 
@@ -1176,11 +1267,22 @@ static int _send_nl_trigger_specific_scan(const char* mesh_if_name,
        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) {
@@ -1198,10 +1300,15 @@ static int _send_nl_trigger_specific_scan(const char* mesh_if_name,
        }
 
        /* 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);
@@ -1231,8 +1338,17 @@ DESTROY:
 
 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;
@@ -1295,8 +1411,17 @@ nla_put_failure:
 
 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;
@@ -1370,8 +1495,17 @@ nla_put_failure:
 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;