-/* $OpenBSD: ifconfig.c,v 1.377 2018/09/08 15:21:03 phessler Exp $ */
+/* $OpenBSD: ifconfig.c,v 1.378 2018/09/09 20:32:55 phessler Exp $ */
/* $NetBSD: ifconfig.c,v 1.40 1997/10/01 02:19:43 enami Exp $ */
/*
struct ifencap;
+struct ieee80211_join join;
+
const char *lacpmodeactive = "active";
const char *lacpmodepassive = "passive";
const char *lacptimeoutfast = "fast";
#define A_MEDIAOPT (A_MEDIAOPTSET|A_MEDIAOPTCLR)
#define A_MEDIAINST 0x0008 /* instance or inst command */
#define A_MEDIAMODE 0x0010 /* mode command */
+#define A_JOIN 0x0020 /* join */
#define A_SILENT 0x8000000 /* doing operation, do not print */
#define NEXTARG0 0xffffff
{ "mtu", NEXTARG, 0, setifmtu },
{ "nwid", NEXTARG, 0, setifnwid },
{ "-nwid", -1, 0, setifnwid },
- { "join", NEXTARG, 0, setifjoin },
+ { "join", NEXTARG, A_JOIN, setifjoin },
{ "-join", NEXTARG, 0, delifjoin },
{ "joinlist", NEXTARG0, 0, showjoin },
{ "-joinlist", -1, 0, delifjoin },
void process_media_commands(void);
void init_current_media(void);
+void process_join_commands(void);
+
unsigned long get_ts_map(int, int, int);
void in_status(int);
return (0);
}
+ process_join_commands();
+
/* Process any media commands that may have been issued. */
process_media_commands();
warn("SIOCS80211NWID");
}
+
+void
+process_join_commands(void)
+{
+ int len;
+
+ if (!(actions & A_JOIN))
+ return;
+
+ ifr.ifr_data = (caddr_t)&join;
+ if (ioctl(s, SIOCS80211JOIN, (caddr_t)&ifr) < 0)
+ warn("SIOCS80211JOIN");
+}
+
void
setifjoin(const char *val, int d)
{
- struct ieee80211_join join;
int len;
if (strlen(nwidname) != 0) {
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");
+
+ actions |= A_JOIN;
}
void
}
}
(void)strlcpy(nwkey.i_name, name, sizeof(nwkey.i_name));
+
+ if (actions & A_JOIN) {
+ memcpy(&join.i_nwkey, &nwkey, sizeof(join.i_nwkey));
+ join.i_flags |= IEEE80211_JOIN_NWKEY;
+ return;
+ }
+
if (ioctl(s, SIOCS80211NWKEY, (caddr_t)&nwkey) == -1)
warn("SIOCS80211NWKEY");
}
(void)strlcpy(wpa.i_name, name, sizeof(wpa.i_name));
/* Don't read current values. The kernel will set defaults. */
wpa.i_enabled = d;
+
+ if (actions & A_JOIN) {
+ memcpy(&join.i_wpaparams, &wpa, sizeof(join.i_wpaparams));
+ join.i_flags |= IEEE80211_JOIN_WPA;
+ return;
+ }
+
if (ioctl(s, SIOCS80211WPAPARMS, (caddr_t)&wpa) < 0)
err(1, "SIOCS80211WPAPARMS");
}
/* Let the kernel set up the appropriate default ciphers. */
wpa.i_ciphers = 0;
wpa.i_groupcipher = 0;
+
+ if (actions & A_JOIN) {
+ memcpy(&join.i_wpaparams, &wpa, sizeof(join.i_wpaparams));
+ join.i_flags |= IEEE80211_JOIN_WPA;
+ return;
+ }
+
if (ioctl(s, SIOCS80211WPAPARMS, (caddr_t)&wpa) < 0)
err(1, "SIOCS80211WPAPARMS");
}
wpa.i_akms = rval;
/* Enable WPA for 802.1x here. PSK case is handled in setifwpakey(). */
wpa.i_enabled = ((rval & IEEE80211_WPA_AKM_8021X) != 0);
+
+ if (actions & A_JOIN) {
+ memcpy(&join.i_wpaparams, &wpa, sizeof(join.i_wpaparams));
+ join.i_flags |= IEEE80211_JOIN_WPA;
+ return;
+ }
+
if (ioctl(s, SIOCS80211WPAPARMS, (caddr_t)&wpa) < 0)
err(1, "SIOCS80211WPAPARMS");
}
if (ioctl(s, SIOCG80211WPAPARMS, (caddr_t)&wpa) < 0)
err(1, "SIOCG80211WPAPARMS");
wpa.i_ciphers = rval;
+
+ if (actions & A_JOIN) {
+ memcpy(&join.i_wpaparams, &wpa, sizeof(join.i_wpaparams));
+ join.i_flags |= IEEE80211_JOIN_WPA;
+ return;
+ }
+
if (ioctl(s, SIOCS80211WPAPARMS, (caddr_t)&wpa) < 0)
err(1, "SIOCS80211WPAPARMS");
}
if (ioctl(s, SIOCG80211WPAPARMS, (caddr_t)&wpa) < 0)
err(1, "SIOCG80211WPAPARMS");
wpa.i_groupcipher = cipher;
+
+ if (actions & A_JOIN) {
+ memcpy(&join.i_wpaparams, &wpa, sizeof(join.i_wpaparams));
+ join.i_flags |= IEEE80211_JOIN_WPA;
+ return;
+ }
+
if (ioctl(s, SIOCS80211WPAPARMS, (caddr_t)&wpa) < 0)
err(1, "SIOCS80211WPAPARMS");
}
psk.i_enabled = 0;
(void)strlcpy(psk.i_name, name, sizeof(psk.i_name));
+
+ if (actions & A_JOIN) {
+ memcpy(&join.i_wpapsk, &psk, sizeof(join.i_wpapsk));
+ join.i_flags |= IEEE80211_JOIN_WPAPSK;
+ if (!join.i_wpaparams.i_enabled)
+ setifwpa(NULL, join.i_wpapsk.i_enabled);
+ return;
+ }
+
if (ioctl(s, SIOCS80211WPAPSK, (caddr_t)&psk) < 0)
err(1, "SIOCS80211WPAPSK");
-/* $OpenBSD: ieee80211_ioctl.c,v 1.64 2018/09/01 08:20:56 stsp Exp $ */
+/* $OpenBSD: ieee80211_ioctl.c,v 1.65 2018/09/09 20:32:55 phessler Exp $ */
/* $NetBSD: ieee80211_ioctl.c,v 1.15 2004/05/06 02:58:16 dyoung Exp $ */
/*-
ic->ic_rsnciphers = 0;
}
+/* Keep in sync with ieee80211_node.c:ieee80211_ess_setnwkeys() */
static int
ieee80211_ioctl_setnwkeys(struct ieee80211com *ic,
const struct ieee80211_nwkey *nwkey)
return 0;
}
+/* Keep in sync with ieee80211_node.c:ieee80211_ess_setwpaparms() */
static int
ieee80211_ioctl_setwpaparms(struct ieee80211com *ic,
const struct ieee80211_wpaparams *wpa)
}
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)) {
- if (ieee80211_add_ess(ic, 0, 0) == 0)
+ if (ieee80211_add_ess(ic, &join) == 0)
ic->ic_flags |= IEEE80211_F_AUTO_JOIN;
}
ieee80211_set_ess(ic, ic->ic_des_essid);
if ((error = suser(curproc)) != 0)
break;
error = ieee80211_ioctl_setnwkeys(ic, (void *)data);
- if (error == ENETRESET)
- ieee80211_add_ess(ic, 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, 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, 1, 0);
error = ENETRESET;
break;
case SIOCG80211WPAPSK:
-/* $OpenBSD: ieee80211_ioctl.h,v 1.33 2018/08/06 11:42:18 benno Exp $ */
+/* $OpenBSD: ieee80211_ioctl.h,v 1.34 2018/09/09 20:32:55 phessler Exp $ */
/* $NetBSD: ieee80211_ioctl.h,v 1.7 2004/04/30 22:51:04 dyoung Exp $ */
/*-
u_int8_t i_nwid[IEEE80211_NWID_LEN];
u_int32_t i_flags;
- struct ieee80211_wpapsk i_wpapsk;
- struct ieee80211_nwkey i_nwkey;
+ struct ieee80211_wpaparams i_wpaparams;
+ struct ieee80211_wpapsk i_wpapsk;
+ struct ieee80211_nwkey i_nwkey;
};
struct ieee80211_joinreq_all {
#define IEEE80211_JOIN_DEL 0x04
#define IEEE80211_JOIN_NWKEY 0x08
#define IEEE80211_JOIN_WPA 0x10
+#define IEEE80211_JOIN_WPAPSK 0x20
/* node and requests */
struct ieee80211_nodereq {
-/* $OpenBSD: ieee80211_node.c,v 1.144 2018/09/06 11:50:54 jsg Exp $ */
+/* $OpenBSD: ieee80211_node.c,v 1.145 2018/09/09 20:32:55 phessler Exp $ */
/* $NetBSD: ieee80211_node.c,v 1.14 2004/05/09 09:18:47 dyoung Exp $ */
/*-
}
}
+struct ieee80211_ess *
+ieee80211_get_ess(struct ieee80211com *ic, const char *nwid, int len)
+{
+ struct ieee80211_ess *ess;
+
+ TAILQ_FOREACH(ess, &ic->ic_ess, ess_next) {
+ if (len == ess->esslen &&
+ memcmp(ess->essid, nwid, ess->esslen) == 0)
+ return ess;
+ }
+
+ return NULL;
+}
+
void
ieee80211_del_ess(struct ieee80211com *ic, char *nwid, int all)
{
}
}
+/* Keep in sync with ieee80211_ioctl.c:ieee80211_ioctl_setnwkeys() */
+static int
+ieee80211_ess_setnwkeys(struct ieee80211_ess *ess,
+ const struct ieee80211_nwkey *nwkey)
+{
+ struct ieee80211_key *k;
+ int i;
+
+ if (nwkey->i_wepon == IEEE80211_NWKEY_OPEN) {
+ if (!(ess->flags & IEEE80211_F_WEPON))
+ return 0;
+ ess->flags &= ~IEEE80211_F_WEPON;
+ return ENETRESET;
+ }
+ if (nwkey->i_defkid < 1 || nwkey->i_defkid > IEEE80211_WEP_NKID)
+ return EINVAL;
+
+ for (i = 0; i < IEEE80211_WEP_NKID; i++) {
+ if (nwkey->i_key[i].i_keylen == 0 ||
+ nwkey->i_key[i].i_keydat == NULL)
+ continue; /* entry not set */
+ if (nwkey->i_key[i].i_keylen > IEEE80211_KEYBUF_SIZE)
+ return EINVAL;
+
+ /* map wep key to ieee80211_key */
+ k = &ess->nw_keys[i];
+ memset(k, 0, sizeof(*k));
+ if (nwkey->i_key[i].i_keylen <= 5)
+ k->k_cipher = IEEE80211_CIPHER_WEP40;
+ else
+ k->k_cipher = IEEE80211_CIPHER_WEP104;
+ k->k_len = ieee80211_cipher_keylen(k->k_cipher);
+ k->k_flags = IEEE80211_KEY_GROUP | IEEE80211_KEY_TX;
+ }
+ ess->def_txkey = nwkey->i_defkid - 1;
+ ess->flags |= IEEE80211_F_WEPON;
+
+ return ENETRESET;
+}
+
+
+/* Keep in sync with ieee80211_ioctl.c:ieee80211_ioctl_setwpaparms() */
+static int
+ieee80211_ess_setwpaparms(struct ieee80211_ess *ess,
+ const struct ieee80211_wpaparams *wpa)
+{
+ if (!wpa->i_enabled) {
+ if (!(ess->flags & IEEE80211_F_RSNON))
+ return 0;
+ ess->flags &= ~IEEE80211_F_RSNON;
+ ess->rsnprotos = 0;
+ ess->rsnakms = 0;
+ ess->rsngroupcipher = 0;
+ ess->rsnciphers = 0;
+ return ENETRESET;
+ }
+
+ ess->rsnprotos = 0;
+ if (wpa->i_protos & IEEE80211_WPA_PROTO_WPA1)
+ ess->rsnprotos |= IEEE80211_PROTO_WPA;
+ if (wpa->i_protos & IEEE80211_WPA_PROTO_WPA2)
+ ess->rsnprotos |= IEEE80211_PROTO_RSN;
+ if (ess->rsnprotos == 0) /* set to default (RSN) */
+ ess->rsnprotos = IEEE80211_PROTO_RSN;
+
+ ess->rsnakms = 0;
+ if (wpa->i_akms & IEEE80211_WPA_AKM_PSK)
+ ess->rsnakms |= IEEE80211_AKM_PSK;
+ if (wpa->i_akms & IEEE80211_WPA_AKM_SHA256_PSK)
+ ess->rsnakms |= IEEE80211_AKM_SHA256_PSK;
+ if (wpa->i_akms & IEEE80211_WPA_AKM_8021X)
+ ess->rsnakms |= IEEE80211_AKM_8021X;
+ if (wpa->i_akms & IEEE80211_WPA_AKM_SHA256_8021X)
+ ess->rsnakms |= IEEE80211_AKM_SHA256_8021X;
+ if (ess->rsnakms == 0) /* set to default (PSK) */
+ ess->rsnakms = IEEE80211_AKM_PSK;
+
+ if (wpa->i_groupcipher == IEEE80211_WPA_CIPHER_WEP40)
+ ess->rsngroupcipher = IEEE80211_CIPHER_WEP40;
+ else if (wpa->i_groupcipher == IEEE80211_WPA_CIPHER_TKIP)
+ ess->rsngroupcipher = IEEE80211_CIPHER_TKIP;
+ else if (wpa->i_groupcipher == IEEE80211_WPA_CIPHER_CCMP)
+ ess->rsngroupcipher = IEEE80211_CIPHER_CCMP;
+ else if (wpa->i_groupcipher == IEEE80211_WPA_CIPHER_WEP104)
+ ess->rsngroupcipher = IEEE80211_CIPHER_WEP104;
+ else { /* set to default */
+ if (ess->rsnprotos & IEEE80211_PROTO_WPA)
+ ess->rsngroupcipher = IEEE80211_CIPHER_TKIP;
+ else
+ ess->rsngroupcipher = IEEE80211_CIPHER_CCMP;
+ }
+
+ ess->rsnciphers = 0;
+ if (wpa->i_ciphers & IEEE80211_WPA_CIPHER_TKIP)
+ ess->rsnciphers |= IEEE80211_CIPHER_TKIP;
+ if (wpa->i_ciphers & IEEE80211_WPA_CIPHER_CCMP)
+ ess->rsnciphers |= IEEE80211_CIPHER_CCMP;
+ if (wpa->i_ciphers & IEEE80211_WPA_CIPHER_USEGROUP)
+ ess->rsnciphers = IEEE80211_CIPHER_USEGROUP;
+ if (ess->rsnciphers == 0) { /* set to default (CCMP, TKIP if WPA1) */
+ ess->rsnciphers = IEEE80211_CIPHER_CCMP;
+ if (ess->rsnprotos & IEEE80211_PROTO_WPA)
+ ess->rsnciphers |= IEEE80211_CIPHER_TKIP;
+ }
+
+ ess->flags |= IEEE80211_F_RSNON;
+
+ return ENETRESET;
+}
+
int
-ieee80211_add_ess(struct ieee80211com *ic, int wpa, int wep)
+ieee80211_add_ess(struct ieee80211com *ic, struct ieee80211_join *join)
{
struct ieee80211_ess *ess;
int i = 0, new = 0, ness = 0;
return (0);
/* Don't save an empty nwid */
- if (ic->ic_des_esslen == 0)
+ if (join->i_len == 0)
return (0);
TAILQ_FOREACH(ess, &ic->ic_ess, ess_next) {
- if (ess->esslen == ic->ic_des_esslen &&
- memcmp(ess->essid, ic->ic_des_essid, ess->esslen) == 0)
+ if (ess->esslen == join->i_len &&
+ memcmp(ess->essid, join->i_nwid, ess->esslen) == 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 ((join->i_flags & IEEE80211_JOIN_WPA) &&
+ (join->i_flags & IEEE80211_JOIN_NWKEY)) {
+ return (EINVAL);
}
if (ness > IEEE80211_CACHE_SIZE)
return (ERANGE);
ess = malloc(sizeof(*ess), M_DEVBUF, M_NOWAIT|M_ZERO);
if (ess == NULL)
return (ENOMEM);
- memcpy(ess->essid, ic->ic_des_essid, ic->ic_des_esslen);
- ess->esslen = ic->ic_des_esslen;
+ memcpy(ess->essid, join->i_nwid, join->i_len);
+ ess->esslen = join->i_len;
}
- 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;
+ if (join->i_flags & IEEE80211_JOIN_WPA) {
+ if (join->i_wpaparams.i_enabled) {
+ if (!(ic->ic_caps & IEEE80211_C_RSN))
+ return ENODEV;
+ ieee80211_ess_setwpaparms(ess,
+ &join->i_wpaparams);
+ if (join->i_flags & IEEE80211_JOIN_WPAPSK) {
+ ess->flags |= IEEE80211_F_PSK;
+ explicit_bzero(ess->psk, sizeof(ess->psk));
+ memcpy(ess->psk, &join->i_wpapsk.i_psk,
+ sizeof(ess->psk));
+ }
/* Disable WEP */
for (i = 0; i < IEEE80211_WEP_NKID; i++) {
explicit_bzero(&ess->nw_keys[i],
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;
+ } else if (join->i_flags & IEEE80211_JOIN_NWKEY) {
+ if (join->i_nwkey.i_wepon) {
+ if (!(ic->ic_caps & IEEE80211_C_WEP))
+ return ENODEV;
- 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;
+ ieee80211_ess_setnwkeys(ess, &join->i_nwkey);
/* Disable WPA */
ess->rsnprotos = ess->rsnakms =
-/* $OpenBSD: ieee80211_var.h,v 1.88 2018/09/01 08:20:56 stsp Exp $ */
+/* $OpenBSD: ieee80211_var.h,v 1.89 2018/09/09 20:32:55 phessler Exp $ */
/* $NetBSD: ieee80211_var.h,v 1.7 2004/05/06 03:07:10 dyoung Exp $ */
/*-
const struct ieee80211_channel *);
void ieee80211_disable_wep(struct ieee80211com *);
void ieee80211_disable_rsn(struct ieee80211com *);
-int ieee80211_add_ess(struct ieee80211com *, int, int);
+int ieee80211_add_ess(struct ieee80211com *, struct ieee80211_join *);
void ieee80211_del_ess(struct ieee80211com *, char *, int);
void ieee80211_set_ess(struct ieee80211com *, char *);
+struct ieee80211_ess *ieee80211_get_ess(struct ieee80211com *, const char *, int);
extern int ieee80211_cache_size;