-.\" $OpenBSD: ifconfig.8,v 1.308 2018/05/05 16:52:59 jmc Exp $
+.\" $OpenBSD: ifconfig.8,v 1.309 2018/07/11 20:18:09 phessler Exp $
.\" $NetBSD: ifconfig.8,v 1.11 1996/01/04 21:27:29 pk Exp $
.\" $FreeBSD: ifconfig.8,v 1.16 1998/02/01 07:03:29 steve Exp $
.\"
.\"
.\" @(#)ifconfig.8 8.4 (Berkeley) 6/1/94
.\"
-.Dd $Mdocdate: May 5 2018 $
+.Dd $Mdocdate: July 11 2018 $
.Dt IFCONFIG 8
.Os
.Sh NAME
.Op Oo Fl Oc Ns Cm chan Op Ar n
.Op Oo Fl Oc Ns Cm nwflag Ar flag
.Op Oo Fl Oc Ns Cm nwid Ar id
+.Op Oo Fl Oc Ns Cm join Op Ar id
.Op Oo Fl Oc Ns Cm nwkey Ar key
.Op Oo Fl Oc Ns Cm powersave Op Ar duration
.Op Cm scan
.It Cm -nwid
Set the network ID to the empty string to allow the interface to connect
to any available access point.
+.It Cm join Op Ar id
+Configure network ID.
+The
+.Ar id
+will be used to auto-join wireless networks.
+The
+.Ar id
+can either be any text string up to 32 characters in length,
+or a series of hexadecimal digits up to 64 digits.
+Any necessary
+.Cm wpakey
+or
+.Cm nwkey
+arguments should be specified on the same line.
+.Pp
+If no
+.Ar id
+is specified, show the list of currently configured auto-join networks.
.It Cm nwkey Ar key
Enable WEP encryption using the specified
.Ar key .
-/* $OpenBSD: ifconfig.c,v 1.367 2018/05/28 08:53:35 kn Exp $ */
+/* $OpenBSD: ifconfig.c,v 1.368 2018/07/11 20:18:09 phessler Exp $ */
/* $NetBSD: ifconfig.c,v 1.40 1997/10/01 02:19:43 enami Exp $ */
/*
void setifmtu(const char *, int);
void setifllprio(const char *, int);
void setifnwid(const char *, int);
+void setifjoin(const char *, int);
+void delifjoin(const char *, int);
void setifbssid(const char *, int);
void setifnwkey(const char *, int);
void setifwpa(const char *, int);
{ "mtu", NEXTARG, 0, setifmtu },
{ "nwid", NEXTARG, 0, setifnwid },
{ "-nwid", -1, 0, setifnwid },
+ { "join", NEXTARG0, 0, setifjoin },
+ { "-join", NEXTARG0, 0, delifjoin },
{ "bssid", NEXTARG, 0, setifbssid },
{ "-bssid", -1, 0, setifbssid },
{ "nwkey", NEXTARG, 0, setifnwkey },
const struct afswtch *afp; /*the address family being set or asked about*/
+char joinname[IEEE80211_NWID_LEN];
+char nwidname[IEEE80211_NWID_LEN];
+
int ifaliases = 0;
int aflag = 0;
}
nwid.i_len = len;
(void)strlcpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
+ (void)strlcpy(nwidname, nwid.i_nwid, sizeof(nwidname));
ifr.ifr_data = (caddr_t)&nwid;
if (ioctl(s, SIOCS80211NWID, (caddr_t)&ifr) < 0)
warn("SIOCS80211NWID");
}
+void
+setifjoin(const char *val, int d)
+{
+ struct ieee80211_join join;
+ int len;
+
+ if (val == NULL) {
+ /* TODO: display the list of join'd networks */
+ return;
+ }
+
+ if (d != 0) {
+ /* no network id is especially desired */
+ memset(&join, 0, sizeof(join));
+ len = 0;
+ } else {
+ len = sizeof(join.i_nwid);
+ if (get_string(val, NULL, join.i_nwid, &len) == NULL)
+ return;
+ }
+ join.i_len = len;
+ (void)strlcpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
+ (void)strlcpy(joinname, join.i_nwid, sizeof(joinname));
+ ifr.ifr_data = (caddr_t)&join;
+ if (ioctl(s, SIOCS80211JOIN, (caddr_t)&ifr) < 0)
+ warn("SIOCS80211JOIN");
+}
+
+void
+delifjoin(const char *val, int d)
+{
+ struct ieee80211_join join;
+ int len;
+
+ memset(&join, 0, sizeof(join));
+ len = 0;
+ join.i_flags |= IEEE80211_JOIN_DEL;
+
+ if (val == NULL) {
+ ifr.ifr_data = (caddr_t)&join;
+ if (ioctl(s, SIOCS80211JOIN, (caddr_t)&ifr) < 0)
+ warn("SIOCS80211JOIN");
+ return;
+ }
+
+ if (d != 0) {
+ /* no network id is especially desired */
+ memset(&join, 0, sizeof(join));
+ len = 0;
+ } else {
+ len = sizeof(join.i_nwid);
+ if (val != NULL &&
+ get_string(val, NULL, join.i_nwid, &len) == NULL)
+ return;
+ }
+ join.i_len = len;
+ (void)strlcpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
+ ifr.ifr_data = (caddr_t)&join;
+ if (ioctl(s, SIOCS80211JOIN, (caddr_t)&ifr) < 0)
+ warn("SIOCS80211JOIN");
+}
+
void
setifbssid(const char *val, int d)
{
memset(&ifr, 0, sizeof(ifr));
ifr.ifr_data = (caddr_t)&nwid;
strlcpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
- if (ioctl(s, SIOCG80211NWID, (caddr_t)&ifr))
- err(1, "SIOCG80211NWID");
+
+ /* Use the value specified in 'join' or 'nwid' */
+ if (strlen(joinname) != 0) {
+ strlcpy(nwid.i_nwid, joinname, sizeof(nwid.i_nwid));
+ nwid.i_len = strlen(joinname);
+ } else if (strlen(nwidname) != 0) {
+ strlcpy(nwid.i_nwid, nwidname, sizeof(nwid.i_nwid));
+ nwid.i_len = strlen(nwidname);
+ } else {
+ warnx("no nwid or join command, guessing nwid to use");
+
+ if (ioctl(s, SIOCG80211NWID, (caddr_t)&ifr))
+ err(1, "SIOCG80211NWID");
+ }
passlen = strlen(val);
if (passlen == 2 + 2 * sizeof(psk.i_psk) &&
void
ieee80211_status(void)
{
- int len, i, nwkey_verbose, inwid, inwkey, ipsk, ichan, ipwr;
+ int len, i, nwkey_verbose, inwid, ijoin, inwkey, ipsk, ichan, ipwr;
int ibssid, iwpa;
struct ieee80211_nwid nwid;
+ struct ieee80211_join join;
struct ieee80211_nwkey nwkey;
struct ieee80211_wpapsk psk;
struct ieee80211_power power;
strlcpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
inwid = ioctl(s, SIOCG80211NWID, (caddr_t)&ifr);
+ ifr.ifr_data = (caddr_t)&join;
+ strlcpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
+ ijoin = ioctl(s, SIOCG80211JOIN, (caddr_t)&ifr);
+
memset(&nwkey, 0, sizeof(nwkey));
strlcpy(nwkey.i_name, name, sizeof(nwkey.i_name));
inwkey = ioctl(s, SIOCG80211NWKEY, (caddr_t)&nwkey);
iwpa = ioctl(s, SIOCG80211WPAPARMS, &wpa);
/* check if any ieee80211 option is active */
- if (inwid == 0 || inwkey == 0 || ipsk == 0 || ipwr == 0 ||
- ichan == 0 || ibssid == 0 || iwpa == 0)
+ if (inwid == 0 || ijoin == 0 || inwkey == 0 || ipsk == 0 ||
+ ipwr == 0 || ichan == 0 || ibssid == 0 || iwpa == 0)
fputs("\tieee80211:", stdout);
else
return;
len = nwid.i_len;
if (len > IEEE80211_NWID_LEN)
len = IEEE80211_NWID_LEN;
- fputs(" nwid ", stdout);
+ if (ijoin == 0 && join.i_flags & IEEE80211_JOIN_FOUND)
+ fputs(" join ", stdout);
+ else
+ fputs(" nwid ", stdout);
print_string(nwid.i_nwid, len);
}
-/* $OpenBSD: ieee80211_ioctl.c,v 1.60 2018/04/26 12:50:07 pirofti Exp $ */
+/* $OpenBSD: ieee80211_ioctl.c,v 1.61 2018/07/11 20:18:09 phessler Exp $ */
/* $NetBSD: ieee80211_ioctl.c,v 1.15 2004/05/06 02:58:16 dyoung Exp $ */
/*-
struct ifreq *ifr = (struct ifreq *)data;
int i, error = 0;
struct ieee80211_nwid nwid;
+ struct ieee80211_join join;
+ struct ieee80211_ess *ess;
struct ieee80211_wpapsk *psk;
struct ieee80211_keyavail *ka;
struct ieee80211_keyrun *kr;
}
error = copyout(&nwid, ifr->ifr_data, sizeof(nwid));
break;
+ case SIOCS80211JOIN:
+ if ((error = suser(curproc)) != 0)
+ break;
+ if ((error = copyin(ifr->ifr_data, &join, sizeof(join))) != 0)
+ break;
+ if (join.i_len > IEEE80211_NWID_LEN) {
+ error = EINVAL;
+ break;
+ }
+ if (join.i_flags & IEEE80211_JOIN_DEL)
+ ieee80211_del_ess(ic, join.i_nwid, join.i_len ? 0 : 1);
+ memset(ic->ic_des_essid, 0, IEEE80211_NWID_LEN);
+ ic->ic_des_esslen = join.i_len;
+ memcpy(ic->ic_des_essid, join.i_nwid, join.i_len);
+ /* disable WPA/WEP */
+ ieee80211_disable_rsn(ic);
+ ieee80211_disable_wep(ic);
+ /* save nwid for auto-join */
+ if (!(join.i_flags & IEEE80211_JOIN_DEL))
+ ieee80211_add_ess(ic, ic->ic_des_essid, 0, 0);
+ ieee80211_set_ess(ic, ic->ic_des_essid);
+ error = ENETRESET;
+ break;
+ case SIOCG80211JOIN:
+ memset(&join, 0, sizeof(join));
+ error = ENOENT;
+ if (ic->ic_bss == NULL)
+ break;
+ TAILQ_FOREACH(ess, &ic->ic_ess, ess_next) {
+ if (memcmp(ess->essid, ic->ic_bss->ni_essid,
+ IEEE80211_NWID_LEN) == 0) {
+ join.i_len = ic->ic_bss->ni_esslen;
+ memcpy(join.i_nwid, ic->ic_bss->ni_essid,
+ join.i_len);
+ join.i_flags = IEEE80211_JOIN_FOUND;
+ error = copyout(&join, ifr->ifr_data,
+ sizeof(join));
+ break;
+ }
+ }
+ break;
case SIOCS80211NWKEY:
if ((error = suser(curproc)) != 0)
break;
error = ieee80211_ioctl_setnwkeys(ic, (void *)data);
+ if (error == ENETRESET)
+ ieee80211_add_ess(ic, ic->ic_des_essid, 0, 1);
break;
case SIOCG80211NWKEY:
error = ieee80211_ioctl_getnwkeys(ic, (void *)data);
if ((error = suser(curproc)) != 0)
break;
error = ieee80211_ioctl_setwpaparms(ic, (void *)data);
+ if (error == ENETRESET)
+ ieee80211_add_ess(ic, ic->ic_des_essid, 1, 0);
break;
case SIOCG80211WPAPARMS:
error = ieee80211_ioctl_getwpaparms(ic, (void *)data);
ic->ic_flags &= ~IEEE80211_F_PSK;
memset(ic->ic_psk, 0, sizeof(ic->ic_psk));
}
+ ieee80211_add_ess(ic, ic->ic_des_essid, 1, 0);
error = ENETRESET;
break;
case SIOCG80211WPAPSK:
-/* $OpenBSD: ieee80211_ioctl.h,v 1.31 2017/10/27 12:22:40 jsg Exp $ */
+/* $OpenBSD: ieee80211_ioctl.h,v 1.32 2018/07/11 20:18:09 phessler Exp $ */
/* $NetBSD: ieee80211_ioctl.h,v 1.7 2004/04/30 22:51:04 dyoung Exp $ */
/*-
#define SIOCS80211SCAN _IOW('i', 210, struct ifreq)
+#define SIOCS80211JOIN _IOWR('i', 255, struct ifreq)
+#define SIOCG80211JOIN _IOWR('i', 256, struct ifreq)
+
+/* join is pointed at by ifr.ifr_data */
+struct ieee80211_join {
+ u_int8_t i_len; /* length of i_nwid */
+ u_int8_t i_nwid[IEEE80211_NWID_LEN];
+ u_int32_t i_flags;
+
+ struct ieee80211_wpapsk i_wpapsk;
+ struct ieee80211_nwkey i_nwkey;
+};
+
+#define IEEE80211_JOIN_SHOW 0x01
+#define IEEE80211_JOIN_FOUND 0x02
+#define IEEE80211_JOIN_DEL 0x04
+#define IEEE80211_JOIN_NWKEY 0x08
+#define IEEE80211_JOIN_WPA 0x10
+
/* node and requests */
struct ieee80211_nodereq {
char nr_ifname[IFNAMSIZ]; /* e.g. "ath0" */
-/* $OpenBSD: ieee80211_node.c,v 1.129 2018/04/28 14:49:07 stsp Exp $ */
+/* $OpenBSD: ieee80211_node.c,v 1.130 2018/07/11 20:18:09 phessler Exp $ */
/* $NetBSD: ieee80211_node.c,v 1.14 2004/05/09 09:18:47 dyoung Exp $ */
/*-
const struct ieee80211_node *);
int ieee80211_node_checkrssi(struct ieee80211com *,
const struct ieee80211_node *);
+int ieee80211_ess_is_better(struct ieee80211com *ic, struct ieee80211_node *,
+ struct ieee80211_node *);
void ieee80211_setup_node(struct ieee80211com *, struct ieee80211_node *,
const u_int8_t *);
void ieee80211_free_node(struct ieee80211com *, struct ieee80211_node *);
}
#endif
+/*
+ * For debug purposes
+ */
+void
+ieee80211_print_ess(struct ieee80211_ess *ess)
+{
+ ieee80211_print_essid(ess->essid, ess->esslen);
+ if (ess->flags & IEEE80211_F_RSNON) {
+ printf(" wpa");
+ if (ess->rsnprotos & IEEE80211_PROTO_RSN)
+ printf(",wpa2");
+ if (ess->rsnprotos & IEEE80211_PROTO_WPA)
+ printf(",wpa1");
+
+ if (ess->rsnakms & IEEE80211_AKM_8021X ||
+ ess->rsnakms & IEEE80211_AKM_SHA256_8021X)
+ printf(",802.1x");
+ printf(" ");
+
+ if (ess->rsnciphers & IEEE80211_CIPHER_USEGROUP)
+ printf("usegroup");
+ if (ess->rsnciphers & IEEE80211_CIPHER_WEP40)
+ printf("wep40");
+ if (ess->rsnciphers & IEEE80211_CIPHER_WEP104)
+ printf("wep104");
+ if (ess->rsnciphers & IEEE80211_CIPHER_TKIP)
+ printf("tkip");
+ if (ess->rsnciphers & IEEE80211_CIPHER_CCMP)
+ printf("ccmp");
+ }
+ if (ess->flags & IEEE80211_F_WEPON) {
+ int i = ess->def_txkey;
+
+ printf(" wep,");
+ if (ess->nw_keys[i].k_cipher & IEEE80211_CIPHER_WEP40)
+ printf("wep40");
+ if (ess->nw_keys[i].k_cipher & IEEE80211_CIPHER_WEP104)
+ printf("wep104");
+ }
+ if (ess->flags == 0)
+ printf(" clear");
+ printf("\n");
+}
+
+void
+ieee80211_print_ess_list(struct ieee80211com *ic)
+{
+ struct ifnet *ifp = &ic->ic_if;
+ struct ieee80211_ess *ess;
+
+ printf("%s: known networks\n", ifp->if_xname);
+ TAILQ_FOREACH(ess, &ic->ic_ess, ess_next) {
+ ieee80211_print_ess(ess);
+ }
+}
+
+void
+ieee80211_del_ess(struct ieee80211com *ic, char *nwid, int all)
+{
+ struct ieee80211_ess *ess, *next;
+
+ TAILQ_FOREACH_SAFE(ess, &ic->ic_ess, ess_next, next) {
+ if (all == 1 || (memcmp(ess->essid, nwid,
+ IEEE80211_NWID_LEN) == 0)) {
+ TAILQ_REMOVE(&ic->ic_ess, ess, ess_next);
+ explicit_bzero(ess, sizeof(*ess));
+ free(ess, M_DEVBUF, sizeof(*ess));
+ if (all != 1)
+ return;
+ }
+ }
+
+}
+
+int
+ieee80211_add_ess(struct ieee80211com *ic, char *nwid, int wpa, int wep)
+{
+ struct ieee80211_ess *ess;
+ int i = 0, new = 0, ness = 0;
+
+ /* Don't save an empty nwid */
+ if (strnlen(nwid, IEEE80211_NWID_LEN) == 0)
+ return (0);
+
+ TAILQ_FOREACH(ess, &ic->ic_ess, ess_next) {
+ if (memcmp(ess->essid, nwid, IEEE80211_NWID_LEN) == 0)
+ break;
+ ness++;
+ }
+
+ KASSERTMSG(wpa == 0 || wep == 0,
+ "%s: both wpa and wep are configured", __func__);
+
+ if (ess == NULL) {
+ /* if not found, and wpa/wep are set, then return */
+ if (wpa != 0 || wep != 0) {
+ return (ENOENT);
+ }
+ if (ness > IEEE80211_CACHE_SIZE)
+ return (ERANGE);
+ new = 1;
+ ess = malloc(sizeof(*ess), M_DEVBUF, M_NOWAIT|M_ZERO);
+ if (ess == NULL)
+ return (ENOMEM);
+ }
+
+ memcpy(ess->essid, nwid, ic->ic_des_esslen);
+ ess->esslen = ic->ic_des_esslen;
+
+ if (wpa) {
+ if (ic->ic_flags & (IEEE80211_F_RSNON|IEEE80211_F_PSK)) {
+ ess->flags = IEEE80211_F_RSNON;
+ if (ic->ic_flags & IEEE80211_F_PSK)
+ ess->flags |= IEEE80211_F_PSK;
+ explicit_bzero(ess->psk, sizeof(ess->psk));
+ memcpy(ess->psk, ic->ic_psk, IEEE80211_PMK_LEN);
+ ess->rsnprotos = ic->ic_rsnprotos;
+ ess->rsnakms = ic->ic_rsnakms;
+ ess->rsngroupcipher = ic->ic_rsngroupcipher;
+ ess->rsnciphers = ic->ic_rsnciphers;
+
+ /* Disable WEP */
+ for (i = 0; i < IEEE80211_WEP_NKID; i++) {
+ explicit_bzero(&ess->nw_keys[i],
+ sizeof(ess->nw_keys[0]));
+ }
+ ess->def_txkey = 0;
+ ess->flags &= ~IEEE80211_F_WEPON;
+ } else {
+ /* Disable WPA */
+ ess->rsnprotos = ess->rsnakms =
+ ess->rsngroupcipher = ess->rsnciphers = 0;
+ explicit_bzero(ess->psk, sizeof(ess->psk));
+ ess->flags &= ~(IEEE80211_F_PSK | IEEE80211_F_RSNON);
+ }
+ } else if (wep) {
+ if (ic->ic_flags & IEEE80211_F_WEPON) {
+ struct ieee80211_key *k;
+ int i;
+
+ ess->flags = IEEE80211_F_WEPON;
+ for (i = 0; i < IEEE80211_WEP_NKID; i++) {
+ memcpy(&ess->nw_keys[i], &ic->ic_nw_keys[i],
+ sizeof(struct ieee80211_key));
+ k = &ic->ic_nw_keys[i];
+ k->k_priv = NULL;
+ }
+ ess->def_txkey = ic->ic_def_txkey;
+
+ /* Disable WPA */
+ ess->rsnprotos = ess->rsnakms =
+ ess->rsngroupcipher = ess->rsnciphers = 0;
+ explicit_bzero(ess->psk, sizeof(ess->psk));
+ ess->flags &= ~(IEEE80211_F_PSK | IEEE80211_F_RSNON);
+ } else {
+ /* Disable WEP */
+ for (i = 0; i < IEEE80211_WEP_NKID; i++) {
+ explicit_bzero(&ess->nw_keys[i],
+ sizeof(ess->nw_keys[0]));
+ }
+ ess->def_txkey = 0;
+ ess->flags &= ~IEEE80211_F_WEPON;
+ }
+ }
+
+ if (new)
+ TAILQ_INSERT_TAIL(&ic->ic_ess, ess, ess_next);
+
+ return (0);
+}
+
+int
+ieee80211_ess_is_better(struct ieee80211com *ic, struct ieee80211_node *nicur,
+ struct ieee80211_node *selni)
+{
+ uint8_t min_5ghz_rssi;
+
+ if (ic->ic_max_rssi)
+ min_5ghz_rssi = IEEE80211_RSSI_THRES_RATIO_5GHZ;
+ else
+ min_5ghz_rssi = (uint8_t)IEEE80211_RSSI_THRES_5GHZ;
+
+ if (selni == NULL)
+ return 1;
+
+ /* First 5GHz with acceptable signal */
+ if ((IEEE80211_IS_CHAN_5GHZ(nicur->ni_chan) &&
+ !IEEE80211_IS_CHAN_5GHZ(selni->ni_chan)) &&
+ nicur->ni_rssi > min_5ghz_rssi)
+ return 1;
+
+ /* Prefer 5GHz N over not-N */
+ if ((IEEE80211_IS_CHAN_5GHZ(nicur->ni_chan) &&
+ nicur->ni_rssi > min_5ghz_rssi) &&
+ ieee80211_node_supports_ht(nicur))
+ return 1;
+
+ /* Settle for just N */
+ if (ieee80211_node_supports_ht(nicur) &&
+ !ieee80211_node_supports_ht(selni))
+ return 1;
+
+ /* Last resort of best rssi */
+ if (nicur->ni_rssi > selni->ni_rssi)
+ return 1;
+
+ return 0;
+}
+
+int
+ieee80211_match_ess(struct ieee80211com *ic)
+{
+ struct ifnet *ifp = &ic->ic_if;
+ struct ieee80211_ess *ess, *seless = NULL;
+ struct ieee80211_node *ni, *selni = NULL;
+
+ if (!ISSET(ifp->if_flags, IFF_RUNNING))
+ return (0);
+
+ /*
+ * Apple's iOS uses the algorithm described at
+ * https://support.apple.com/en-us/HT202831
+ *
+ * basically:
+ * last network recently joined
+ * then strongest security
+ * then rssi level
+ */
+
+ /* skip if it's the same network */
+ TAILQ_FOREACH(ess, &ic->ic_ess, ess_next) {
+ if (LINK_STATE_IS_UP(ifp->if_link_state) &&
+ ess->esslen == ic->ic_des_esslen &&
+ (memcmp(ic->ic_des_essid, ess->essid,
+ IEEE80211_NWID_LEN) == 0)) {
+ if (ifp->if_flags & IFF_DEBUG) {
+ printf(" %s: staying on ",
+ ifp->if_xname);
+ ieee80211_print_essid(ess->essid, ess->esslen);
+ printf("\n");
+ }
+ return (0);
+ }
+ }
+
+ TAILQ_FOREACH(ess, &ic->ic_ess, ess_next) {
+ RBT_FOREACH(ni, ieee80211_tree, &ic->ic_tree) {
+ if (memcmp(ess->essid, ni->ni_essid,
+ IEEE80211_NWID_LEN) != 0 ||
+ ni->ni_fails != 0)
+ continue;
+
+ if (selni == NULL ||
+ ieee80211_ess_is_better(ic, ni, selni) > 1) {
+ seless = ess;
+ selni = ni;
+ }
+ }
+ }
+
+ if (seless && !(seless->esslen == ic->ic_des_esslen &&
+ (memcmp(ic->ic_des_essid, seless->essid,
+ IEEE80211_NWID_LEN) == 0))) {
+ ieee80211_set_ess(ic, seless->essid);
+ return (1);
+ }
+
+ return (0);
+}
+void
+ieee80211_set_ess(struct ieee80211com *ic, char *nwid)
+{
+ struct ifnet *ifp = &ic->ic_if;
+ struct ieee80211_ess *ess;
+
+ TAILQ_FOREACH(ess, &ic->ic_ess, ess_next) {
+ if (memcmp(ess->essid, nwid, IEEE80211_NWID_LEN) == 0)
+ break;
+ }
+
+ if (ess == NULL)
+ return;
+
+ memset(ic->ic_des_essid, 0, IEEE80211_NWID_LEN);
+ ic->ic_des_esslen = ess->esslen;
+ memcpy(ic->ic_des_essid, ess->essid, ic->ic_des_esslen);
+
+ ieee80211_disable_wep(ic);
+ ieee80211_disable_rsn(ic);
+ if (ess->flags & IEEE80211_F_RSNON) {
+ explicit_bzero(ic->ic_psk, sizeof(ic->ic_psk));
+ memcpy(ic->ic_psk, ess->psk, sizeof(ic->ic_psk));
+
+ ic->ic_rsnprotos = ess->rsnprotos;
+ ic->ic_rsnakms = ess->rsnakms;
+ ic->ic_rsngroupcipher = ess->rsngroupcipher;
+ ic->ic_rsnciphers = ess->rsnciphers;
+ ic->ic_flags |= IEEE80211_F_RSNON;
+ if (ess->flags & IEEE80211_F_PSK)
+ ic->ic_flags |= IEEE80211_F_PSK;
+ } else if (ess->flags & IEEE80211_F_WEPON) {
+ struct ieee80211_key *k;
+ int i;
+
+ for (i = 0; i < IEEE80211_WEP_NKID; i++) {
+ k = &ic->ic_nw_keys[i];
+ if (k->k_cipher != IEEE80211_CIPHER_NONE)
+ (*ic->ic_delete_key)(ic, NULL, k);
+ memcpy(&ic->ic_nw_keys[i], &ess->nw_keys[i],
+ sizeof(struct ieee80211_key));
+ (*ic->ic_set_key)(ic, NULL, k);
+ }
+ ic->ic_def_txkey = ess->def_txkey;
+ ic->ic_flags |= IEEE80211_F_WEPON;
+ }
+
+ /* join the (new) ess station */
+ if (ISSET(ifp->if_flags, IFF_RUNNING)) {
+ ieee80211_new_state(ic, IEEE80211_S_AUTH, -1);
+ ieee80211_media_change(ifp);
+ }
+
+ return;
+}
+
void
ieee80211_node_attach(struct ifnet *ifp)
{
ieee80211_node_cache_timeout, ic);
}
#endif
+ TAILQ_INIT(&ic->ic_ess);
}
struct ieee80211_node *
(*ic->ic_node_free)(ic, ic->ic_bss);
ic->ic_bss = NULL;
}
+ ieee80211_del_ess(ic, NULL, 1);
ieee80211_free_allnodes(ic, 1);
#ifndef IEEE80211_STA_ONLY
free(ic->ic_aid_bitmap, M_DEVBUF,
return;
}
+ /* Possibly switch which ssid we are associated with */
+ if (!bgscan)
+ ieee80211_match_ess(ic);
+
for (; ni != NULL; ni = nextbs) {
nextbs = RBT_NEXT(ieee80211_tree, ni);
if (ni->ni_fails) {
return (memcmp(b1->ni_macaddr, b2->ni_macaddr, IEEE80211_ADDR_LEN));
}
+/*
+ * Compare nodes in the tree by essid
+ */
+int
+ieee80211_ess_cmp(const struct ieee80211_ess_rbt *b1,
+ const struct ieee80211_ess_rbt *b2)
+{
+ return (memcmp(b1->essid, b2->essid, IEEE80211_NWID_LEN));
+}
+
/*
* Generate red-black tree function logic
*/
RBT_GENERATE(ieee80211_tree, ieee80211_node, ni_node, ieee80211_node_cmp);
+RBT_GENERATE(ieee80211_ess_tree, ieee80211_ess_rbt, ess_rbt, ieee80211_ess_cmp);
-/* $OpenBSD: ieee80211_node.h,v 1.74 2018/04/28 14:49:07 stsp Exp $ */
+/* $OpenBSD: ieee80211_node.h,v 1.75 2018/07/11 20:18:09 phessler Exp $ */
/* $NetBSD: ieee80211_node.h,v 1.9 2004/04/30 22:57:32 dyoung Exp $ */
/*-
RBT_HEAD(ieee80211_tree, ieee80211_node);
+struct ieee80211_ess_rbt {
+ RBT_ENTRY(ieee80211_ess_rbt) ess_rbt;
+ u_int8_t esslen;
+ u_int8_t essid[IEEE80211_NWID_LEN];
+ struct ieee80211_node *ni2;
+ struct ieee80211_node *ni5;
+ struct ieee80211_node *ni;
+};
+
+RBT_HEAD(ieee80211_ess_tree, ieee80211_ess_rbt);
+
static inline void
ieee80211_node_incref(struct ieee80211_node *ni)
{
int ieee80211_node_cmp(const struct ieee80211_node *,
const struct ieee80211_node *);
+int ieee80211_ess_cmp(const struct ieee80211_ess_rbt *,
+ const struct ieee80211_ess_rbt *);
RBT_PROTOTYPE(ieee80211_tree, ieee80211_node, ni_node, ieee80211_node_cmp);
+RBT_PROTOTYPE(ieee80211_ess_tree, ieee80211_ess_rbt, ess_rbt, ieee80211_ess_cmp);
#endif /* _NET80211_IEEE80211_NODE_H_ */
-/* $OpenBSD: ieee80211_var.h,v 1.85 2018/04/26 12:50:07 pirofti Exp $ */
+/* $OpenBSD: ieee80211_var.h,v 1.86 2018/07/11 20:18:09 phessler Exp $ */
/* $NetBSD: ieee80211_var.h,v 1.7 2004/05/06 03:07:10 dyoung Exp $ */
/*-
u_int8_t ic_aselcaps;
u_int8_t ic_dialog_token;
int ic_fixed_mcs;
+ TAILQ_HEAD(, ieee80211_ess) ic_ess;
};
#define ic_if ic_ac.ac_if
#define ic_softc ic_if.if_softc
LIST_HEAD(ieee80211com_head, ieee80211com);
extern struct ieee80211com_head ieee80211com_head;
+/* list of APs we want to automatically use */
+/* all data is copied from struct ieee80211com */
+struct ieee80211_ess {
+ /* nwid */
+ int esslen;
+ u_int8_t essid[IEEE80211_NWID_LEN];
+
+ /* clear/wep/wpa */
+ u_int32_t flags;
+
+ /* nwkey */
+ struct ieee80211_key nw_keys[IEEE80211_GROUP_NKID];
+ int def_txkey;
+
+ /* wpakey */
+ u_int8_t psk[IEEE80211_PMK_LEN];
+ u_int rsnprotos;
+ u_int rsnakms;
+ u_int rsnciphers;
+ enum ieee80211_cipher rsngroupcipher;
+
+ TAILQ_ENTRY(ieee80211_ess) ess_next;
+};
+
#define IEEE80211_ADDR_EQ(a1,a2) (memcmp(a1,a2,IEEE80211_ADDR_LEN) == 0)
#define IEEE80211_ADDR_COPY(dst,src) memcpy(dst,src,IEEE80211_ADDR_LEN)
const struct ieee80211_channel *);
void ieee80211_disable_wep(struct ieee80211com *);
void ieee80211_disable_rsn(struct ieee80211com *);
+int ieee80211_add_ess(struct ieee80211com *, char *, int, int);
+void ieee80211_del_ess(struct ieee80211com *, char *, int);
+void ieee80211_set_ess(struct ieee80211com *, char *);
extern int ieee80211_cache_size;