Skip to content

RFC: Wi-Fi add accesspoint support #1085

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 8 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion board/common/rootfs/etc/udev/rules.d/70-rename-wifi.rules
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
SUBSYSTEM=="net", ACTION=="add", TEST=="/sys/class/net/$name/wireless", NAME="wifi%n"
# Only rename physical interfaces, skip virtual ones created by hostapd
SUBSYSTEM=="net", ACTION=="add", TEST=="/sys/class/net/$name/wireless", TEST=="/sys/class/net/$name/device", KERNEL!="*_*", NAME="wifi%n"
4 changes: 4 additions & 0 deletions package/feature-wifi/Config.in
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@ config BR2_PACKAGE_FEATURE_WIFI
select BR2_PACKAGE_WPA_SUPPLICANT_AUTOSCAN
select BR2_PACKAGE_WPA_SUPPLICANT_CLI
select BR2_PACKAGE_WIRELESS_REGDB
select BR2_PACKAGE_HOSTAPD
select BR2_PACKAGE_HOSTAPD_DRIVER_NL80211
select BR2_PACKAGE_HOSTAPD_WPA3
select BR2_PACKAGE_HOSTAPD_WPS
select BR2_PACKAGE_IW
help
Enables WiFi in Infix. Enables all requried applications.
Expand Down
1 change: 0 additions & 1 deletion package/feature-wifi/feature-wifi.mk
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ define FEATURE_WIFI_LINUX_CONFIG_FIXUPS
$(call KCONFIG_ENABLE_OPT,CONFIG_RFKILL)
$(call KCONFIG_SET_OPT,CONFIG_MAC80211,m)
$(call KCONFIG_SET_OPT,CONFIG_CFG80211,m)

$(if $(filter y,$(BR2_PACKAGE_FEATURE_WIFI_DONGLE_REALTEK)),
$(call KCONFIG_ENABLE_OPT,CONFIG_WLAN_VENDOR_REALTEK)
$(call KCONFIG_ENABLE_OPT,CONFIG_RTW88)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,8 @@
},
{
"name": "wifi0",
"type": "infix-if-type:wifi"
"type": "infix-if-type:wifi",
"infix-interfaces:wifi": {}
}
]
},
Expand Down
2 changes: 1 addition & 1 deletion src/confd/bin/gen-interfaces
Original file line number Diff line number Diff line change
Expand Up @@ -96,8 +96,8 @@ filter_iface_ports()
iface_devs=""
for phy in $ifaces; do
found=""
[ -d "/sys/class/net/${phy}/wireless" ] && continue
for port in $ports; do
[ -d "/sys/class/net/${port}/wireless" ] && continue
if [ "$port" = "$phy" ]; then
found=true
break
Expand Down
2 changes: 1 addition & 1 deletion src/confd/src/ietf-interfaces.h
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@ int bridge_port_gen(struct lyd_node *dif, struct lyd_node *cif, FILE *ip);

/* infix-if-wifi.c */
int wifi_gen(struct lyd_node *dif, struct lyd_node *cif, struct dagger *net);
int wifi_gen_del(struct lyd_node *dif, struct dagger *net);
int wifi_gen_del(struct lyd_node *iface, struct dagger *net);

/* infix-if-gre.c */
int gre_gen(struct lyd_node *dif, struct lyd_node *cif, FILE *ip);
Expand Down
195 changes: 159 additions & 36 deletions src/confd/src/infix-if-wifi.c
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,9 @@

#define WPA_SUPPLICANT_FINIT_CONF "/etc/finit.d/available/wpa_supplicant-%s.conf"
#define WPA_SUPPLICANT_CONF "/etc/wpa_supplicant-%s.conf"
#define HOSTAPD_SUPPLICANT_CONF "/etc/hostapd-%s.conf"

