]> Gitweb @ Texas Instruments - Open Source Git Repositories - git.TI.com/gitweb - build-utilities/hostap.git/blobdiff - src/drivers/driver_nl80211.c
Enable only unicast RXFILTER by default
[build-utilities/hostap.git] / src / drivers / driver_nl80211.c
index a7936421fb2f6f1184f3ba52550662f05060d01b..fd9b082a2940f4f0964611f605c5e7fa8fea0bdd 100644 (file)
@@ -1900,6 +1900,10 @@ static void nl80211_cqm_event(struct wpa_driver_nl80211_data *drv,
                wpa_printf(MSG_DEBUG, "nl80211: Connection quality monitor "
                           "event: RSSI low");
                ed.signal_change.above_threshold = 0;
+       } else if (event == NL80211_CQM_RSSI_BEACON_LOSS) {
+               wpa_printf(MSG_DEBUG, "nl80211: Connection quality monitor "
+                          "event: beacon loss!");
+               wpa_supplicant_event(drv->ctx, EVENT_START_ROAMING, &ed);
        } else
                return;
 
@@ -8416,6 +8420,14 @@ static int wpa_driver_nl80211_deinit_ap(void *priv)
        return wpa_driver_nl80211_set_mode(priv, NL80211_IFTYPE_STATION);
 }
 
