Add multicast to unicast support

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>
master
Michael Braun 8 years ago committed by Jouni Malinen
parent 5f2c0a22a9
commit 34f7c699a6

@ -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'",

@ -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

@ -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;
};

@ -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;
}

@ -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 {

@ -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,

Loading…
Cancel
Save