1 /*
2 * Driver interaction with OpenBSD net80211 layer
3 * Copyright (c) 2013, Mark Kettenis
4 *
5 * This software may be distributed under the terms of the BSD license.
6 * See README for more details.
7 */
8
9 #include "includes.h"
10 #include <sys/ioctl.h>
11
12 #include <net/if.h>
13 #include <net80211/ieee80211.h>
14 #include <net80211/ieee80211_crypto.h>
15 #include <net80211/ieee80211_ioctl.h>
16
17 #include "common.h"
18 #include "driver.h"
19
20 struct openbsd_driver_data {
21 char ifname[IFNAMSIZ + 1];
22 void *ctx;
23
24 int sock; /* open socket for 802.11 ioctls */
25 };
26
27
28 static int
wpa_driver_openbsd_get_ssid(void * priv,u8 * ssid)29 wpa_driver_openbsd_get_ssid(void *priv, u8 *ssid)
30 {
31 struct openbsd_driver_data *drv = priv;
32 struct ieee80211_nwid nwid;
33 struct ifreq ifr;
34
35 os_memset(&ifr, 0, sizeof(ifr));
36 os_strlcpy(ifr.ifr_name, drv->ifname, sizeof(ifr.ifr_name));
37 ifr.ifr_data = (void *)&nwid;
38 if (ioctl(drv->sock, SIOCG80211NWID, &ifr) < 0 ||
39 nwid.i_len > IEEE80211_NWID_LEN)
40 return -1;
41
42 os_memcpy(ssid, nwid.i_nwid, nwid.i_len);
43 return nwid.i_len;
44 }
45
46 static int
wpa_driver_openbsd_get_bssid(void * priv,u8 * bssid)47 wpa_driver_openbsd_get_bssid(void *priv, u8 *bssid)
48 {
49 struct openbsd_driver_data *drv = priv;
50 struct ieee80211_bssid id;
51
52 os_strlcpy(id.i_name, drv->ifname, sizeof(id.i_name));
53 if (ioctl(drv->sock, SIOCG80211BSSID, &id) < 0)
54 return -1;
55
56 os_memcpy(bssid, id.i_bssid, IEEE80211_ADDR_LEN);
57 return 0;
58 }
59
60
61 static int
wpa_driver_openbsd_get_capa(void * priv,struct wpa_driver_capa * capa)62 wpa_driver_openbsd_get_capa(void *priv, struct wpa_driver_capa *capa)
63 {
64 os_memset(capa, 0, sizeof(*capa));
65 capa->flags = WPA_DRIVER_FLAGS_4WAY_HANDSHAKE_PSK |
66 WPA_DRIVER_FLAGS_4WAY_HANDSHAKE_8021X;
67 return 0;
68 }
69
70
71 static int
wpa_driver_openbsd_set_key(void * priv,struct wpa_driver_set_key_params * params)72 wpa_driver_openbsd_set_key(void *priv, struct wpa_driver_set_key_params *params)
73 {
74 struct openbsd_driver_data *drv = priv;
75 struct ieee80211_keyavail keyavail;
76 enum key_flag key_flag = params->key_flag;
77 const u8 *key = params->key;
78 size_t key_len = params->key_len;
79
80 if (params->key_flag & KEY_FLAG_NEXT)
81 return -1;
82
83 if (key_len > IEEE80211_PMK_LEN ||
84 (key_flag & KEY_FLAG_PMK_MASK) != KEY_FLAG_PMK) {
85 return -1;
86
87 memset(&keyavail, 0, sizeof(keyavail));
88 os_strlcpy(keyavail.i_name, drv->ifname, sizeof(keyavail.i_name));
89 if (wpa_driver_openbsd_get_bssid(priv, keyavail.i_macaddr) < 0)
90 return -1;
91 memcpy(keyavail.i_key, key, key_len);
92
93 if (ioctl(drv->sock, SIOCS80211KEYAVAIL, &keyavail) < 0)
94 return -1;
95
96 return 0;
97 }
98
99 static void *
100 wpa_driver_openbsd_init(void *ctx, const char *ifname)
101 {
102 struct openbsd_driver_data *drv;
103
104 drv = os_zalloc(sizeof(*drv));
105 if (drv == NULL)
106 return NULL;
107
108 drv->sock = socket(PF_INET, SOCK_DGRAM, 0);
109 if (drv->sock < 0)
110 goto fail;
111
112 drv->ctx = ctx;
113 os_strlcpy(drv->ifname, ifname, sizeof(drv->ifname));
114
115 return drv;
116
117 fail:
118 os_free(drv);
119 return NULL;
120 }
121
122
123 static void
124 wpa_driver_openbsd_deinit(void *priv)
125 {
126 struct openbsd_driver_data *drv = priv;
127
128 close(drv->sock);
129 os_free(drv);
130 }
131
132
133 const struct wpa_driver_ops wpa_driver_openbsd_ops = {
134 .name = "openbsd",
135 .desc = "OpenBSD 802.11 support",
136 .get_ssid = wpa_driver_openbsd_get_ssid,
137 .get_bssid = wpa_driver_openbsd_get_bssid,
138 .get_capa = wpa_driver_openbsd_get_capa,
139 .set_key = wpa_driver_openbsd_set_key,
140 .init = wpa_driver_openbsd_init,
141 .deinit = wpa_driver_openbsd_deinit,
142 };
143