📄 driver_broadcom.c
字号:
/* * WPA Supplicant - driver interaction with Broadcom wl.o driver * Copyright (c) 2004, Nikki Chumkov <nikki@gattaca.ru> * Copyright (c) 2004, Jouni Malinen <j@w1.fi> * * 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>#if 0#include <netpacket/packet.h>#include <net/ethernet.h> /* the L2 protocols */#else#include <linux/if_packet.h>#include <linux/if_ether.h> /* The L2 protocols */#endif#include <net/if.h>#include <typedefs.h>/* wlioctl.h is a Broadcom header file and it is available, e.g., from Linksys * WRT54G GPL tarball. */#include <wlioctl.h>#include "common.h"#include "driver.h"#include "eloop.h"#include "wpa_supplicant.h"#include "wpa.h"struct wpa_driver_broadcom_data { void *ctx; int ioctl_sock; int event_sock; char ifname[IFNAMSIZ + 1];};#ifndef WLC_DEAUTHENTICATE#define WLC_DEAUTHENTICATE 143#endif#ifndef WLC_DEAUTHENTICATE_WITH_REASON#define WLC_DEAUTHENTICATE_WITH_REASON 201#endif#ifndef WLC_SET_TKIP_COUNTERMEASURES#define WLC_SET_TKIP_COUNTERMEASURES 202#endif#if !defined(PSK_ENABLED) /* NEW driver interface */#define WL_VERSION 360130/* wireless authentication bit vector */#define WPA_ENABLED 1#define PSK_ENABLED 2 #define WAUTH_WPA_ENABLED(wauth) ((wauth) & WPA_ENABLED)#define WAUTH_PSK_ENABLED(wauth) ((wauth) & PSK_ENABLED)#define WAUTH_ENABLED(wauth) ((wauth) & (WPA_ENABLED | PSK_ENABLED))#define WSEC_PRIMARY_KEY WL_PRIMARY_KEYtypedef wl_wsec_key_t wsec_key_t;#endiftypedef struct { uint32 val; struct ether_addr ea; uint16 res;} wlc_deauth_t;static void wpa_driver_broadcom_scan_timeout(void *eloop_ctx, void *timeout_ctx);static int broadcom_ioctl(struct wpa_driver_broadcom_data *drv, int cmd, void *buf, int len){ struct ifreq ifr; wl_ioctl_t ioc; int ret = 0; wpa_printf(MSG_MSGDUMP, "BROADCOM: wlioctl(%s,%d,len=%d,val=%p)", drv->ifname, cmd, len, buf); /* wpa_hexdump(MSG_MSGDUMP, "BROADCOM: wlioctl buf", buf, len); */ ioc.cmd = cmd; ioc.buf = buf; ioc.len = len; os_strncpy(ifr.ifr_name, drv->ifname, IFNAMSIZ); ifr.ifr_data = (caddr_t) &ioc; if ((ret = ioctl(drv->ioctl_sock, SIOCDEVPRIVATE, &ifr)) < 0) { if (cmd != WLC_GET_MAGIC) perror(ifr.ifr_name); wpa_printf(MSG_MSGDUMP, "BROADCOM: wlioctl cmd=%d res=%d", cmd, ret); } return ret;}static int wpa_driver_broadcom_get_bssid(void *priv, u8 *bssid){ struct wpa_driver_broadcom_data *drv = priv; if (broadcom_ioctl(drv, WLC_GET_BSSID, bssid, ETH_ALEN) == 0) return 0; os_memset(bssid, 0, ETH_ALEN); return -1;}static int wpa_driver_broadcom_get_ssid(void *priv, u8 *ssid){ struct wpa_driver_broadcom_data *drv = priv; wlc_ssid_t s; if (broadcom_ioctl(drv, WLC_GET_SSID, &s, sizeof(s)) == -1) return -1; os_memcpy(ssid, s.SSID, s.SSID_len); return s.SSID_len;}static int wpa_driver_broadcom_set_wpa(void *priv, int enable){ struct wpa_driver_broadcom_data *drv = priv; unsigned int wauth, wsec; struct ether_addr ea; os_memset(&ea, enable ? 0xff : 0, sizeof(ea)); if (broadcom_ioctl(drv, WLC_GET_WPA_AUTH, &wauth, sizeof(wauth)) == -1 || broadcom_ioctl(drv, WLC_GET_WSEC, &wsec, sizeof(wsec)) == -1) return -1; if (enable) { wauth = PSK_ENABLED; wsec = TKIP_ENABLED; } else { wauth = 255; wsec &= ~(TKIP_ENABLED | AES_ENABLED); } if (broadcom_ioctl(drv, WLC_SET_WPA_AUTH, &wauth, sizeof(wauth)) == -1 || broadcom_ioctl(drv, WLC_SET_WSEC, &wsec, sizeof(wsec)) == -1) return -1; /* FIX: magic number / error handling? */ broadcom_ioctl(drv, 122, &ea, sizeof(ea)); return 0;}static int wpa_driver_broadcom_set_key(void *priv, wpa_alg alg, const u8 *addr, int key_idx, int set_tx, const u8 *seq, size_t seq_len, const u8 *key, size_t key_len){ struct wpa_driver_broadcom_data *drv = priv; int ret; wsec_key_t wkt; os_memset(&wkt, 0, sizeof wkt); wpa_printf(MSG_MSGDUMP, "BROADCOM: SET %sKEY[%d] alg=%d", set_tx ? "PRIMARY " : "", key_idx, alg); if (key && key_len > 0) wpa_hexdump_key(MSG_MSGDUMP, "BROADCOM: key", key, key_len); switch (alg) { case WPA_ALG_NONE: wkt.algo = CRYPTO_ALGO_OFF; break; case WPA_ALG_WEP: wkt.algo = CRYPTO_ALGO_WEP128; /* CRYPTO_ALGO_WEP1? */ break; case WPA_ALG_TKIP: wkt.algo = 0; /* CRYPTO_ALGO_TKIP? */ break; case WPA_ALG_CCMP: wkt.algo = 0; /* CRYPTO_ALGO_AES_CCM; * AES_OCB_MSDU, AES_OCB_MPDU? */ break; default: wkt.algo = CRYPTO_ALGO_NALG; break; } if (seq && seq_len > 0) wpa_hexdump(MSG_MSGDUMP, "BROADCOM: SEQ", seq, seq_len); if (addr) wpa_hexdump(MSG_MSGDUMP, "BROADCOM: addr", addr, ETH_ALEN); wkt.index = key_idx; wkt.len = key_len; if (key && key_len > 0) { os_memcpy(wkt.data, key, key_len); if (key_len == 32) { /* hack hack hack XXX */ os_memcpy(&wkt.data[16], &key[24], 8); os_memcpy(&wkt.data[24], &key[16], 8); } } /* wkt.algo = CRYPTO_ALGO_...; */ wkt.flags = set_tx ? 0 : WSEC_PRIMARY_KEY; if (addr && set_tx) os_memcpy(&wkt.ea, addr, sizeof(wkt.ea)); ret = broadcom_ioctl(drv, WLC_SET_KEY, &wkt, sizeof(wkt)); if (addr && set_tx) { /* FIX: magic number / error handling? */ broadcom_ioctl(drv, 121, &wkt.ea, sizeof(wkt.ea)); } return ret;}static void wpa_driver_broadcom_event_receive(int sock, void *ctx, void *sock_ctx){ char buf[8192]; int left; wl_wpa_header_t *wwh; union wpa_event_data data; if ((left = recv(sock, buf, sizeof buf, 0)) < 0) return; wpa_hexdump(MSG_DEBUG, "RECEIVE EVENT", buf, left); if ((size_t) left < sizeof(wl_wpa_header_t)) return; wwh = (wl_wpa_header_t *) buf; if (wwh->snap.type != WL_WPA_ETHER_TYPE) return; if (os_memcmp(&wwh->snap, wl_wpa_snap_template, 6) != 0) return; os_memset(&data, 0, sizeof(data)); switch (wwh->type) { case WLC_ASSOC_MSG: left -= WL_WPA_HEADER_LEN; wpa_printf(MSG_DEBUG, "BROADCOM: ASSOC MESSAGE (left: %d)", left); if (left > 0) { data.assoc_info.resp_ies = os_malloc(left); if (data.assoc_info.resp_ies == NULL) return; os_memcpy(data.assoc_info.resp_ies, buf + WL_WPA_HEADER_LEN, left); data.assoc_info.resp_ies_len = left; wpa_hexdump(MSG_MSGDUMP, "BROADCOM: copying %d bytes " "into resp_ies", data.assoc_info.resp_ies, left); } /* data.assoc_info.req_ies = NULL; */ /* data.assoc_info.req_ies_len = 0; */ wpa_supplicant_event(ctx, EVENT_ASSOCINFO, &data); wpa_supplicant_event(ctx, EVENT_ASSOC, NULL); break; case WLC_DISASSOC_MSG: wpa_printf(MSG_DEBUG, "BROADCOM: DISASSOC MESSAGE"); wpa_supplicant_event(ctx, EVENT_DISASSOC, NULL); break; case WLC_PTK_MIC_MSG: wpa_printf(MSG_DEBUG, "BROADCOM: PTK MIC MSG MESSAGE"); data.michael_mic_failure.unicast = 1; wpa_supplicant_event(ctx, EVENT_MICHAEL_MIC_FAILURE, &data); break; case WLC_GTK_MIC_MSG: wpa_printf(MSG_DEBUG, "BROADCOM: GTK MIC MSG MESSAGE"); data.michael_mic_failure.unicast = 0; wpa_supplicant_event(ctx, EVENT_MICHAEL_MIC_FAILURE, &data); break; default: wpa_printf(MSG_DEBUG, "BROADCOM: UNKNOWN MESSAGE (%d)", wwh->type); break; } os_free(data.assoc_info.resp_ies);} static void * wpa_driver_broadcom_init(void *ctx, const char *ifname){ int s; struct sockaddr_ll ll; struct wpa_driver_broadcom_data *drv; struct ifreq ifr; /* open socket to kernel */ if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -