14b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt/* 24b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt * Driver interaction with OpenBSD net80211 layer 34b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt * Copyright (c) 2013, Mark Kettenis 44b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt * 54b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt * This software may be distributed under the terms of the BSD license. 64b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt * See README for more details. 74b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt */ 84b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt 94b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt#include "includes.h" 104b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt#include <sys/ioctl.h> 114b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt 124b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt#include <net/if.h> 134b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt#include <net80211/ieee80211.h> 144b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt#include <net80211/ieee80211_crypto.h> 154b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt#include <net80211/ieee80211_ioctl.h> 164b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt 174b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt#include "common.h" 184b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt#include "driver.h" 194b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt 204b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidtstruct openbsd_driver_data { 214b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt char ifname[IFNAMSIZ + 1]; 224b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt void *ctx; 234b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt 244b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt int sock; /* open socket for 802.11 ioctls */ 254b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt}; 264b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt 274b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt 284b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidtstatic int 294b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidtwpa_driver_openbsd_get_ssid(void *priv, u8 *ssid) 304b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt{ 314b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt struct openbsd_driver_data *drv = priv; 324b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt struct ieee80211_nwid nwid; 334b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt struct ifreq ifr; 344b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt 354b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt os_memset(&ifr, 0, sizeof(ifr)); 364b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt os_strlcpy(ifr.ifr_name, drv->ifname, sizeof(ifr.ifr_name)); 374b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt ifr.ifr_data = (void *)&nwid; 384b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt if (ioctl(drv->sock, SIOCG80211NWID, &ifr) < 0 || 394b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt nwid.i_len > IEEE80211_NWID_LEN) 404b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt return -1; 414b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt 424b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt os_memcpy(ssid, nwid.i_nwid, nwid.i_len); 434b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt return nwid.i_len; 444b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt} 454b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt 464b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidtstatic int 474b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidtwpa_driver_openbsd_get_bssid(void *priv, u8 *bssid) 484b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt{ 494b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt struct openbsd_driver_data *drv = priv; 504b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt struct ieee80211_bssid id; 514b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt 524b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt os_strlcpy(id.i_name, drv->ifname, sizeof(id.i_name)); 534b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt if (ioctl(drv->sock, SIOCG80211BSSID, &id) < 0) 544b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt return -1; 554b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt 564b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt os_memcpy(bssid, id.i_bssid, IEEE80211_ADDR_LEN); 574b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt return 0; 584b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt} 594b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt 604b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt 614b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidtstatic int 624b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidtwpa_driver_openbsd_get_capa(void *priv, struct wpa_driver_capa *capa) 634b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt{ 644b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt os_memset(capa, 0, sizeof(*capa)); 654b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt capa->flags = WPA_DRIVER_FLAGS_4WAY_HANDSHAKE; 664b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt return 0; 674b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt} 684b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt 694b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt 704b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidtstatic int 714b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidtwpa_driver_openbsd_set_key(const char *ifname, void *priv, enum wpa_alg alg, 724b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt const unsigned char *addr, int key_idx, int set_tx, const u8 *seq, 734b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt size_t seq_len, const u8 *key, size_t key_len) 744b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt{ 754b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt struct openbsd_driver_data *drv = priv; 764b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt struct ieee80211_keyavail keyavail; 774b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt 784b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt if (alg != WPA_ALG_PMK || key_len > IEEE80211_PMK_LEN) 794b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt return -1; 804b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt 814b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt memset(&keyavail, 0, sizeof(keyavail)); 824b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt os_strlcpy(keyavail.i_name, drv->ifname, sizeof(keyavail.i_name)); 834b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt if (wpa_driver_openbsd_get_bssid(priv, keyavail.i_macaddr) < 0) 844b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt return -1; 854b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt memcpy(keyavail.i_key, key, key_len); 864b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt 874b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt if (ioctl(drv->sock, SIOCS80211KEYAVAIL, &keyavail) < 0) 884b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt return -1; 894b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt 904b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt return 0; 914b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt} 924b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt 934b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidtstatic void * 944b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidtwpa_driver_openbsd_init(void *ctx, const char *ifname) 954b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt{ 964b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt struct openbsd_driver_data *drv; 974b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt 984b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt drv = os_zalloc(sizeof(*drv)); 994b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt if (drv == NULL) 1004b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt return NULL; 1014b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt 1024b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt drv->sock = socket(PF_INET, SOCK_DGRAM, 0); 1034b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt if (drv->sock < 0) 1044b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt goto fail; 1054b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt 1064b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt drv->ctx = ctx; 1074b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt os_strlcpy(drv->ifname, ifname, sizeof(drv->ifname)); 1084b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt 1094b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt return drv; 1104b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt 1114b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidtfail: 1124b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt os_free(drv); 1134b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt return NULL; 1144b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt} 1154b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt 1164b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt 1174b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidtstatic void 1184b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidtwpa_driver_openbsd_deinit(void *priv) 1194b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt{ 1204b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt struct openbsd_driver_data *drv = priv; 1214b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt 1224b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt close(drv->sock); 1234b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt os_free(drv); 1244b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt} 1254b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt 1264b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt 1274b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidtconst struct wpa_driver_ops wpa_driver_openbsd_ops = { 1284b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt .name = "openbsd", 1294b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt .desc = "OpenBSD 802.11 support", 1304b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt .get_ssid = wpa_driver_openbsd_get_ssid, 1314b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt .get_bssid = wpa_driver_openbsd_get_bssid, 1324b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt .get_capa = wpa_driver_openbsd_get_capa, 1334b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt .set_key = wpa_driver_openbsd_set_key, 1344b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt .init = wpa_driver_openbsd_init, 1354b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt .deinit = wpa_driver_openbsd_deinit, 1364b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt}; 137