📄 driver_test.c
字号:
/* * hostapd / Driver interface for development testing * Copyright (c) 2004-2008, 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/un.h>#include <dirent.h>#include "hostapd.h"#include "driver.h"#include "sha1.h"#include "eloop.h"#include "ieee802_1x.h"#include "sta_info.h"#include "wpa.h"#include "accounting.h"#include "radius/radius.h"#include "l2_packet/l2_packet.h"#include "ieee802_11.h"#include "hw_features.h"#include "wps_hostapd.h"struct test_client_socket { struct test_client_socket *next; u8 addr[ETH_ALEN]; struct sockaddr_un un; socklen_t unlen; struct test_driver_bss *bss;};struct test_driver_bss { struct test_driver_bss *next; char ifname[IFNAMSIZ + 1]; u8 bssid[ETH_ALEN]; u8 *ie; size_t ielen; u8 *wps_beacon_ie; size_t wps_beacon_ie_len; u8 *wps_probe_resp_ie; size_t wps_probe_resp_ie_len; u8 ssid[32]; size_t ssid_len; int privacy;};struct test_driver_data { struct hostapd_data *hapd; struct test_client_socket *cli; int test_socket; struct test_driver_bss *bss; char *socket_dir; char *own_socket_path; int udp_port;};static void test_driver_free_bss(struct test_driver_bss *bss){ free(bss->ie); free(bss->wps_beacon_ie); free(bss->wps_probe_resp_ie); free(bss);}static void test_driver_free_priv(struct test_driver_data *drv){ struct test_driver_bss *bss, *prev; if (drv == NULL) return; bss = drv->bss; while (bss) { prev = bss; bss = bss->next; test_driver_free_bss(prev); } free(drv->own_socket_path); free(drv->socket_dir); free(drv);}static struct test_client_socket *test_driver_get_cli(struct test_driver_data *drv, struct sockaddr_un *from, socklen_t fromlen){ struct test_client_socket *cli = drv->cli; while (cli) { if (cli->unlen == fromlen && strncmp(cli->un.sun_path, from->sun_path, fromlen - sizeof(cli->un.sun_family)) == 0) return cli; cli = cli->next; } return NULL;}static int test_driver_send_eapol(void *priv, const u8 *addr, const u8 *data, size_t data_len, int encrypt, const u8 *own_addr){ struct test_driver_data *drv = priv; struct test_client_socket *cli; struct msghdr msg; struct iovec io[3]; struct l2_ethhdr eth; if (drv->test_socket < 0) return -1; cli = drv->cli; while (cli) { if (memcmp(cli->addr, addr, ETH_ALEN) == 0) break; cli = cli->next; } if (!cli) { wpa_printf(MSG_DEBUG, "%s: no destination client entry", __func__); return -1; } memcpy(eth.h_dest, addr, ETH_ALEN); memcpy(eth.h_source, own_addr, ETH_ALEN); eth.h_proto = host_to_be16(ETH_P_EAPOL); io[0].iov_base = "EAPOL "; io[0].iov_len = 6; io[1].iov_base = ð io[1].iov_len = sizeof(eth); io[2].iov_base = (u8 *) data; io[2].iov_len = data_len; memset(&msg, 0, sizeof(msg)); msg.msg_iov = io; msg.msg_iovlen = 3; msg.msg_name = &cli->un; msg.msg_namelen = cli->unlen; return sendmsg(drv->test_socket, &msg, 0);}static int test_driver_send_ether(void *priv, const u8 *dst, const u8 *src, u16 proto, const u8 *data, size_t data_len){ struct test_driver_data *drv = priv; struct msghdr msg; struct iovec io[3]; struct l2_ethhdr eth; char desttxt[30]; struct sockaddr_un addr; struct dirent *dent; DIR *dir; int ret = 0, broadcast = 0, count = 0; if (drv->test_socket < 0 || drv->socket_dir == NULL) { wpa_printf(MSG_DEBUG, "%s: invalid parameters (sock=%d " "socket_dir=%p)", __func__, drv->test_socket, drv->socket_dir); return -1; } broadcast = memcmp(dst, "\xff\xff\xff\xff\xff\xff", ETH_ALEN) == 0; snprintf(desttxt, sizeof(desttxt), MACSTR, MAC2STR(dst)); memcpy(eth.h_dest, dst, ETH_ALEN); memcpy(eth.h_source, src, ETH_ALEN); eth.h_proto = host_to_be16(proto); io[0].iov_base = "ETHER "; io[0].iov_len = 6; io[1].iov_base = ð io[1].iov_len = sizeof(eth); io[2].iov_base = (u8 *) data; io[2].iov_len = data_len; memset(&msg, 0, sizeof(msg)); msg.msg_iov = io; msg.msg_iovlen = 3; dir = opendir(drv->socket_dir); if (dir == NULL) { perror("test_driver: opendir"); return -1; } while ((dent = readdir(dir))) {#ifdef _DIRENT_HAVE_D_TYPE /* Skip the file if it is not a socket. Also accept * DT_UNKNOWN (0) in case the C library or underlying file * system does not support d_type. */ if (dent->d_type != DT_SOCK && dent->d_type != DT_UNKNOWN) continue;#endif /* _DIRENT_HAVE_D_TYPE */ if (strcmp(dent->d_name, ".") == 0 || strcmp(dent->d_name, "..") == 0) continue; memset(&addr, 0, sizeof(addr)); addr.sun_family = AF_UNIX; snprintf(addr.sun_path, sizeof(addr.sun_path), "%s/%s", drv->socket_dir, dent->d_name); if (strcmp(addr.sun_path, drv->own_socket_path) == 0) continue; if (!broadcast && strstr(dent->d_name, desttxt) == NULL) continue; wpa_printf(MSG_DEBUG, "%s: Send ether frame to %s", __func__, dent->d_name); msg.msg_name = &addr; msg.msg_namelen = sizeof(addr); ret = sendmsg(drv->test_socket, &msg, 0); if (ret < 0) perror("driver_test: sendmsg"); count++; } closedir(dir); if (!broadcast && count == 0) { wpa_printf(MSG_DEBUG, "%s: Destination " MACSTR " not found", __func__, MAC2STR(dst)); return -1; } return ret;}static int test_driver_send_mgmt_frame(void *priv, const void *buf, size_t len, int flags){ struct test_driver_data *drv = priv; struct msghdr msg; struct iovec io[2]; const u8 *dest; int ret = 0, broadcast = 0; char desttxt[30]; struct sockaddr_un addr; struct dirent *dent; DIR *dir; struct ieee80211_hdr *hdr; u16 fc; if (drv->test_socket < 0 || len < 10 || drv->socket_dir == NULL) { wpa_printf(MSG_DEBUG, "%s: invalid parameters (sock=%d len=%lu" " socket_dir=%p)", __func__, drv->test_socket, (unsigned long) len, drv->socket_dir); return -1; } dest = buf; dest += 4; broadcast = memcmp(dest, "\xff\xff\xff\xff\xff\xff", ETH_ALEN) == 0; snprintf(desttxt, sizeof(desttxt), MACSTR, MAC2STR(dest)); io[0].iov_base = "MLME "; io[0].iov_len = 5; io[1].iov_base = (void *) buf; io[1].iov_len = len; memset(&msg, 0, sizeof(msg)); msg.msg_iov = io; msg.msg_iovlen = 2; dir = opendir(drv->socket_dir); if (dir == NULL) { perror("test_driver: opendir"); return -1; } while ((dent = readdir(dir))) {#ifdef _DIRENT_HAVE_D_TYPE /* Skip the file if it is not a socket. Also accept * DT_UNKNOWN (0) in case the C library or underlying file * system does not support d_type. */ if (dent->d_type != DT_SOCK && dent->d_type != DT_UNKNOWN) continue;#endif /* _DIRENT_HAVE_D_TYPE */ if (strcmp(dent->d_name, ".") == 0 || strcmp(dent->d_name, "..") == 0) continue; memset(&addr, 0, sizeof(addr)); addr.sun_family = AF_UNIX; snprintf(addr.sun_path, sizeof(addr.sun_path), "%s/%s", drv->socket_dir, dent->d_name); if (strcmp(addr.sun_path, drv->own_socket_path) == 0) continue; if (!broadcast && strstr(dent->d_name, desttxt) == NULL) continue; wpa_printf(MSG_DEBUG, "%s: Send management frame to %s", __func__, dent->d_name); msg.msg_name = &addr; msg.msg_namelen = sizeof(addr); ret = sendmsg(drv->test_socket, &msg, 0); if (ret < 0) perror("driver_test: sendmsg"); } closedir(dir); hdr = (struct ieee80211_hdr *) buf; fc = le_to_host16(hdr->frame_control); ieee802_11_mgmt_cb(drv->hapd, (u8 *) buf, len, WLAN_FC_GET_STYPE(fc), ret >= 0); return ret;}static void test_driver_scan(struct test_driver_data *drv, struct sockaddr_un *from, socklen_t fromlen, char *data){ char buf[512], *pos, *end; int ret; struct test_driver_bss *bss; u8 sa[ETH_ALEN]; u8 ie[512]; size_t ielen; /* data: optional [ ' ' | STA-addr | ' ' | IEs(hex) ] */ wpa_printf(MSG_DEBUG, "test_driver: SCAN"); if (*data) { if (*data != ' ' || hwaddr_aton(data + 1, sa)) { wpa_printf(MSG_DEBUG, "test_driver: Unexpected SCAN " "command format"); return; } data += 18; while (*data == ' ') data++; ielen = os_strlen(data) / 2; if (ielen > sizeof(ie)) ielen = sizeof(ie); if (hexstr2bin(data, ie, ielen) < 0) ielen = 0; wpa_printf(MSG_DEBUG, "test_driver: Scan from " MACSTR, MAC2STR(sa)); wpa_hexdump(MSG_MSGDUMP, "test_driver: scan IEs", ie, ielen); hostapd_wps_probe_req_rx(drv->hapd, sa, ie, ielen); } for (bss = drv->bss; bss; bss = bss->next) { pos = buf; end = buf + sizeof(buf); /* reply: SCANRESP BSSID SSID IEs */ ret = snprintf(pos, end - pos, "SCANRESP " MACSTR " ", MAC2STR(bss->bssid)); if (ret < 0 || ret >= end - pos) return; pos += ret; pos += wpa_snprintf_hex(pos, end - pos, bss->ssid, bss->ssid_len); ret = snprintf(pos, end - pos, " "); if (ret < 0 || ret >= end - pos) return; pos += ret; pos += wpa_snprintf_hex(pos, end - pos, bss->ie, bss->ielen); pos += wpa_snprintf_hex(pos, end - pos, bss->wps_probe_resp_ie, bss->wps_probe_resp_ie_len); if (bss->privacy) { ret = snprintf(pos, end - pos, " PRIVACY"); if (ret < 0 || ret >= end - pos) return; pos += ret; } sendto(drv->test_socket, buf, pos - buf, 0, (struct sockaddr *) from, fromlen); }}static struct hostapd_data * test_driver_get_hapd(struct test_driver_data *drv, struct test_driver_bss *bss){ struct hostapd_iface *iface = drv->hapd->iface; struct hostapd_data *hapd = NULL; size_t i; if (bss == NULL) { wpa_printf(MSG_DEBUG, "%s: bss == NULL", __func__); return NULL; } for (i = 0; i < iface->num_bss; i++) { hapd = iface->bss[i]; if (memcmp(hapd->own_addr, bss->bssid, ETH_ALEN) == 0) break; } if (i == iface->num_bss) { wpa_printf(MSG_DEBUG, "%s: no matching interface entry found " "for BSSID " MACSTR, __func__, MAC2STR(bss->bssid)); return NULL; } return hapd;}static int test_driver_new_sta(struct test_driver_data *drv, struct test_driver_bss *bss, const u8 *addr, const u8 *ie, size_t ielen){ struct hostapd_data *hapd;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -