]> git.ipfire.org Git - thirdparty/hostap.git/commitdiff
Add multicast to unicast support
authorMichael Braun <michael-dev@fami-braun.de>
Mon, 31 Oct 2016 13:58:08 +0000 (14:58 +0100)
committerJouni Malinen <j@w1.fi>
Sun, 4 Dec 2016 19:00:06 +0000 (21:00 +0200)
This adds support for nl80211 NL80211_CMD_SET_MULTICAST_TO_UNICAST
command.

By setting the new hostapd configuration option multicast_to_unicast=1,
hostapd configures this AP to perform multicast to unicast conversion.

When enabled, all multicast packets with ethertype ARP, IPv4, or IPv6
(possibly within an 802.1Q header) will be sent out to each station once
with the destination (multicast) MAC address replaced by the station's
MAC address. Note that this may break certain expectations of the
receiver, e.g., the ability to drop unicast IP packets encapsulated in
multicast L2 frames, or the ability to not send destination unreachable
messages in such cases.

This also does not implement Directed Multicast Service (DMS).

Signed-off-by: Michael Braun <michael-dev@fami-braun.de>
hostapd/config_file.c
hostapd/hostapd.conf
src/ap/ap_config.h
src/ap/beacon.c
src/drivers/driver.h
src/drivers/driver_nl80211.c

index 65f1eb9b5d03cb9a5e0d8ec28b22cbbdd8490105..832ff5517ac68d59e128f27870645d65da940430 100644 (file)
@@ -3560,6 +3560,8 @@ static int hostapd_config_fill(struct hostapd_config *conf,
                }
                bss->fils_cache_id_set = 1;
 #endif /* CONFIG_FILS */
