driver_madwifi.c
来自「hostapd无线AP工具」· C语言 代码 · 共 1,184 行 · 第 1/2 页
C
1,184 行
/* * Host AP - driver interaction with MADWIFI 802.11 driver * Copyright (c) 2004, Sam Leffler <sam@errno.com> * Copyright (c) 2004, Video54 Technologies * * 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 <stdlib.h>#include <stdio.h>#include <unistd.h>#include <string.h>#include <sys/ioctl.h>#include <errno.h>#include <sys/types.h>#include <sys/socket.h>#include <include/compat.h>#include <net80211/ieee80211.h>#ifdef WME_NUM_AC/* Assume this is built against BSD branch of madwifi driver. */#define MADWIFI_BSD#include <net80211/_ieee80211.h>#endif /* WME_NUM_AC */#include <net80211/ieee80211_crypto.h>#include <net80211/ieee80211_ioctl.h>#include <net/if_arp.h>#include <linux/wireless.h>#include <netinet/in.h>#include <netpacket/packet.h>#include "hostapd.h"#include "driver.h"#include "ieee802_1x.h"#include "eloop.h"#include "priv_netlink.h"#include "sta_info.h"#include "l2_packet.h"#include "eapol_sm.h"#include "wpa.h"#include "radius.h"#include "ieee802_11.h"#include "accounting.h"#include "common.h"struct madwifi_driver_data { struct driver_ops ops; /* base class */ struct hostapd_data *hapd; /* back pointer */ char iface[IFNAMSIZ + 1]; int ifindex; struct l2_packet_data *sock_xmit; /* raw packet xmit socket */ struct l2_packet_data *sock_recv; /* raw packet recv socket */ int ioctl_sock; /* socket for ioctl() use */ int wext_sock; /* socket for wireless events */ u8 acct_mac[ETH_ALEN]; struct hostap_sta_driver_data acct_data;};static const struct driver_ops madwifi_driver_ops;static int madwifi_sta_deauth(void *priv, u8 *addr, int reason_code);static intset80211priv(struct madwifi_driver_data *drv, int op, void *data, int len){#define N(a) (sizeof(a)/sizeof(a[0])) struct iwreq iwr; memset(&iwr, 0, sizeof(iwr)); strncpy(iwr.ifr_name, drv->iface, IFNAMSIZ); if (len < IFNAMSIZ) { /* * Argument data fits inline; put it there. */ memcpy(iwr.u.name, data, len); } else { /* * Argument data too big for inline transfer; setup a * parameter block instead; the kernel will transfer * the data for the driver. */ iwr.u.data.pointer = data; iwr.u.data.length = len; } if (ioctl(drv->ioctl_sock, op, &iwr) < 0) { static const char *opnames[] = { "ioctl[IEEE80211_IOCTL_SETPARAM]", "ioctl[IEEE80211_IOCTL_GETPARAM]", "ioctl[IEEE80211_IOCTL_SETKEY]", "ioctl[SIOCIWFIRSTPRIV+3]", "ioctl[IEEE80211_IOCTL_DELKEY]", "ioctl[SIOCIWFIRSTPRIV+5]", "ioctl[IEEE80211_IOCTL_SETMLME]", "ioctl[SIOCIWFIRSTPRIV+7]", "ioctl[IEEE80211_IOCTL_SETOPTIE]", "ioctl[IEEE80211_IOCTL_GETOPTIE]", "ioctl[IEEE80211_IOCTL_ADDMAC]", "ioctl[SIOCIWFIRSTPRIV+11]", "ioctl[IEEE80211_IOCTL_DELMAC]", "ioctl[SIOCIWFIRSTPRIV+13]", "ioctl[IEEE80211_IOCTL_CHANLIST]", "ioctl[SIOCIWFIRSTPRIV+15]", "ioctl[IEEE80211_IOCTL_GETRSN]", "ioctl[SIOCIWFIRSTPRIV+17]", "ioctl[IEEE80211_IOCTL_GETKEY]", }; op -= SIOCIWFIRSTPRIV; if (0 <= op && op < N(opnames)) perror(opnames[op]); else perror("ioctl[unknown???]"); return -1; } return 0;#undef N}static intset80211param(struct madwifi_driver_data *drv, int op, int arg){ struct iwreq iwr; memset(&iwr, 0, sizeof(iwr)); strncpy(iwr.ifr_name, drv->iface, IFNAMSIZ); iwr.u.mode = op; memcpy(iwr.u.name+sizeof(__u32), &arg, sizeof(arg)); if (ioctl(drv->ioctl_sock, IEEE80211_IOCTL_SETPARAM, &iwr) < 0) { perror("ioctl[IEEE80211_IOCTL_SETPARAM]"); 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 intmadwifi_configure_wpa(struct madwifi_driver_data *drv){ hostapd *hapd = drv->hapd; struct hostapd_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; } HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL, "%s: group key cipher=%d\n", __func__, v); if (set80211param(drv, IEEE80211_PARAM_MCASTCIPHER, v)) { printf("Unable to set group key cipher to %u\n", 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_PARAM_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; HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL, "%s: pairwise key ciphers=0x%x\n", __func__, v); if (set80211param(drv, IEEE80211_PARAM_UCASTCIPHERS, v)) { printf("Unable to set pairwise key ciphers to 0x%x\n", v); return -1; } HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL, "%s: key management algorithms=0x%x\n", __func__, conf->wpa_key_mgmt); if (set80211param(drv, IEEE80211_PARAM_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); HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL, "%s: rsn capabilities=0x%x\n", __func__, conf->rsn_preauth); if (set80211param(drv, IEEE80211_PARAM_RSNCAPS, v)) { printf("Unable to set RSN capabilities to 0x%x\n", v); return -1; } HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL, "%s: enable WPA= 0x%x\n", __func__, conf->wpa); if (set80211param(drv, IEEE80211_PARAM_WPA, conf->wpa)) { printf("Unable to set WPA to %u\n", conf->wpa); return -1; } return 0;}static intmadwifi_set_iface_flags(void *priv, int dev_up){ struct madwifi_driver_data *drv = priv; hostapd *hapd = drv->hapd; struct ifreq ifr; HOSTAPD_DEBUG(HOSTAPD_DEBUG_VERBOSE, "%s: dev_up=%d\n", __func__, dev_up); if (drv->ioctl_sock < 0) return -1; memset(&ifr, 0, sizeof(ifr)); snprintf(ifr.ifr_name, IFNAMSIZ, "%s", drv->iface); 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)); snprintf(ifr.ifr_name, IFNAMSIZ, "%s", drv->iface); 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 intmadwifi_set_ieee8021x(void *priv, int enabled){ struct madwifi_driver_data *drv = priv; hostapd *hapd = drv->hapd; struct hostapd_config *conf = hapd->conf; HOSTAPD_DEBUG(HOSTAPD_DEBUG_VERBOSE, "%s: enabled=%d\n", __func__, enabled); if (!enabled) { /* XXX restore state */ return set80211param(priv, IEEE80211_PARAM_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 && madwifi_configure_wpa(drv) != 0) { hostapd_logger(hapd, NULL, HOSTAPD_MODULE_DRIVER, HOSTAPD_LEVEL_WARNING, "Error configuring WPA state!"); return -1; } if (set80211param(priv, IEEE80211_PARAM_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 madwifi_set_iface_flags(priv, 1);}static intmadwifi_set_privacy(void *priv, int enabled){ struct madwifi_driver_data *drv = priv; hostapd *hapd = drv->hapd; HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL, "%s: enabled=%d\n", __func__, enabled); return set80211param(priv, IEEE80211_PARAM_PRIVACY, enabled);}static intmadwifi_set_sta_authorized(void *priv, u8 *addr, int authorized){ struct madwifi_driver_data *drv = priv; hostapd *hapd = drv->hapd; struct ieee80211req_mlme mlme; HOSTAPD_DEBUG(HOSTAPD_DEBUG_VERBOSE, "%s: addr=%s authorized=%d\n", __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 set80211priv(priv, IEEE80211_IOCTL_SETMLME, &mlme, sizeof(mlme));}static intmadwifi_del_key(void *priv, unsigned char *addr, int key_idx){ struct madwifi_driver_data *drv = priv; hostapd *hapd = drv->hapd; struct ieee80211req_del_key wk; HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL, "%s: addr=%s key_idx=%d\n", __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 = (u8) IEEE80211_KEYIX_NONE; } else { wk.idk_keyix = key_idx; } return set80211priv(priv, IEEE80211_IOCTL_DELKEY, &wk, sizeof(wk));}static intmadwifi_set_key(void *priv, const char *alg, unsigned char *addr, int key_idx, u8 *key, size_t key_len){ struct madwifi_driver_data *drv = priv; hostapd *hapd = drv->hapd; struct ieee80211req_key wk; u_int8_t cipher; if (strcmp(alg, "none") == 0) return madwifi_del_key(priv, addr, key_idx); HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL, "%s: alg=%s addr=%s key_idx=%d\n", __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 %lu too big\n", __func__, (unsigned long) 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 set80211priv(priv, IEEE80211_IOCTL_SETKEY, &wk, sizeof(wk));}static intmadwifi_get_seqnum(void *priv, u8 *addr, int idx, u8 *seq){ struct madwifi_driver_data *drv = priv; hostapd *hapd = drv->hapd; struct ieee80211req_key wk; HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL, "%s: addr=%s idx=%d\n", __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 (set80211priv(priv, IEEE80211_IOCTL_GETKEY, &wk, sizeof(wk))) { printf("Failed to get encryption.\n"); return -1; }#ifdef WORDS_BIGENDIAN { /* * wk.ik_keytsc is in host byte order (big endian), need to * swap it to match with the byte order used in WPA. */ int i; u8 tmp[WPA_KEY_RSC_LEN]; memcpy(tmp, &wk.ik_keytsc, sizeof(wk.ik_keytsc)); for (i = 0; i < WPA_KEY_RSC_LEN; i++) { seq[i] = tmp[WPA_KEY_RSC_LEN - i - 1]; } }#else /* WORDS_BIGENDIAN */ memcpy(seq, &wk.ik_keytsc, sizeof(wk.ik_keytsc));#endif /* WORDS_BIGENDIAN */ return 0;}static int madwifi_flush(void *priv){#ifdef MADWIFI_BSD u8 allsta[IEEE80211_ADDR_LEN]; memset(allsta, 0xff, IEEE80211_ADDR_LEN); return madwifi_sta_deauth(priv, allsta, IEEE80211_REASON_AUTH_LEAVE);#else /* MADWIFI_BSD */ return 0; /* XXX */#endif /* MADWIFI_BSD */}static intmadwifi_read_sta_driver_data(void *priv, struct hostap_sta_driver_data *data, u8 *addr){ struct madwifi_driver_data *drv = priv;#ifdef MADWIFI_BSD struct ieee80211req_sta_stats stats; memset(data, 0, sizeof(*data)); /* * Fetch statistics for station from the system. */ memset(&stats, 0, sizeof(stats)); memcpy(stats.is_u.macaddr, addr, IEEE80211_ADDR_LEN); if (set80211priv(drv, IEEE80211_IOCTL_GETSTASTATS, &stats, sizeof(stats))) { if (memcmp(addr, drv->acct_mac, ETH_ALEN) == 0) { memcpy(data, &drv->acct_data, sizeof(*data)); return 0; } printf("Failed to get station stats information element.\n"); return -1; } data->rx_packets = stats.is_stats.ns_rx_data; data->rx_bytes = stats.is_stats.ns_rx_bytes; data->tx_packets = stats.is_stats.ns_tx_data; data->tx_bytes = stats.is_stats.ns_tx_bytes; return 0;#else /* MADWIFI_BSD */ char buf[1024], line[128], *pos; FILE *f; unsigned long val; memset(data, 0, sizeof(*data)); snprintf(buf, sizeof(buf), "/proc/net/madwifi/%s/" MACSTR, drv->iface, MAC2STR(addr)); f = fopen(buf, "r"); if (!f) { if (memcmp(addr, drv->acct_mac, ETH_ALEN) != 0) return -1; memcpy(data, &drv->acct_data, sizeof(*data)); return 0; } /* Need to read proc file with in one piece, so use large enough * buffer. */ setbuffer(f, buf, sizeof(buf)); while (fgets(line, sizeof(line), f)) { pos = strchr(line, '='); if (!pos) continue; *pos++ = '\0'; val = strtoul(pos, NULL, 10); if (strcmp(line, "rx_packets") == 0) data->rx_packets = val; else if (strcmp(line, "tx_packets") == 0) data->tx_packets = val; else if (strcmp(line, "rx_bytes") == 0) data->rx_bytes = val; else if (strcmp(line, "tx_bytes") == 0) data->tx_bytes = val; } fclose(f); return 0;#endif /* MADWIFI_BSD */}static intmadwifi_sta_clear_stats(void *priv, u8 *addr){#ifdef MADWIFI_BSD struct madwifi_driver_data *drv = priv; struct hostapd_data *hapd = drv->hapd; struct ieee80211req_mlme mlme; HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL, "%s: addr=%s\n", __func__, ether_sprintf(addr)); mlme.im_op = IEEE80211_MLME_CLEAR_STATS; memcpy(mlme.im_macaddr, addr, IEEE80211_ADDR_LEN); return set80211priv(priv, IEEE80211_IOCTL_SETMLME, &mlme, sizeof(mlme));#else /* MADWIFI_BSD */ return 0; /* FIX */#endif /* MADWIFI_BSD */}static intmadwifi_set_opt_ie(void *priv, const u8 *ie, size_t ie_len){ /* * Do nothing; we setup parameters at startup that define the
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?