+static int wpa_driver_nl80211_deinit_p2p_cli(void *priv)
+{
+       struct i802_bss *bss = priv;
+       struct wpa_driver_nl80211_data *drv = bss->drv;
+       if (drv->nlmode != NL80211_IFTYPE_P2P_CLIENT)
+               return -1;
+       return wpa_driver_nl80211_set_mode(priv, NL80211_IFTYPE_STATION);
+}
 
 static void wpa_driver_nl80211_resume(void *priv)
 {
@@ -8765,6 +8777,7 @@ nl80211_self_filter_get_pattern_handler(u8 *buf, int buflen, void *arg)
 }
 
 static struct rx_filter rx_filters[] = {
+       /* ID 0 */
        {.name = "self",
         .pattern = {},
         .pattern_len = 6,
@@ -8773,6 +8786,7 @@ static struct rx_filter rx_filters[] = {
         .get_pattern_handler = nl80211_self_filter_get_pattern_handler,
        },
 
+       /* ID 1 */
        {.name = "bcast",
         .pattern = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF},
         .pattern_len = 6,
@@ -8780,6 +8794,7 @@ static struct rx_filter rx_filters[] = {
         .mask_len = 1,
        },
 
+       /* ID 2 */
        {.name = "ipv4mc",
         .pattern = {0x01,0x00,0x5E},
         .pattern_len = 3,
@@ -8787,6 +8802,7 @@ static struct rx_filter rx_filters[] = {
         .mask_len = 1,
        },
 
+       /* ID 3 */
        {.name = "ipv6mc",
         .pattern = {0x33,0x33},
         .pattern_len = 2,
@@ -8794,18 +8810,45 @@ static struct rx_filter rx_filters[] = {
         .mask_len = 1,
        },
 
+       /* ID 4 */
        {.name = "dhcp",
-        .pattern = {0   , 0   , 0   , 0   , 0   , 0   , 0   , 0   ,
+        .pattern = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0   , 0   ,
                     0   , 0   , 0   , 0   , 0   , 0   , 0x45, 0   ,
                     0   , 0   , 0   , 0   , 0   , 0   , 0   , 0x11,
                     0   , 0   , 0   , 0   , 0   , 0   , 0   , 0   ,
                     0   , 0   , 0   , 0   , 0x00, 0x44},
         .pattern_len = 38,
-        .mask = { 0,                                 /* OCTET 1 */
-                  BIT(6),                            /* OCTET 2 */
-                  BIT(7),                            /* OCTET 3 */
-                  0,                                 /* OCTET 4 */
-                  BIT(4) | BIT(5) },                 /* OCTET 5 */
+        .mask = { BIT(0) | BIT(1) | BIT(2) | BIT(3) | BIT(4) | BIT(5),
+                  BIT(6),                               /* OCTET 2 */
+                  BIT(7),                               /* OCTET 3 */
+                  0,                                    /* OCTET 4 */
+                  BIT(4) | BIT(5) },                    /* OCTET 5 */
+        .mask_len = 5,
+       },
+
+       /* ID 5 */
+       {.name = "arp",
+        .pattern = {0   , 0   , 0   , 0   , 0   , 0   , 0   , 0   ,
+                    0   , 0   , 0   , 0   , 0x08, 0x06},
+        .pattern_len = 14,
+        .mask = { 0,                                    /* OCTET 1 */
+                  BIT(4) | BIT(5) },                    /* OCTET 2 */
+        .mask_len = 2,
+       },
+
+       /* ID 6 */
+       {.name = "ssdp",
+        .pattern = {0x01, 0x00, 0x5E, 0   , 0   , 0   , 0   , 0   ,
+                    0   , 0   , 0   , 0   , 0   , 0   , 0x45, 0   ,
+                    0   , 0   , 0   , 0   , 0   , 0   , 0   , 0x11,
+                    0   , 0   , 0   , 0   , 0   , 0   , 0xEF, 0xFF,
+                    0xFF, 0xFA, 0   , 0   , 0x07, 0x6C},
+        .pattern_len = 38,
+        .mask = { BIT(0) | BIT(1) | BIT(2),             /* OCTET 1 */
+                  BIT(6),                               /* OCTET 2 */
+                  BIT(7),                               /* OCTET 3 */
+                  BIT(6) | BIT(7),                      /* OCTET 4 */
+                  BIT(0) | BIT(1) | BIT(4) | BIT(5) },  /* OCTET 5 */
         .mask_len = 5,
        },
 };
@@ -8845,10 +8888,13 @@ static int nl80211_set_wowlan_triggers(struct i802_bss *bss, int enable)
                        goto nla_put_failure;
                }
 
-               /* In ginger filter 0 and 1 are always set but in ICS they
-                  were completely removed. Make sure to always set them
-                  otherwise unicast and bcast are dropped */
-               filters = bss->drv->wowlan_triggers |= 3;
+               /*
+                * In GB filters 0 and 1 are always set but in ICS they
+                * were completely removed. Add filter 0 (unicast) by default
+                * so unicast traffic won't be dropped in any case.
+                */
+
+               filters = bss->drv->wowlan_triggers |= 1;
 
                for (i = 0; i < NR_RX_FILTERS; i++) {
                        struct rx_filter *rx_filter = &rx_filters[i];
@@ -8926,6 +8972,62 @@ static int nl80211_parse_wowlan_trigger_nr(char *s)
        return i;
 }
 
+static int nl80211_toggle_dropbcast(int enable)
+{
+       char filename[90];
+       int rv;
+       FILE *f;
+
+       snprintf(filename, sizeof(filename) - 1,
+                "/sys/bus/platform/devices/wl12xx/drop_bcast");
+       f = fopen(filename, "w");
+       if (f < 0) {
+               wpa_printf(MSG_DEBUG, "Could not open file %s: %s",
+                          filename, strerror(errno));
+               return -1;
+       }
+
+       rv = fprintf(f, "%d", enable);
+       fclose(f);
+       if (rv < 1) {
+               wpa_printf(MSG_DEBUG, "Could not write to file %s: %s",
+                          filename, strerror(errno));
+               return -1;
+       }
+
+       return 0;
+}
+
+static int nl80211_dropbcast_get(char *buf, size_t buf_len)
+{
+       char filename[90], value[10], *pos;
+       int f, rv;
+
+       snprintf(filename, sizeof(filename) - 1,
+                "/sys/bus/platform/devices/wl12xx/drop_bcast");
+       f = open(filename, O_RDONLY);
+       if (f < 0) {
+               wpa_printf(MSG_DEBUG, "Could not open file %s: %s",
+                          filename, strerror(errno));
+               return -1;
+       }
+
+       rv = read(f, value, sizeof(value) - 1);
+       close(f);
+       if (rv < 0) {
+               wpa_printf(MSG_DEBUG, "Could not read file %s: %s",
+                          filename, strerror(errno));
+               return -1;
+       }
+
+       value[rv] = '\0';
+       pos = os_strchr(value, '\n');
+       if (pos)
+               *pos = '\0';
+
+       return snprintf(buf, buf_len, "Drop bcast = %s\n", value);
+}
+
 #endif /* ANDROID */
 
 static int nl80211_add_pmkid(void *priv, const u8 *bssid, const u8 *pmkid)
@@ -9428,10 +9530,28 @@ static int wpa_driver_nl80211_driver_cmd(void *priv, char *cmd, char *buf,
                if(i < 0)
                        return i;
                return nl80211_toggle_wowlan_trigger(bss, i, 0);
-       } else if( os_strcasecmp(cmd, "RXFILTER-START") == 0 ) {
+       } else if (os_strcasecmp(cmd, "RXFILTER-START") == 0) {
                return nl80211_set_wowlan_triggers(bss, 1);
-       } else if( os_strcasecmp(cmd, "RXFILTER-STOP") == 0 ) {
+       } else if (os_strcasecmp(cmd, "RXFILTER-STOP") == 0) {
                return nl80211_set_wowlan_triggers(bss, 0);
+       } else if (os_strncasecmp(cmd, "DROPBCAST", 9) == 0) {
+               char *value = cmd + 10;
+
+               if (!os_strcasecmp(value, "ENABLE") ||
+                   !os_strcasecmp(value, "1")) {
+                       ret = nl80211_toggle_dropbcast(1);
+               } else if (!os_strcasecmp(value, "DISABLE") ||
+                          !os_strcasecmp(value, "0")) {
+                       ret = nl80211_toggle_dropbcast(0);
+               } else if (!os_strcasecmp(value, "GET") ||
+                          !os_strlen(value)) {
+                       ret = nl80211_dropbcast_get(buf, buf_len);
+               } else {
+                       wpa_printf(MSG_ERROR,
+                                  "Invalid parameter for DROPBCAST: %s",
+                                  value);
+                       ret = -1;
+               }
        } else if( os_strcasecmp(cmd, "LINKSPEED") == 0 ) {
                struct wpa_signal_info sig;
                int linkspeed;
@@ -9608,6 +9728,7 @@ const struct wpa_driver_ops wpa_driver_nl80211_ops = {
        wpa_driver_nl80211_cancel_remain_on_channel,
        .probe_req_report = wpa_driver_nl80211_probe_req_report,
        .deinit_ap = wpa_driver_nl80211_deinit_ap,
+       .deinit_p2p_cli = wpa_driver_nl80211_deinit_p2p_cli,
        .resume = wpa_driver_nl80211_resume,
        .send_ft_action = nl80211_send_ft_action,
        .signal_monitor = nl80211_signal_monitor,