+       } else if (os_strcmp(buf, "multicast_to_unicast") == 0) {
+               bss->multicast_to_unicast = atoi(pos);
        } else {
                wpa_printf(MSG_ERROR,
                           "Line %d: unknown configuration item '%s'",
index 9ea3d6c960c5678f97065ed053a5848a6f240c7d..1fd4fcc9583589a8b7ea74f121778807fd10993c 100644 (file)
@@ -495,6 +495,22 @@ wmm_ac_vo_acm=0
 # <station count>:<channel utilization>:<available admission capacity>
 #bss_load_test=12:80:20000
 
+# Multicast to unicast conversion
+# Request that the AP will do multicast-to-unicast conversion for ARP, IPv4, and
+# IPv6 frames (possibly within 802.1Q). If enabled, such frames are to be sent
+# to each station separately, with the DA replaced by their own MAC address
+# rather than the group address.
+#
+# Note that this may break certain expectations of the receiver, such as the
+# ability to drop unicast IP packets received within multicast L2 frames, or the
+# ability to not send ICMP destination unreachable messages for packets received
+# in L2 multicast (which is required, but the receiver can't tell the difference
+# if this new option is enabled).
+#
+# This also doesn't implement the 802.11 DMS (directed multicast service).
+#
+#multicast_to_unicast=0
+
 ##### IEEE 802.11n related configuration ######################################
 
 # ieee80211n: Whether IEEE 802.11n (HT) is enabled
index b56bb310996817b2407a66e4a0f85b33cff06ed5..7d8f283179e2e6f12b971bf00631f1c26b203a5d 100644 (file)
@@ -601,6 +601,8 @@ struct hostapd_bss_config {
        u8 fils_cache_id[FILS_CACHE_ID_LEN];
        int fils_cache_id_set;
 #endif /* CONFIG_FILS */
+
+       int multicast_to_unicast;
 };
 
 
index 5b708f5eaade9b7b18c0ba27dcd17719f1653016..3788a9764091f5804cf2f7a7105a8ee22fc3d4a3 100644 (file)
@@ -1288,6 +1288,7 @@ int ieee802_11_build_ap_params(struct hostapd_data *hapd,
                params->osen = 1;
        }
 #endif /* CONFIG_HS20 */
+       params->multicast_to_unicast = hapd->conf->multicast_to_unicast;
        params->pbss = hapd->conf->pbss;
        return 0;
 }
index 71ad0069e4dcdc4a127d1e0a4f2b61d5a22cc85f..212f16ca05cc53b1fa954a08b24a45b410d08f6e 100644 (file)
@@ -1170,6 +1170,27 @@ struct wpa_driver_ap_params {
         * infrastructure BSS. Valid only for DMG network.
         */
        int pbss;
+
+       /**
+        * multicast_to_unicast - Whether to use multicast_to_unicast
+        *
+        * If this is non-zero, the AP is requested to perform multicast to
+        * unicast conversion for ARP, IPv4, and IPv6 frames (possibly within
+        * 802.1Q). If enabled, such frames are to be sent to each station
+        * separately, with the DA replaced by their own MAC address rather
+        * than the group address.
+        *
+        * Note that this may break certain expectations of the receiver, such
+        * as the ability to drop unicast IP packets received within multicast
+        * L2 frames, or the ability to not send ICMP destination unreachable
+        * messages for packets received in L2 multicast (which is required,
+        * but the receiver can't tell the difference if this new option is
+        * enabled.)
+        *
+        * This also doesn't implement the 802.11 DMS (directed multicast
+        * service).
+        */
+       int multicast_to_unicast;
 };
 
 struct wpa_driver_mesh_bss_params {
index 6bd984d5697fc377554a473137034a755f33d850..b23c440fdfdcce429c4123fa45fd4ced3a8d2d35 100644 (file)
@@ -3666,6 +3666,52 @@ static int nl80211_put_beacon_rate(struct nl_msg *msg, const u64 flags,
 }
 
 
+static int nl80211_set_multicast_to_unicast(struct i802_bss *bss,
+                                           int multicast_to_unicast)
+{
+       struct wpa_driver_nl80211_data *drv = bss->drv;
+       struct nl_msg *msg;
+       int ret;
+
+       msg = nl80211_bss_msg(bss, 0, NL80211_CMD_SET_MULTICAST_TO_UNICAST);
+       if (!msg ||
+           (multicast_to_unicast &&
+            nla_put_flag(msg, NL80211_ATTR_MULTICAST_TO_UNICAST_ENABLED))) {
+               wpa_printf(MSG_ERROR,
+                          "nl80211: Failed to build NL80211_CMD_SET_MULTICAST_TO_UNICAST msg for %s",
+                          bss->ifname);
+               nlmsg_free(msg);
+               return -ENOBUFS;
+       }
+
+       ret = send_and_recv_msgs(drv, msg, NULL, NULL);
+
+       switch (ret) {
+       case 0:
+               wpa_printf(MSG_DEBUG,
+                          "nl80211: multicast to unicast %s on interface %s",
+                          multicast_to_unicast ? "enabled" : "disabled",
+                          bss->ifname);
+               break;
+       case -EOPNOTSUPP:
+               if (!multicast_to_unicast)
+                       break;
+               wpa_printf(MSG_INFO,
+                          "nl80211: multicast to unicast not supported on interface %s",
+                          bss->ifname);
+               break;
+       default:
+               wpa_printf(MSG_ERROR,
+                          "nl80211: %s multicast to unicast failed with %d (%s) on interface %s",
+                          multicast_to_unicast ? "enabling" : "disabling",
+                          ret, strerror(-ret), bss->ifname);
+               break;
+       }
+
+       return ret;
+}
+
+
 static int wpa_driver_nl80211_set_ap(void *priv,
                                     struct wpa_driver_ap_params *params)
 {
@@ -3885,6 +3931,8 @@ static int wpa_driver_nl80211_set_ap(void *priv,
                nl80211_set_bss(bss, params->cts_protect, params->preamble,
                                params->short_slot_time, params->ht_opmode,
                                params->isolate, params->basic_rates);
+               nl80211_set_multicast_to_unicast(bss,
+                                                params->multicast_to_unicast);
                if (beacon_set && params->freq &&
                    params->freq->bandwidth != bss->bandwidth) {
                        wpa_printf(MSG_DEBUG,