Home | History | Annotate | Download | only in drivers
      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
     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
     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
     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;
     66 	return 0;
     67 }
     68 
     69 
     70 static int
     71 wpa_driver_openbsd_set_key(const char *ifname, void *priv, enum wpa_alg alg,
     72 	    const unsigned char *addr, int key_idx, int set_tx, const u8 *seq,
     73 	    size_t seq_len, const u8 *key, size_t key_len)
     74 {
     75 	struct openbsd_driver_data *drv = priv;
     76 	struct ieee80211_keyavail keyavail;
     77 
     78 	if (alg != WPA_ALG_PMK || key_len > IEEE80211_PMK_LEN)
     79 		return -1;
     80 
     81 	memset(&keyavail, 0, sizeof(keyavail));
     82 	os_strlcpy(keyavail.i_name, drv->ifname, sizeof(keyavail.i_name));
     83 	if (wpa_driver_openbsd_get_bssid(priv, keyavail.i_macaddr) < 0)
     84 		return -1;
     85 	memcpy(keyavail.i_key, key, key_len);
     86 
     87 	if (ioctl(drv->sock, SIOCS80211KEYAVAIL, &keyavail) < 0)
     88 		return -1;
     89 
     90 	return 0;
     91 }
     92 
     93 static void *
     94 wpa_driver_openbsd_init(void *ctx, const char *ifname)
     95 {
     96 	struct openbsd_driver_data *drv;
     97 
     98 	drv = os_zalloc(sizeof(*drv));
     99 	if (drv == NULL)
    100 		return NULL;
    101 
    102 	drv->sock = socket(PF_INET, SOCK_DGRAM, 0);
    103 	if (drv->sock < 0)
    104 		goto fail;
    105 
    106 	drv->ctx = ctx;
    107 	os_strlcpy(drv->ifname, ifname, sizeof(drv->ifname));
    108 
    109 	return drv;
    110 
    111 fail:
    112 	os_free(drv);
    113 	return NULL;
    114 }
    115 
    116 
    117 static void
    118 wpa_driver_openbsd_deinit(void *priv)
    119 {
    120 	struct openbsd_driver_data *drv = priv;
    121 
    122 	close(drv->sock);
    123 	os_free(drv);
    124 }
    125 
    126 
    127 const struct wpa_driver_ops wpa_driver_openbsd_ops = {
    128 	.name = "openbsd",
    129 	.desc = "OpenBSD 802.11 support",
    130 	.get_ssid = wpa_driver_openbsd_get_ssid,
    131 	.get_bssid = wpa_driver_openbsd_get_bssid,
    132 	.get_capa = wpa_driver_openbsd_get_capa,
    133 	.set_key = wpa_driver_openbsd_set_key,
    134 	.init = wpa_driver_openbsd_init,
    135 	.deinit = wpa_driver_openbsd_deinit,
    136 };
    137