static int wifi_gen_config(const char *ifname, const char *ssid, const char *country, const char *secret, const char* encryption, struct dagger *net)
static int wifi_gen_client_config(const char *ifname, const char *ssid, const char *country, const char *secret, const char* encryption, struct dagger *net, int counter)
{
FILE *wpa_supplicant = NULL, *wpa = NULL;
char *encryption_str;
Expand All @@ -32,79 +33,201 @@ static int wifi_gen_config(const char *ifname, const char *ssid, const char *cou
fprintf(wpa, "fi\n");
fclose(wpa);

wpa_supplicant = fopenf("w", WPA_SUPPLICANT_CONF, ifname);
wpa_supplicant = fopenf("a+", WPA_SUPPLICANT_CONF, ifname);
if (!wpa_supplicant) {
rc = SR_ERR_INTERNAL;
goto out;
}

if (!secret || !ssid || !country || !encryption) {
if (!ssid || !secret) {
fprintf(wpa_supplicant,
"ctrl_interface=/run/wpa_supplicant\n"
"autoscan=periodic:10\n"
"ap_scan=1\n");
} else {
if (!strcmp(encryption, "disabled")) {
if (!encryption) {
asprintf(&encryption_str, "key_mgmt=NONE");
} else {
asprintf(&encryption_str, "key_mgmt=SAE WPA-PSK\npsk=\"%s\"", secret);
}
fprintf(wpa_supplicant,
"country=%s\n"
"ctrl_interface=/run/wpa_supplicant\n"
"autoscan=periodic:10\n"
"ap_scan=1\n"
"network={\n"
if (!counter) { /* First SSID */
fprintf(wpa_supplicant,
"country=%s\n"
"ctrl_interface=/run/wpa_supplicant\n"
"autoscan=periodic:10\n"
"ap_scan=1\n\n", country);
}
fprintf(wpa_supplicant, "network={\n"
"bgscan=\"simple: 30:-45:300\"\n"
"ssid=\"%s\"\n"
"%s\n"
"}\n", country, ssid, encryption_str);
free(encryption_str);
"}\n\n", ssid, encryption_str);
free(encryption_str);
}
fclose(wpa_supplicant);

out:
return rc;

}
int wifi_gen(struct lyd_node *dif, struct lyd_node *cif, struct dagger *net)
static int wifi_gen_accesspoint_config(const char *ifname, const char *ssid, const char *country, const char *secret, const char* encryption, const char *band, const char *channel, struct dagger *net, int counter)
{
const char *ssid, *secret_name, *secret, *ifname, *country, *encryption;
struct lyd_node *wifi, *secret_node;
FILE *hostapd_conf, *hostapd_finit;
int rc = 0;

hostapd_finit = dagger_fopen_net_init(net, ifname, NETDAG_INIT_POST, "hostapd.sh");
if (!hostapd_finit) {
rc = SR_ERR_INTERNAL;
goto out;
}

fprintf(hostapd_finit, "# Generated by Infix confd\n");

fprintf(hostapd_finit, "if [ -f '/etc/finit.d/enabled/hostapd@%s.conf' ];then\n", ifname);
fprintf(hostapd_finit, "initctl -bfqn touch hostapd@%s\n", ifname);
fprintf(hostapd_finit, "else\n");
fprintf(hostapd_finit, "initctl -bfqn enable hostapd@%s\n", ifname);
fprintf(hostapd_finit, "fi\n");
fclose(hostapd_finit);
hostapd_conf = fopenf("a+", HOSTAPD_SUPPLICANT_CONF, ifname);
if (!hostapd_conf) {
rc = SR_ERR_INTERNAL;
goto out;
}

if (!counter) { /* First SSID */
bool freq_24GHz = !strcmp(band, "2.4GHz");
fprintf(hostapd_conf, "# Generated by Infix confd\n");

if (!strcmp(channel, "auto"))
channel = freq_24GHz ? "6" : "149";

fprintf(hostapd_conf,
"interface=%s\n"
"driver=nl80211\n"
"hw_mode=%c\n"
"country_code=%s\n"
"wmm_enabled=1\n" /* QoS */
"channel=%s\n"
"logger_syslog=-1\n"
"logger_syslog_level=0\n\n"
"logger_stdout=0\n"
"ctrl_interface=/var/run/hostapd\n"
"ctrl_interface_group=0\n",
ifname, freq_24GHz ? 'g' : 'a', country, channel);
if (freq_24GHz)
fprintf(hostapd_conf, "ieee80211n=1\n");
else
fprintf(hostapd_conf, "ieee80211ac=1\n");
}


fprintf (hostapd_conf,
"\n\n#################################\n"
"# SSID %s\n"
"#################################\n\n",
ssid);
if (counter)
fprintf(hostapd_conf, "bss=%s_%d\n", ifname, counter);

fprintf(hostapd_conf, "ssid=%s\n", ssid);
if (encryption) {
fprintf(hostapd_conf, "wpa_key_mgmt=WPA-PSK SAE\n");
fprintf(hostapd_conf, "wpa_passphrase=%s\n", secret);
fprintf(hostapd_conf, "sae_password=%s\n", secret);
fputs("wpa_pairwise=CCMP\n",hostapd_conf);
fputs("rsn_pairwise=CCMP\n", hostapd_conf);
fputs("ieee80211w=1\n",hostapd_conf); /* This to allow WPA2 clients */
fputs("wpa=2\n",hostapd_conf);
}
fputs("ignore_broadcast_ssid=0\n", hostapd_conf);
fputs("\n", hostapd_conf);
fclose(hostapd_conf);
out:
return rc;

}
static void disable_wifi(const char *ifname, FILE *fp)
{
fprintf(fp, "# Generated by Infix confd\n");
fprintf(fp, "iw dev %s disconnect\n", ifname);
fprintf(fp, "initctl -bfqn disable wifi@%s\n", ifname);
fprintf(fp, "initctl -bfqn disable hostapd@%s\n", ifname);
erasef(WPA_SUPPLICANT_CONF, ifname);
erasef(HOSTAPD_SUPPLICANT_CONF, ifname);
}
int wifi_gen(struct lyd_node *dif, struct lyd_node *cif, struct dagger *net)
{
const char *ssid_name, *secret_name, *secret = NULL, *ifname, *country;
const char *encryption, *mode, *band, *channel;;
struct lyd_node *wifi, *secret_node, *ssid;
bool enabled;
int counter = 0;
FILE *fp;

ifname = lydx_get_cattr(cif, "name");
fp = dagger_fopen_net_init(net, ifname, NETDAG_INIT_POST, "disable-wifi.sh");

if (cif && !lydx_get_child(cif, "wifi")) {
return wifi_gen_config(ifname, NULL, NULL, NULL, NULL, net);
if (!fp) {
ERROR("Could not open disable-wifi.sh");
return SR_ERR_INTERNAL;
}

enabled = lydx_get_bool(cif, "enabled");
wifi = lydx_get_child(cif, "wifi");

ssid = lydx_get_cattr(wifi, "ssid");
secret_name = lydx_get_cattr(wifi, "secret");
if (!enabled || !wifi) {
disable_wifi(ifname, fp);
goto out;
}

if (wifi && !lydx_get_child(wifi, "ssid")) { /* Only the precense container is set. */
wifi_gen_client_config(ifname, NULL, NULL, NULL, NULL, net, 0);
goto out;
}

country = lydx_get_cattr(wifi, "country-code");
encryption = lydx_get_cattr(wifi, "encryption");
secret_node = lydx_get_xpathf(cif, "../../keystore/symmetric-keys/symmetric-key[name='%s']", secret_name);
secret = lydx_get_cattr(secret_node, "cleartext-key");
mode = lydx_get_cattr(wifi, "mode");
band = lydx_get_cattr(wifi, "band"); /* Only set in AP mode */
channel = lydx_get_cattr(wifi, "channel"); /* Only set in AP mode */

if (!strcmp(mode, "client"))
erasef(WPA_SUPPLICANT_CONF, ifname);
else
erasef(HOSTAPD_SUPPLICANT_CONF, ifname);
LYX_LIST_FOR_EACH(lyd_child(wifi), ssid, "ssid") {
ssid_name = lydx_get_cattr(ssid, "name");
secret_name = lydx_get_cattr(ssid, "secret");
encryption = lydx_get_cattr(ssid, "encryption");
if (encryption) {
secret_node = lydx_get_xpathf(cif, "../../keystore/symmetric-keys/symmetric-key[name='%s']", secret_name);
secret = lydx_get_cattr(secret_node, "cleartext-key");
}
if (!strcmp(mode, "client")) {
wifi_gen_client_config(ifname, ssid_name, country, secret, encryption, net, counter);
} else {
wifi_gen_accesspoint_config(ifname, ssid_name, country, secret, encryption, band, channel, net, counter);
}
counter++;

if (!enabled)
return wifi_gen_del(cif, net);
}

return wifi_gen_config(ifname, ssid, country, secret, encryption, net);
out:
fclose(fp);
return SR_ERR_OK;
}

int wifi_gen_del(struct lyd_node *dif, struct dagger *net)
int wifi_gen_del(struct lyd_node *iface, struct dagger *net)
{
const char *ifname = lydx_get_cattr(dif, "name");
FILE *iw = dagger_fopen_net_exit(net, ifname, NETDAG_EXIT_PRE, "iw.sh");

fprintf(iw, "# Generated by Infix confd\n");
fprintf(iw, "iw dev %s disconnect\n", ifname);
fprintf(iw, "initctl -bfqn disable wifi@%s\n", ifname);
fclose(iw);
erasef(WPA_SUPPLICANT_CONF, ifname);

const char *ifname;
FILE *fp;

ifname = lydx_get_cattr(iface, "name");
fp = dagger_fopen_net_exit(net, ifname, NETDAG_EXIT_PRE, "disable-wifi.sh");
if (!fp) {
ERROR("Failed to open disable-wifi.sh");
return SR_ERR_INTERNAL;
}
disable_wifi(ifname, fp);
fclose(fp);
return SR_ERR_OK;
}
Loading