📄 driver_bsd.c
字号:
/* * hostapd / Driver interaction with BSD net80211 layer * Copyright (c) 2004, Sam Leffler <sam@errno.com> * Copyright (c) 2004, 2Wire, Inc * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * * Alternatively, this software may be distributed under the terms of BSD * license. * * See README and COPYING for more details. */#include "includes.h"#include <sys/ioctl.h>#include <net/if.h>#include <net80211/ieee80211.h>#include <net80211/ieee80211_crypto.h>#include <net80211/ieee80211_ioctl.h>/* * Avoid conflicts with hostapd definitions by undefining couple of defines * from net80211 header files. */#undef RSN_VERSION#undef WPA_VERSION#undef WPA_OUI_TYPE#undef WME_OUI_TYPE#include "hostapd.h"#include "driver.h"#include "ieee802_1x.h"#include "eloop.h"#include "sta_info.h"#include "l2_packet/l2_packet.h"#include "eapol_sm.h"#include "wpa.h"#include "radius/radius.h"#include "ieee802_11.h"#include "common.h"struct bsd_driver_data { struct hostapd_data *hapd; /* back pointer */ char iface[IFNAMSIZ + 1]; struct l2_packet_data *sock_xmit; /* raw packet xmit socket */ int ioctl_sock; /* socket for ioctl() use */ int wext_sock; /* socket for wireless events */};static int bsd_sta_deauth(void *priv, const u8 *addr, int reason_code);static intset80211var(struct bsd_driver_data *drv, int op, const void *arg, int arg_len){ struct ieee80211req ireq; memset(&ireq, 0, sizeof(ireq)); os_strlcpy(ireq.i_name, drv->iface, IFNAMSIZ); ireq.i_type = op; ireq.i_len = arg_len; ireq.i_data = (void *) arg; if (ioctl(drv->ioctl_sock, SIOCS80211, &ireq) < 0) { perror("ioctl[SIOCS80211]"); return -1; } return 0;}static intget80211var(struct bsd_driver_data *drv, int op, void *arg, int arg_len){ struct ieee80211req ireq; memset(&ireq, 0, sizeof(ireq)); os_strlcpy(ireq.i_name, drv->iface, IFNAMSIZ); ireq.i_type = op; ireq.i_len = arg_len; ireq.i_data = arg; if (ioctl(drv->ioctl_sock, SIOCG80211, &ireq) < 0) { perror("ioctl[SIOCG80211]"); return -1; } return ireq.i_len;}static intset80211param(struct bsd_driver_data *drv, int op, int arg){ struct ieee80211req ireq; memset(&ireq, 0, sizeof(ireq)); os_strlcpy(ireq.i_name, drv->iface, IFNAMSIZ); ireq.i_type = op; ireq.i_val = arg; if (ioctl(drv->ioctl_sock, SIOCS80211, &ireq) < 0) { perror("ioctl[SIOCS80211]"); return -1; } return 0;}static const char *ether_sprintf(const u8 *addr){ static char buf[sizeof(MACSTR)]; if (addr != NULL) snprintf(buf, sizeof(buf), MACSTR, MAC2STR(addr)); else snprintf(buf, sizeof(buf), MACSTR, 0,0,0,0,0,0); return buf;}/* * Configure WPA parameters. */static intbsd_configure_wpa(struct bsd_driver_data *drv){ static const char *ciphernames[] = { "WEP", "TKIP", "AES-OCB", "AES-CCM", "CKIP", "NONE" }; struct hostapd_data *hapd = drv->hapd; struct hostapd_bss_config *conf = hapd->conf; int v; switch (conf->wpa_group) { case WPA_CIPHER_CCMP: v = IEEE80211_CIPHER_AES_CCM; break; case WPA_CIPHER_TKIP: v = IEEE80211_CIPHER_TKIP; break; case WPA_CIPHER_WEP104: v = IEEE80211_CIPHER_WEP; break; case WPA_CIPHER_WEP40: v = IEEE80211_CIPHER_WEP; break; case WPA_CIPHER_NONE: v = IEEE80211_CIPHER_NONE; break; default: printf("Unknown group key cipher %u\n", conf->wpa_group); return -1; } wpa_printf(MSG_DEBUG, "%s: group key cipher=%s (%u)", __func__, ciphernames[v], v); if (set80211param(drv, IEEE80211_IOC_MCASTCIPHER, v)) { printf("Unable to set group key cipher to %u (%s)\n", v, ciphernames[v]); return -1; } if (v == IEEE80211_CIPHER_WEP) { /* key length is done only for specific ciphers */ v = (conf->wpa_group == WPA_CIPHER_WEP104 ? 13 : 5); if (set80211param(drv, IEEE80211_IOC_MCASTKEYLEN, v)) { printf("Unable to set group key length to %u\n", v); return -1; } } v = 0; if (conf->wpa_pairwise & WPA_CIPHER_CCMP) v |= 1<<IEEE80211_CIPHER_AES_CCM; if (conf->wpa_pairwise & WPA_CIPHER_TKIP) v |= 1<<IEEE80211_CIPHER_TKIP; if (conf->wpa_pairwise & WPA_CIPHER_NONE) v |= 1<<IEEE80211_CIPHER_NONE; wpa_printf(MSG_DEBUG, "%s: pairwise key ciphers=0x%x", __func__, v); if (set80211param(drv, IEEE80211_IOC_UCASTCIPHERS, v)) { printf("Unable to set pairwise key ciphers to 0x%x\n", v); return -1; } wpa_printf(MSG_DEBUG, "%s: key management algorithms=0x%x", __func__, conf->wpa_key_mgmt); if (set80211param(drv, IEEE80211_IOC_KEYMGTALGS, conf->wpa_key_mgmt)) { printf("Unable to set key management algorithms to 0x%x\n", conf->wpa_key_mgmt); return -1; } v = 0; if (conf->rsn_preauth) v |= BIT(0); wpa_printf(MSG_DEBUG, "%s: rsn capabilities=0x%x", __func__, conf->rsn_preauth); if (set80211param(drv, IEEE80211_IOC_RSNCAPS, v)) { printf("Unable to set RSN capabilities to 0x%x\n", v); return -1; } wpa_printf(MSG_DEBUG, "%s: enable WPA= 0x%x", __func__, conf->wpa); if (set80211param(drv, IEEE80211_IOC_WPA, conf->wpa)) { printf("Unable to set WPA to %u\n", conf->wpa); return -1; } return 0;}static intbsd_set_iface_flags(void *priv, int dev_up){ struct bsd_driver_data *drv = priv; struct ifreq ifr; wpa_printf(MSG_DEBUG, "%s: dev_up=%d", __func__, dev_up); if (drv->ioctl_sock < 0) return -1; memset(&ifr, 0, sizeof(ifr)); os_strlcpy(ifr.ifr_name, drv->iface, IFNAMSIZ); if (ioctl(drv->ioctl_sock, SIOCGIFFLAGS, &ifr) != 0) { perror("ioctl[SIOCGIFFLAGS]"); return -1; } if (dev_up) ifr.ifr_flags |= IFF_UP; else ifr.ifr_flags &= ~IFF_UP; if (ioctl(drv->ioctl_sock, SIOCSIFFLAGS, &ifr) != 0) { perror("ioctl[SIOCSIFFLAGS]"); return -1; } if (dev_up) { memset(&ifr, 0, sizeof(ifr)); os_strlcpy(ifr.ifr_name, drv->iface, IFNAMSIZ); ifr.ifr_mtu = HOSTAPD_MTU; if (ioctl(drv->ioctl_sock, SIOCSIFMTU, &ifr) != 0) { perror("ioctl[SIOCSIFMTU]"); printf("Setting MTU failed - trying to survive with " "current value\n"); } } return 0;}static intbsd_set_ieee8021x(const char *ifname, void *priv, int enabled){ struct bsd_driver_data *drv = priv; struct hostapd_data *hapd = drv->hapd; struct hostapd_bss_config *conf = hapd->conf; wpa_printf(MSG_DEBUG, "%s: enabled=%d", __func__, enabled); if (!enabled) { /* XXX restore state */ return set80211param(priv, IEEE80211_IOC_AUTHMODE, IEEE80211_AUTH_AUTO); } if (!conf->wpa && !conf->ieee802_1x) { hostapd_logger(hapd, NULL, HOSTAPD_MODULE_DRIVER, HOSTAPD_LEVEL_WARNING, "No 802.1X or WPA enabled!"); return -1; } if (conf->wpa && bsd_configure_wpa(drv) != 0) { hostapd_logger(hapd, NULL, HOSTAPD_MODULE_DRIVER, HOSTAPD_LEVEL_WARNING, "Error configuring WPA state!"); return -1; } if (set80211param(priv, IEEE80211_IOC_AUTHMODE, (conf->wpa ? IEEE80211_AUTH_WPA : IEEE80211_AUTH_8021X))) { hostapd_logger(hapd, NULL, HOSTAPD_MODULE_DRIVER, HOSTAPD_LEVEL_WARNING, "Error enabling WPA/802.1X!"); return -1; } return bsd_set_iface_flags(priv, 1);}static intbsd_set_privacy(const char *ifname, void *priv, int enabled){ struct bsd_driver_data *drv = priv; wpa_printf(MSG_DEBUG, "%s: enabled=%d", __func__, enabled); return set80211param(drv, IEEE80211_IOC_PRIVACY, enabled);}static intbsd_set_sta_authorized(void *priv, const u8 *addr, int authorized){ struct bsd_driver_data *drv = priv; struct ieee80211req_mlme mlme; wpa_printf(MSG_DEBUG, "%s: addr=%s authorized=%d", __func__, ether_sprintf(addr), authorized); if (authorized) mlme.im_op = IEEE80211_MLME_AUTHORIZE; else mlme.im_op = IEEE80211_MLME_UNAUTHORIZE; mlme.im_reason = 0; memcpy(mlme.im_macaddr, addr, IEEE80211_ADDR_LEN); return set80211var(drv, IEEE80211_IOC_MLME, &mlme, sizeof(mlme));}static intbsd_sta_set_flags(void *priv, const u8 *addr, int total_flags, int flags_or, int flags_and){ /* For now, only support setting Authorized flag */ if (flags_or & WLAN_STA_AUTHORIZED) return bsd_set_sta_authorized(priv, addr, 1); if (!(flags_and & WLAN_STA_AUTHORIZED)) return bsd_set_sta_authorized(priv, addr, 0); return 0;}static intbsd_del_key(void *priv, const u8 *addr, int key_idx){ struct bsd_driver_data *drv = priv; struct ieee80211req_del_key wk; wpa_printf(MSG_DEBUG, "%s: addr=%s key_idx=%d", __func__, ether_sprintf(addr), key_idx); memset(&wk, 0, sizeof(wk)); if (addr != NULL) { memcpy(wk.idk_macaddr, addr, IEEE80211_ADDR_LEN); wk.idk_keyix = (u_int8_t) IEEE80211_KEYIX_NONE; /* XXX */ } else { wk.idk_keyix = key_idx; } return set80211var(drv, IEEE80211_IOC_DELKEY, &wk, sizeof(wk));}static intbsd_set_key(const char *ifname, void *priv, const char *alg, const u8 *addr, int key_idx, const u8 *key, size_t key_len, int txkey){ struct bsd_driver_data *drv = priv; struct ieee80211req_key wk; u_int8_t cipher; if (strcmp(alg, "none") == 0) return bsd_del_key(drv, addr, key_idx); wpa_printf(MSG_DEBUG, "%s: alg=%s addr=%s key_idx=%d", __func__, alg, ether_sprintf(addr), key_idx); if (strcmp(alg, "WEP") == 0) cipher = IEEE80211_CIPHER_WEP; else if (strcmp(alg, "TKIP") == 0) cipher = IEEE80211_CIPHER_TKIP; else if (strcmp(alg, "CCMP") == 0) cipher = IEEE80211_CIPHER_AES_CCM; else { printf("%s: unknown/unsupported algorithm %s\n", __func__, alg); return -1; } if (key_len > sizeof(wk.ik_keydata)) { printf("%s: key length %d too big\n", __func__, key_len); return -3; } memset(&wk, 0, sizeof(wk)); wk.ik_type = cipher; wk.ik_flags = IEEE80211_KEY_RECV | IEEE80211_KEY_XMIT; if (addr == NULL) { memset(wk.ik_macaddr, 0xff, IEEE80211_ADDR_LEN); wk.ik_keyix = key_idx; wk.ik_flags |= IEEE80211_KEY_DEFAULT; } else { memcpy(wk.ik_macaddr, addr, IEEE80211_ADDR_LEN); wk.ik_keyix = IEEE80211_KEYIX_NONE; } wk.ik_keylen = key_len; memcpy(wk.ik_keydata, key, key_len); return set80211var(drv, IEEE80211_IOC_WPAKEY, &wk, sizeof(wk));}static intbsd_get_seqnum(const char *ifname, void *priv, const u8 *addr, int idx, u8 *seq){ struct bsd_driver_data *drv = priv; struct ieee80211req_key wk; wpa_printf(MSG_DEBUG, "%s: addr=%s idx=%d", __func__, ether_sprintf(addr), idx); memset(&wk, 0, sizeof(wk)); if (addr == NULL) memset(wk.ik_macaddr, 0xff, IEEE80211_ADDR_LEN); else memcpy(wk.ik_macaddr, addr, IEEE80211_ADDR_LEN); wk.ik_keyix = idx; if (get80211var(drv, IEEE80211_IOC_WPAKEY, &wk, sizeof(wk)) < 0) { printf("Failed to get encryption.\n"); return -1; }#ifdef WORDS_BIGENDIAN
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -