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_PSK | 66 WPA_DRIVER_FLAGS_4WAY_HANDSHAKE_8021X; 67 return 0; 68 } 69 70 71 static int 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 (key_len > IEEE80211_PMK_LEN || 81 (key_flag & KEY_FLAG_PMK_MASK) != KEY_FLAG_PMK) { 82 return -1; 83 84 memset(&keyavail, 0, sizeof(keyavail)); 85 os_strlcpy(keyavail.i_name, drv->ifname, sizeof(keyavail.i_name)); 86 if (wpa_driver_openbsd_get_bssid(priv, keyavail.i_macaddr) < 0) 87 return -1; 88 memcpy(keyavail.i_key, key, key_len); 89 90 if (ioctl(drv->sock, SIOCS80211KEYAVAIL, &keyavail) < 0) 91 return -1; 92 93 return 0; 94 } 95 96 static void * 97 wpa_driver_openbsd_init(void *ctx, const char *ifname) 98 { 99 struct openbsd_driver_data *drv; 100 101 drv = os_zalloc(sizeof(*drv)); 102 if (drv == NULL) 103 return NULL; 104 105 drv->sock = socket(PF_INET, SOCK_DGRAM, 0); 106 if (drv->sock < 0) 107 goto fail; 108 109 drv->ctx = ctx; 110 os_strlcpy(drv->ifname, ifname, sizeof(drv->ifname)); 111 112 return drv; 113 114 fail: 115 os_free(drv); 116 return NULL; 117 } 118 119 120 static void 121 wpa_driver_openbsd_deinit(void *priv) 122 { 123 struct openbsd_driver_data *drv = priv; 124 125 close(drv->sock); 126 os_free(drv); 127 } 128 129 130 const struct wpa_driver_ops wpa_driver_openbsd_ops = { 131 .name = "openbsd", 132 .desc = "OpenBSD 802.11 support", 133 .get_ssid = wpa_driver_openbsd_get_ssid, 134 .get_bssid = wpa_driver_openbsd_get_bssid, 135 .get_capa = wpa_driver_openbsd_get_capa, 136 .set_key = wpa_driver_openbsd_set_key, 137 .init = wpa_driver_openbsd_init, 138 .deinit = wpa_driver_openbsd_deinit, 139 }; 140