diff --git a/src/config.c b/src/config.c index a416c987e7c6e679638951362fdb434dc7c8d249..a71fc329bfa602cd8f4e3eb4637cd48b0e3f1e36 100644 --- a/src/config.c +++ b/src/config.c @@ -241,6 +241,71 @@ int hostmngr_config_defaults(struct hostmngr_config *cfg) return 0; } +int ap_get_mld_ifname(char *ifname, char *mld_ifname) +{ + enum { + W_IFNAME, + W_MLD, + NUM_POLICIES + }; + const struct uci_parse_option opts[] = { + { .name = "ifname", .type = UCI_TYPE_STRING }, + { .name = "mld", .type = UCI_TYPE_STRING } + }; + struct uci_option *tb[NUM_POLICIES]; + struct uci_context *ctx; + struct uci_package *pkg; + struct uci_element *e; + int ret = -1; + + ctx = uci_alloc_context(); + if (!ctx) + return ret; + + if (uci_load(ctx, "wireless", &pkg)) { + uci_free_context(ctx); + return ret; + } + + uci_foreach_element(&pkg->sections, e) { + struct uci_section *s = uci_to_section(e); + struct uci_ptr ptr; + + if (strcmp(s->type, "wifi-iface")) + continue; + + uci_parse_section(s, opts, NUM_POLICIES, tb); + + if (!tb[W_IFNAME]) + continue; + + if (strncmp(ifname, tb[W_IFNAME]->v.string, 16)) + continue; + + if (!tb[W_MLD]) + break; + + /* lookup mld ifname in wifi-mld section directly */ + ptr.package = "wireless"; + ptr.section = tb[W_MLD]->v.string; + ptr.option = "ifname"; + ptr.target = UCI_TYPE_OPTION; + + ret = uci_lookup_ptr(ctx, &ptr, NULL, false); + if (ret != UCI_OK ||!(ptr.flags & UCI_LOOKUP_DONE)) + break; + + if (!(ptr.flags & UCI_LOOKUP_COMPLETE)) + break; + + strncpy(mld_ifname, ptr.o->v.string, 16); + } + + uci_unload(ctx, pkg); + uci_free_context(ctx); + return ret; +} + int hostmngr_dump_config(struct hostmngr_config *cfg) { char *s, *ifnames = NULL; diff --git a/src/hostmngr.c b/src/hostmngr.c index 76b1ac0a27df93a2b0da0a8ce098daf625fcbb19..c6afc12b4ea49796b5e01374c1eda18445c8b6a2 100644 --- a/src/hostmngr.c +++ b/src/hostmngr.c @@ -51,26 +51,9 @@ static void hostmngr_sighandler(int sig) signal_pending = sig; } -struct local_interface *hostmngr_alloc_interface(const char *ifname) -{ - struct local_interface *iface = NULL; - struct ip_address ips[32] = {0}; - int num_ipaddrs = 32; - int ret; - - iface = calloc(1, sizeof(*iface)); - if (!iface) { - return NULL; - } - - snprintf(iface->ifname, 16, "%s", ifname); - iface->ifindex = if_nametoindex(ifname); - dbg("%s: %s (%d)\n", __func__, iface->ifname, iface->ifindex); - if_gethwaddr(ifname, iface->macaddr); - if_getflags(ifname, &iface->ifflags); - if_getoperstate(ifname, &iface->operstate); - if_getcarrier(ifname, &iface->carrier); +static void hostmngr_update_interface_bridgeinfo(struct local_interface *iface) +{ iface->is_bridge = if_isbridge(iface->ifname); if (!iface->is_bridge) { int br_ifindex; @@ -82,6 +65,13 @@ struct local_interface *hostmngr_alloc_interface(const char *ifname) iface->br_ifindex = br_ifindex; } } +} + +static void hostmngr_update_interface_ipaddrs(struct local_interface *iface) +{ + struct ip_address ips[32] = {0}; + int num_ipaddrs = 32; + int ret; ret = if_getaddrs(iface->ifname, ips, &num_ipaddrs); if (!ret && num_ipaddrs > 0) { @@ -91,16 +81,45 @@ struct local_interface *hostmngr_alloc_interface(const char *ifname) memcpy(iface->ipaddrs, ips, num_ipaddrs * sizeof(struct ip_address)); } } +} +static void hostmngr_update_interface_mediatype(struct local_interface *iface) +{ if (strncmp(iface->ifname, "lo", 2)) { if (is_wifi_interface(iface->ifname)) { iface->mediatype = IF_MEDIA_WIFI; - if (is_ap_interface(iface->ifname)) + if (is_ap_interface(iface->ifname)) { iface->is_ap = true; + iface->is_affiliated_ap = is_affiliated_ap(iface->ifname); + if (iface->is_affiliated_ap) + ap_get_mld_ifname(iface->ifname, iface->mld_ifname); + } } else { iface->mediatype = IF_MEDIA_ETH; } } +} + +struct local_interface *hostmngr_alloc_interface(const char *ifname) +{ + struct local_interface *iface = NULL; + + iface = calloc(1, sizeof(*iface)); + if (!iface) { + return NULL; + } + + snprintf(iface->ifname, 16, "%s", ifname); + iface->ifindex = if_nametoindex(ifname); + dbg("%s: %s (%d)\n", __func__, iface->ifname, iface->ifindex); + if_gethwaddr(ifname, iface->macaddr); + if_getflags(ifname, &iface->ifflags); + if_getoperstate(ifname, &iface->operstate); + if_getcarrier(ifname, &iface->carrier); + + hostmngr_update_interface_bridgeinfo(iface); + hostmngr_update_interface_ipaddrs(iface); + hostmngr_update_interface_mediatype(iface); return iface; } @@ -116,7 +135,6 @@ void enum_interfaces_cb(struct nl_object *obj, void *arg) struct rtnl_link *link = NULL; int num_ipaddrs = 32; struct nl_addr *a = NULL; - int ret; nl_object_get(obj); @@ -142,36 +160,10 @@ void enum_interfaces_cb(struct nl_object *obj, void *arg) iface->ifflags = rtnl_link_get_flags(link); iface->operstate = rtnl_link_get_operstate(link); - iface->is_bridge = if_isbridge(iface->ifname); - if (!iface->is_bridge) { - int br_ifindex; - - br_ifindex = if_isbridge_interface(iface->ifname); - if (br_ifindex > 0) { - iface->is_brif = true; - iface->brport = if_brportnum(iface->ifname); - iface->br_ifindex = br_ifindex; - } - } - ret = if_getaddrs(iface->ifname, ips, &num_ipaddrs); - if (!ret && num_ipaddrs > 0) { - iface->ipaddrs = calloc(num_ipaddrs, sizeof(struct ip_address)); - if (iface->ipaddrs) { - iface->num_ipaddrs = num_ipaddrs; - memcpy(iface->ipaddrs, ips, num_ipaddrs * sizeof(struct ip_address)); - } - } - - if (strncmp(iface->ifname, "lo", 2)) { - if (is_wifi_interface(iface->ifname)) { - iface->mediatype = IF_MEDIA_WIFI; - if (is_ap_interface(iface->ifname)) - iface->is_ap = true; - } else { - iface->mediatype = IF_MEDIA_ETH; - } - } + hostmngr_update_interface_bridgeinfo(iface); + hostmngr_update_interface_ipaddrs(iface); + hostmngr_update_interface_mediatype(iface); list_add_tail(&iface->list, argp->iflist); *argp->n += 1; diff --git a/src/hostmngr.h b/src/hostmngr.h index 5968f49a1e48ab4be580c4526cd60e8b1c45c230..775295b1c97f9b925eee084b7e2c8783b097c884 100644 --- a/src/hostmngr.h +++ b/src/hostmngr.h @@ -192,11 +192,14 @@ int hostmngr_reconfig(struct hostmngr_config *cfg, const char *path, const char void hostmngr_config_free(struct hostmngr_config *cfg); int hostmngr_config_add_zone(struct hostmngr_config *cfg, const char *ifname); +int ap_get_mld_ifname(char *ifname, char *mld_ifname); struct local_interface { char ifname[16]; int ifindex; uint8_t macaddr[6]; + char mld_ifname[16]; + bool is_affiliated_ap; uint32_t ifflags; uint8_t operstate; bool is_bridge; diff --git a/src/neigh.c b/src/neigh.c index 9905f542e045aa83760a1f95fa81418e86ba05c5..8520386e83fa6ae3c417a7a8bec55ed2396241bf 100644 --- a/src/neigh.c +++ b/src/neigh.c @@ -1069,11 +1069,15 @@ int neigh_is_wifi_type(void *priv, uint8_t *macaddr) list_for_each_entry(iface, &p->iflist, list) { if (iface->is_ap) { + char *ifname = iface->ifname; uint8_t stas[6*128] = {0}; int num = 128; int ret; int i; + if (iface->is_affiliated_ap && strlen(iface->mld_ifname)) + ifname = iface->mld_ifname; + ret = ap_get_assoclist(iface->ifname, stas, &num); if (ret) continue; @@ -1092,12 +1096,16 @@ int neigh_is_wifi_type(void *priv, uint8_t *macaddr) void hostmngr_get_wifi_stations(struct hostmngr_private *priv, struct local_interface *iface) { + char *ifname = iface->ifname; uint8_t stas[6*128] = {0}; int num = 128; int ret; int i; - ret = ap_get_assoclist(iface->ifname, stas, &num); + if (iface->is_affiliated_ap && strlen(iface->mld_ifname)) + ifname = iface->mld_ifname; + + ret = ap_get_assoclist(ifname, stas, &num); if (ret) return; diff --git a/src/wifi_api.c b/src/wifi_api.c index 7a5f755712b667535e023b24394fe62ffcb9df63..c40999d14fa8369ebd2332027a311bd62668b0cb 100644 --- a/src/wifi_api.c +++ b/src/wifi_api.c @@ -58,6 +58,22 @@ int interface_get_4addr_parent(const char *ifname, char *parent) return wifi_get_4addr_parent(ifname, parent); } + +int is_affiliated_ap(const char *ifname) +{ + struct wifi_ap ap = {0}; + int ret; + + ret = wifi_ap_info(ifname, &ap); + if (ret) + return false; + + if (ap.bss.mlo_link_id == -1 || hwaddr_is_zero(ap.bss.mld_macaddr)) + return false; + + return true; +} + int is_wifi_interface(const char *ifname) { char parent[16] = {0}; diff --git a/src/wifi_api.h b/src/wifi_api.h index e01b177485293a9455c70d0c2158c951da8b1c3e..281955762a61f75dc4d75c9c7ef059ada39d5df3 100644 --- a/src/wifi_api.h +++ b/src/wifi_api.h @@ -15,7 +15,7 @@ int is_wifi_interface(const char *ifname); int is_ap_interface(const char *ifname); int ap_get_assoclist(const char *ifname, uint8_t *sta_macaddrs, int *num); int interface_get_4addr_parent(const char *ifname, char *parent); - +int is_affiliated_ap(const char *ifname); #else static inline int is_wifi_interface(const char *ifname) { @@ -36,6 +36,10 @@ static inline int interface_get_4addr_parent(const char *ifname, char *parent) { return -1; } +static inline int is_affiliated_ap(const char *ifname) +{ + return -1; +} #endif /* HAS_WIFI */