15b9c547cSRui Paulo /* 25b9c547cSRui Paulo * Driver interaction with OpenBSD net80211 layer 35b9c547cSRui Paulo * Copyright (c) 2013, Mark Kettenis 45b9c547cSRui Paulo * 55b9c547cSRui Paulo * This software may be distributed under the terms of the BSD license. 65b9c547cSRui Paulo * See README for more details. 75b9c547cSRui Paulo */ 85b9c547cSRui Paulo 95b9c547cSRui Paulo #include "includes.h" 105b9c547cSRui Paulo #include <sys/ioctl.h> 115b9c547cSRui Paulo 125b9c547cSRui Paulo #include <net/if.h> 135b9c547cSRui Paulo #include <net80211/ieee80211.h> 145b9c547cSRui Paulo #include <net80211/ieee80211_crypto.h> 155b9c547cSRui Paulo #include <net80211/ieee80211_ioctl.h> 165b9c547cSRui Paulo 175b9c547cSRui Paulo #include "common.h" 185b9c547cSRui Paulo #include "driver.h" 195b9c547cSRui Paulo 205b9c547cSRui Paulo struct openbsd_driver_data { 215b9c547cSRui Paulo char ifname[IFNAMSIZ + 1]; 225b9c547cSRui Paulo void *ctx; 235b9c547cSRui Paulo 245b9c547cSRui Paulo int sock; /* open socket for 802.11 ioctls */ 255b9c547cSRui Paulo }; 265b9c547cSRui Paulo 275b9c547cSRui Paulo 285b9c547cSRui Paulo static int 295b9c547cSRui Paulo wpa_driver_openbsd_get_ssid(void *priv, u8 *ssid) 305b9c547cSRui Paulo { 315b9c547cSRui Paulo struct openbsd_driver_data *drv = priv; 325b9c547cSRui Paulo struct ieee80211_nwid nwid; 335b9c547cSRui Paulo struct ifreq ifr; 345b9c547cSRui Paulo 355b9c547cSRui Paulo os_memset(&ifr, 0, sizeof(ifr)); 365b9c547cSRui Paulo os_strlcpy(ifr.ifr_name, drv->ifname, sizeof(ifr.ifr_name)); 375b9c547cSRui Paulo ifr.ifr_data = (void *)&nwid; 385b9c547cSRui Paulo if (ioctl(drv->sock, SIOCG80211NWID, &ifr) < 0 || 395b9c547cSRui Paulo nwid.i_len > IEEE80211_NWID_LEN) 405b9c547cSRui Paulo return -1; 415b9c547cSRui Paulo 425b9c547cSRui Paulo os_memcpy(ssid, nwid.i_nwid, nwid.i_len); 435b9c547cSRui Paulo return nwid.i_len; 445b9c547cSRui Paulo } 455b9c547cSRui Paulo 465b9c547cSRui Paulo static int 475b9c547cSRui Paulo wpa_driver_openbsd_get_bssid(void *priv, u8 *bssid) 485b9c547cSRui Paulo { 495b9c547cSRui Paulo struct openbsd_driver_data *drv = priv; 505b9c547cSRui Paulo struct ieee80211_bssid id; 515b9c547cSRui Paulo 525b9c547cSRui Paulo os_strlcpy(id.i_name, drv->ifname, sizeof(id.i_name)); 535b9c547cSRui Paulo if (ioctl(drv->sock, SIOCG80211BSSID, &id) < 0) 545b9c547cSRui Paulo return -1; 555b9c547cSRui Paulo 565b9c547cSRui Paulo os_memcpy(bssid, id.i_bssid, IEEE80211_ADDR_LEN); 575b9c547cSRui Paulo return 0; 585b9c547cSRui Paulo } 595b9c547cSRui Paulo 605b9c547cSRui Paulo 615b9c547cSRui Paulo static int 625b9c547cSRui Paulo wpa_driver_openbsd_get_capa(void *priv, struct wpa_driver_capa *capa) 635b9c547cSRui Paulo { 645b9c547cSRui Paulo os_memset(capa, 0, sizeof(*capa)); 65*4bc52338SCy Schubert capa->flags = WPA_DRIVER_FLAGS_4WAY_HANDSHAKE_PSK | 66*4bc52338SCy Schubert WPA_DRIVER_FLAGS_4WAY_HANDSHAKE_8021X; 675b9c547cSRui Paulo return 0; 685b9c547cSRui Paulo } 695b9c547cSRui Paulo 705b9c547cSRui Paulo 715b9c547cSRui Paulo static int 725b9c547cSRui Paulo wpa_driver_openbsd_set_key(const char *ifname, void *priv, enum wpa_alg alg, 735b9c547cSRui Paulo const unsigned char *addr, int key_idx, int set_tx, const u8 *seq, 745b9c547cSRui Paulo size_t seq_len, const u8 *key, size_t key_len) 755b9c547cSRui Paulo { 765b9c547cSRui Paulo struct openbsd_driver_data *drv = priv; 775b9c547cSRui Paulo struct ieee80211_keyavail keyavail; 785b9c547cSRui Paulo 795b9c547cSRui Paulo if (alg != WPA_ALG_PMK || key_len > IEEE80211_PMK_LEN) 805b9c547cSRui Paulo return -1; 815b9c547cSRui Paulo 825b9c547cSRui Paulo memset(&keyavail, 0, sizeof(keyavail)); 835b9c547cSRui Paulo os_strlcpy(keyavail.i_name, drv->ifname, sizeof(keyavail.i_name)); 845b9c547cSRui Paulo if (wpa_driver_openbsd_get_bssid(priv, keyavail.i_macaddr) < 0) 855b9c547cSRui Paulo return -1; 865b9c547cSRui Paulo memcpy(keyavail.i_key, key, key_len); 875b9c547cSRui Paulo 885b9c547cSRui Paulo if (ioctl(drv->sock, SIOCS80211KEYAVAIL, &keyavail) < 0) 895b9c547cSRui Paulo return -1; 905b9c547cSRui Paulo 915b9c547cSRui Paulo return 0; 925b9c547cSRui Paulo } 935b9c547cSRui Paulo 945b9c547cSRui Paulo static void * 955b9c547cSRui Paulo wpa_driver_openbsd_init(void *ctx, const char *ifname) 965b9c547cSRui Paulo { 975b9c547cSRui Paulo struct openbsd_driver_data *drv; 985b9c547cSRui Paulo 995b9c547cSRui Paulo drv = os_zalloc(sizeof(*drv)); 1005b9c547cSRui Paulo if (drv == NULL) 1015b9c547cSRui Paulo return NULL; 1025b9c547cSRui Paulo 1035b9c547cSRui Paulo drv->sock = socket(PF_INET, SOCK_DGRAM, 0); 1045b9c547cSRui Paulo if (drv->sock < 0) 1055b9c547cSRui Paulo goto fail; 1065b9c547cSRui Paulo 1075b9c547cSRui Paulo drv->ctx = ctx; 1085b9c547cSRui Paulo os_strlcpy(drv->ifname, ifname, sizeof(drv->ifname)); 1095b9c547cSRui Paulo 1105b9c547cSRui Paulo return drv; 1115b9c547cSRui Paulo 1125b9c547cSRui Paulo fail: 1135b9c547cSRui Paulo os_free(drv); 1145b9c547cSRui Paulo return NULL; 1155b9c547cSRui Paulo } 1165b9c547cSRui Paulo 1175b9c547cSRui Paulo 1185b9c547cSRui Paulo static void 1195b9c547cSRui Paulo wpa_driver_openbsd_deinit(void *priv) 1205b9c547cSRui Paulo { 1215b9c547cSRui Paulo struct openbsd_driver_data *drv = priv; 1225b9c547cSRui Paulo 1235b9c547cSRui Paulo close(drv->sock); 1245b9c547cSRui Paulo os_free(drv); 1255b9c547cSRui Paulo } 1265b9c547cSRui Paulo 1275b9c547cSRui Paulo 1285b9c547cSRui Paulo const struct wpa_driver_ops wpa_driver_openbsd_ops = { 1295b9c547cSRui Paulo .name = "openbsd", 1305b9c547cSRui Paulo .desc = "OpenBSD 802.11 support", 1315b9c547cSRui Paulo .get_ssid = wpa_driver_openbsd_get_ssid, 1325b9c547cSRui Paulo .get_bssid = wpa_driver_openbsd_get_bssid, 1335b9c547cSRui Paulo .get_capa = wpa_driver_openbsd_get_capa, 1345b9c547cSRui Paulo .set_key = wpa_driver_openbsd_set_key, 1355b9c547cSRui Paulo .init = wpa_driver_openbsd_init, 1365b9c547cSRui Paulo .deinit = wpa_driver_openbsd_deinit, 1375b9c547cSRui Paulo }; 138