diff --git a/src/agent.c b/src/agent.c index 0cd52ae13dd3130d91f6d928a3b991da5b891ef6..5683844f272627318412d4a4016919ccefc24d65 100644 --- a/src/agent.c +++ b/src/agent.c @@ -590,6 +590,19 @@ struct netif_bk *find_bkhaul_by_bssid(struct agent *a, uint8_t *bssid) return NULL; } +/* find wds by interface name */ +struct netif_wds *find_wds_by_ifname(struct agent *a, const char *ifname) +{ + struct netif_wds *p; + + list_for_each_entry(p, &a->wdslist, list) { + if (!strncmp(p->name, ifname, sizeof(p->name))) + return p; + } + + return NULL; +} + void agent_link_ap_to_cfg(struct agent *a) { struct netif_fhcfg *fcfg; @@ -2132,7 +2145,7 @@ static uint16_t wifi_process_pvid_assoc_frame(struct agent *a, uint8_t *frame, static void wifi_sta_event_handler(void *c, struct blob_attr *msg) { struct agent *a = (struct agent *)c; - char ifname[16] = {0}, event[16] = {0}; + char ifname[16] = {0}, event[24] = {0}; struct blob_attr *tb[3]; static const struct blobmsg_policy ev_attr[3] = { [0] = { .name = "ifname", .type = BLOBMSG_TYPE_STRING }, @@ -2322,8 +2335,44 @@ static void wifi_sta_event_handler(void *c, struct blob_attr *msg) if (!s->supports_bcnreport) s->supports_bcnreport = true; - } else if (!strcmp(event, "wds-station-add")) { - /* TODO: wds handling */ + } else if (!strcmp(event, "wds-station-added") || + !strcmp(event, "wds-station-removed")) { + struct blob_attr *data[1]; + static const struct blobmsg_policy data_attr[1] = { + [0] = { .name = "ifname", .type = BLOBMSG_TYPE_STRING }, + }; + char wdsname[16] = {0}; + struct ts_context *ts = &a->ts; + struct netif_fh *fh = NULL; + bool add = !strcmp(event, "wds-station-added"); + uint16_t vid; + + if (a->cfg.brcm_setup) + return; + + blobmsg_parse(data_attr, 1, data, blobmsg_data(tb[2]), + blobmsg_data_len(tb[2])); + + if (!data[0]) + return; + + strncpy(wdsname, blobmsg_data(data[0]), sizeof(wdsname) - 1); + + if (add) + netif_alloc_wds(a, wdsname); + else + netif_free_wds_by_ifname(a, wdsname); + + list_for_each_entry(fh, &a->fhlist, list) { + vid = fh->cfg->vid; + if (!is_vid_valid(vid)) + vid = ts->primary_vid; + + if (a->cfg.guest_isolation && (vid != 1 && vid != ts->primary_vid)) { + dbg("/lib/wifi/multiap ts isolate_wds %s %s %s\n", (add ? "add" : "del"), fh->name, wdsname); + runCmd("/lib/wifi/multiap ts isolate_wds %s %s %s", (add ? "add" : "del"), fh->name, wdsname); + } + } } else if (!strcmp(event, "action")) { /* TODO: this event belongs under wifi.iface handler */ struct blob_attr *data[2]; static const struct blobmsg_policy data_attr[2] = { @@ -5172,6 +5221,38 @@ static struct netif_bk *netif_alloc_bk(const char *ifname) return n; } +struct netif_wds *netif_alloc_wds(struct agent *a, const char *ifname) +{ + struct netif_wds *n = NULL; + + n = calloc(1, sizeof(struct netif_wds)); + if (!n) + return NULL; + + snprintf(n->name, 15, "%s", ifname); + + list_add(&n->list, &a->wdslist); + + return n; +} + +void netif_free_wds(struct netif_wds *n) +{ + list_del(&n->list); + free(n); +} + +void netif_free_wds_by_ifname(struct agent *a, const char *ifname) +{ + struct netif_wds *n = NULL; + + n = find_wds_by_ifname(a, ifname); + if (!n) + return; + + netif_free_wds(n); +} + /* get first ap on the radio */ // TODO: fixme: get base interface based on macaddr instead? struct netif_fh *wifi_radio_to_ap(struct agent *a, const char *radio) @@ -6429,6 +6510,14 @@ void clear_bklist(struct agent *a) } } +void clear_wdslist(struct agent *a) +{ + struct netif_wds *p, *tmp; + + list_for_each_entry_safe(p, tmp, &a->wdslist, list) { + netif_free_wds(p); + } +} int agent_map_sub_cb(void *bus, void *priv, void *data) { @@ -6540,6 +6629,7 @@ int agent_init_defaults(struct agent *a) INIT_LIST_HEAD(&a->ethlist); INIT_LIST_HEAD(&a->framelist); INIT_LIST_HEAD(&a->nodelist); + INIT_LIST_HEAD(&a->wdslist); #if (EASYMESH_VERSION > 2) INIT_LIST_HEAD(&a->dpp_ctx.enrolleelist); INIT_LIST_HEAD(&a->dpp_ctx.chirplist); @@ -6738,6 +6828,7 @@ void run_agent(void) cmdu_ackq_free(&w->cmdu_ack_q); clear_fhlist(w); clear_bklist(w); + clear_wdslist(w); ubus_unregister_event_handler(ctx, &w->evh); #ifdef VENDOR_EXTENSION agent_unload_extensions(w); diff --git a/src/agent.h b/src/agent.h index 9bdb7e90f7c4ca8f0f15791877d21ab17cb4c54b..07d58bb07ace6ec217519433883be1f509e956f4 100644 --- a/src/agent.h +++ b/src/agent.h @@ -339,6 +339,12 @@ struct netif_bk { uint8_t blacklist_bssid[16][6]; }; +/* wds wifi (ap vlan) interface */ +struct netif_wds { + char name[16]; + struct list_head list; +}; + #if 0 struct agent_msg { void *ctx; @@ -672,6 +678,7 @@ struct agent { struct list_head bklist; struct list_head framelist; struct list_head ethlist; + struct list_head wdslist; #if (EASYMESH_VERSION > 2) struct dpp_context dpp_ctx; @@ -870,6 +877,7 @@ void agent_free_radios(struct agent *a); void agent_free_cntlr_sync(struct agent *a); void clear_fhlist(struct agent *a); void clear_bklist(struct agent *a); +void clear_wdslist(struct agent *a); bool agent_has_active_backhaul(struct agent *a); int agent_radio_scanresults(struct agent *a, struct wifi_radio_element *re); int agent_init_interfaces(struct agent *a); @@ -892,6 +900,9 @@ int agent_send_ch_scan_response(struct agent *a, struct wifi_netdev *ndev, struct wifi_scan_request_radio *req); bool agent_ch_scan_succesful(struct agent *a); struct netif_fh *netif_alloc_fh(const char *ifname); - +struct netif_wds *netif_alloc_wds(struct agent *a, const char *ifname); +void netif_free_wds(struct netif_wds *n); +void netif_free_wds_by_ifname(struct agent *a, const char *ifname); +struct netif_wds *find_wds_by_ifname(struct agent *a, const char *ifname); #endif /* AGENT_H */ diff --git a/src/agent_tlv.c b/src/agent_tlv.c index 4e83a1c5e41386be3cd7063effba1ccf7fb1238b..a2c0f95c07b344120f45985a39094cc7adf09b8f 100644 --- a/src/agent_tlv.c +++ b/src/agent_tlv.c @@ -2748,7 +2748,7 @@ int agent_clear_traffic_sep(struct agent *a) list_for_each_entry(fcfg, &a->cfg.fhlist, list) { char fmt[68] = {0}; - char fif_prefix[IFNAMSIZ] = {0}; /* 4addr ifname prefix */ + int band = 0; snprintf(fmt, sizeof(fmt), "ts cleanup %u", fcfg->vid); agent_exec_platform_scripts(fmt); @@ -2758,26 +2758,30 @@ int agent_clear_traffic_sep(struct agent *a) if (!is_vid_valid(vid)) vid = a->ts.primary_vid; - if (a->cfg.brcm_setup) - strncpy(fif_prefix, "wds", sizeof(fif_prefix) - 1); - else - strncpy(fif_prefix, "TODO", sizeof(fif_prefix) - 1); /* FIXME: non brcm platforms, one for each bbss */ - if (a->cfg.brcm_setup) { - int band = 0; - - if (fcfg->band == BAND_2) - band = 2; - else if (fcfg->band == BAND_5) - band = 5; - else if (fcfg->band == BAND_6) - band = 6; - else - continue; + dbg("/lib/wifi/multiap ts isolate_wds %s %s wds+\n", "del", fcfg->name); + runCmd("/lib/wifi/multiap ts isolate_wds %s %s wds+", "del", fcfg->name); + } + else { + struct netif_wds *wds = NULL; - dbg("/lib/wifi/multiap ts isolate %s %d %d %d %s %s\n", "del", a->ts.primary_vid, fcfg->vid, band, fcfg->name, fif_prefix); - runCmd("/lib/wifi/multiap ts isolate %s %d %d %d %s %s", "del", a->ts.primary_vid, fcfg->vid, band, fcfg->name, fif_prefix); + list_for_each_entry(wds, &a->wdslist, list) { + dbg("/lib/wifi/multiap ts isolate_wds %s %s %s\n", "del", fcfg->name, wds->name); + runCmd("/lib/wifi/multiap ts isolate_wds %s %s %s", "del", fcfg->name, wds->name); + } } + + if (fcfg->band == BAND_2) + band = 2; + else if (fcfg->band == BAND_5) + band = 5; + else if (fcfg->band == BAND_6) + band = 6; + else + continue; + + dbg("/lib/wifi/multiap ts isolate_ap %s %d %d %d %s\n", "del", a->ts.primary_vid, fcfg->vid, band, fcfg->name); + runCmd("/lib/wifi/multiap ts isolate_ap %s %d %d %d %s", "del", a->ts.primary_vid, fcfg->vid, band, fcfg->name); } /* if pvid was previously enabled, disable and wake nl */ if (a->cfg.pcfg) { diff --git a/src/nl.c b/src/nl.c index fbb86ac014284694d9dd4a5040e08209cc22ccd2..54395ce45552f1c0165b222f3528ad7e898df16d 100644 --- a/src/nl.c +++ b/src/nl.c @@ -315,11 +315,11 @@ static void ts_set_system(struct ts_context *ts) Cmd(buf, sizeof(buf), "/lib/wifi/multiap ts reload"); } -static void ts_check_ifi(struct ts_context *ts, struct ifinfomsg *ifi, const char *ifname) +static void ts_check_ifi(struct agent *a, struct ifinfomsg *ifi, const char *ifname) { + struct ts_context *ts = &a->ts; struct ts_iface *tsif; - if (ts->primary_vid == 0) return; @@ -338,7 +338,8 @@ static void ts_check_ifi(struct ts_context *ts, struct ifinfomsg *ifi, const cha return; } - if (!strstr(ifname, "wds") && !strstr(ifname, "sta")) + if (!strstr(ifname, "wds") && !strstr(ifname, "sta") && + find_wds_by_ifname(a, ifname) == NULL) return; tsif = ts_configure_iface(ts, ifname, 0); @@ -390,7 +391,6 @@ int nl_main_cb(struct nl_msg *msg, void *arg) { struct nlmsghdr *nlh = nlmsg_hdr(msg); struct agent *a = (struct agent *) arg; - struct ts_context *ts = &a->ts; const char *bridge = a->cfg.al_bridge; bool brcm_setup = a->cfg.brcm_setup; @@ -423,7 +423,7 @@ int nl_main_cb(struct nl_msg *msg, void *arg) if (!(ifi->ifi_flags & IFF_UP)) break; */ - ts_check_ifi(ts, ifi, ifname); + ts_check_ifi(a, ifi, ifname); if (!brcm_setup) break; @@ -512,8 +512,8 @@ static void ts_configure(struct agent *a) /* Fronthaul/Backhaul APs */ list_for_each_entry(fh, &a->fhlist, list) { - char fif_prefix[IFNAMSIZ] = {0}; /* 4addr ifname prefix */ bool add = false; + int band = 0; dbg("FH/BH AP name %s multi_ap %d\n", fh->name, fh->cfg->multi_ap); vid = fh->cfg->vid; @@ -521,28 +521,33 @@ static void ts_configure(struct agent *a) vid = ts->primary_vid; ts_configure_iface(ts, fh->name, vid); - if (a->cfg.brcm_setup) - strncpy(fif_prefix, "wds", sizeof(fif_prefix) - 1); - else - strncpy(fif_prefix, "TODO", sizeof(fif_prefix) - 1); /* FIXME: non brcm platforms, one for each bbss */ add = (a->cfg.guest_isolation && (vid != 1 && vid != ts->primary_vid) ? true : false); if (a->cfg.brcm_setup) { - int band = 0; - - if (fh->cfg->band == BAND_2) - band = 2; - else if (fh->cfg->band == BAND_5) - band = 5; - else if (fh->cfg->band == BAND_6) - band = 6; - else - continue; + dbg("/lib/wifi/multiap ts isolate_wds %s %s wds+\n", (add ? "add" : "del"), fh->name); + runCmd("/lib/wifi/multiap ts isolate_wds %s %s wds+", (add ? "add" : "del"), fh->name); + } + else { + struct netif_wds *wds = NULL; - dbg("/lib/wifi/multiap ts isolate %s %d %u %d %s %s\n", (add ? "add" : "del"), ts->primary_vid, fh->cfg->vid, band, fh->name, fif_prefix); - runCmd("/lib/wifi/multiap ts isolate %s %d %u %d %s %s", (add ? "add" : "del"), ts->primary_vid, fh->cfg->vid, band, fh->name, fif_prefix); + list_for_each_entry(wds, &a->wdslist, list) { + dbg("/lib/wifi/multiap ts isolate_wds %s %s %s\n", (add ? "add" : "del"), fh->name, wds->name); + runCmd("/lib/wifi/multiap ts isolate_wds %s %s %s", (add ? "add" : "del"), fh->name, wds->name); + } } + + if (fh->cfg->band == BAND_2) + band = 2; + else if (fh->cfg->band == BAND_5) + band = 5; + else if (fh->cfg->band == BAND_6) + band = 6; + else + continue; + + dbg("/lib/wifi/multiap ts isolate_ap %s %d %u %d %s\n", (add ? "add" : "del"), ts->primary_vid, fh->cfg->vid, band, fh->name); + runCmd("/lib/wifi/multiap ts isolate_ap %s %d %u %d %s", (add ? "add" : "del"), ts->primary_vid, fh->cfg->vid, band, fh->name); } /* Backhaul stations */ diff --git a/src/script/traffic_separation b/src/script/traffic_separation index a0c812a320aa29183acf053ae50d3241ba691210..509eab2dcd8cd4f73f7f670466fd601f7a2c0e7f 100755 --- a/src/script/traffic_separation +++ b/src/script/traffic_separation @@ -435,7 +435,22 @@ EOF fcctl flush } - ts_isolate() { + ts_isolate_wds() { + local action=$1 # add/del + local ifname=$2 # guest fbss name + local wds=$3 # 4addr interface name or prefix+ + + [ -z "$wds" -o -z "$ifname" ] && return + + ebtables -D FORWARD -i $ifname -o $wds -j DROP > /dev/null 2>&1 + ebtables -D FORWARD -i $wds -o $ifname -j DROP > /dev/null 2>&1 + + [ "$action" != "add" ] && return + ebtables -A FORWARD -i $ifname -o $wds -j DROP > /dev/null 2>&1 + ebtables -A FORWARD -i $wds -o $ifname -j DROP > /dev/null 2>&1 + } + + ts_isolate_ap() { ts_isolate_radio() { local section=$1 local action=$2 @@ -452,11 +467,11 @@ EOF config_get apifname "$section" ifname [ "$ifname" = "$apifname" ] && continue # this should never happen - ebtables -D FORWARD -i $ifname --o $apifname -j DROP > /dev/null 2>&1 + ebtables -D FORWARD -i $ifname -o $apifname -j DROP > /dev/null 2>&1 [ "$action" != "add" ] && continue - ebtables -A FORWARD -i $ifname --o $apifname -j DROP > /dev/null 2>&1 + ebtables -A FORWARD -i $ifname -o $apifname -j DROP > /dev/null 2>&1 } local action=$1 shift @@ -468,10 +483,9 @@ EOF shift local ifname=$1 # guest fbss name shift - local ifprefix=$1 # 4addr mode ifname prefix local br_dev="${AL_BRIDGE/-/_}" - [ -z "$pvid" -o -z "$ifprefix" -o -z "$ifname" ] && return + [ -z "$pvid" -o -z "$ifname" ] && return config_load mapagent config_foreach ts_isolate_radio ap $action $band $vid $ifname @@ -481,23 +495,14 @@ EOF json_get_var bk_ifname ifname json_cleanup - for prefix in $@; do - ebtables -D FORWARD -i $ifname --o ${prefix}+ -j DROP > /dev/null 2>&1 - ebtables -D FORWARD -i ${prefix}+ --o $ifname -j DROP > /dev/null 2>&1 + # isolate eth interfaces + for port in $(uci -q get network.${br_dev}.ports) ; do + ebtables -D FORWARD -i $ifname -o $port -j DROP > /dev/null 2>&1 + ebtables -D FORWARD -i $port -o $ifname -j DROP > /dev/null 2>&1 - # isolate eth interfaces - for port in $(uci -q get network.${br_dev}.ports) ; do - ebtables -D FORWARD -i $ifname --o $port -j DROP > /dev/null 2>&1 - ebtables -D FORWARD -i $port --o $ifname -j DROP > /dev/null 2>&1 - - [ "$action" != "add" -o "$port" = "$bk_ifname" ] && continue - ebtables -A FORWARD -i $ifname --o $port -j DROP > /dev/null 2>&1 - ebtables -A FORWARD -i $port --o $ifname -j DROP > /dev/null 2>&1 - done - - [ "$action" != "add" ] && continue - ebtables -A FORWARD -i $ifname --o ${prefix}+ -j DROP > /dev/null 2>&1 - ebtables -A FORWARD -i ${prefix}+ --o $ifname -j DROP > /dev/null 2>&1 + [ "$action" != "add" -o "$port" = "$bk_ifname" ] && continue + ebtables -A FORWARD -i $ifname -o $port -j DROP > /dev/null 2>&1 + ebtables -A FORWARD -i $port -o $ifname -j DROP > /dev/null 2>&1 done } @@ -509,7 +514,8 @@ EOF keep) ts_dbg "keep $@"; ts_keep $@;; reload) ts_dbg "reload $@"; ts_reload $@;; cleanup) ts_dbg "cleanup $@"; ts_cleanup $@;; - isolate) ts_dbg "isolate $@"; ts_isolate $@;; + isolate_ap) ts_dbg "isolate_ap $@"; ts_isolate_ap $@;; + isolate_wds) ts_dbg "isolate_wds $@"; ts_isolate_wds $@;; --help|help) ts_usage;; *) ts_usage; exit 1;; esac