mirror of
https://github.com/freebsd/freebsd-src
synced 2024-10-04 07:31:11 +00:00
freebsd pieces of wpa supplicant support
Reviewed by: brooks
This commit is contained in:
parent
b9203a8aca
commit
cb9aecf05f
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=147020
5
usr.sbin/wpa/Makefile
Normal file
5
usr.sbin/wpa/Makefile
Normal file
|
@ -0,0 +1,5 @@
|
|||
# $FreeBSD$
|
||||
|
||||
SUBDIR= wpa_supplicant wpa_cli
|
||||
|
||||
.include <bsd.subdir.mk>
|
3
usr.sbin/wpa/Makefile.inc
Normal file
3
usr.sbin/wpa/Makefile.inc
Normal file
|
@ -0,0 +1,3 @@
|
|||
# $FreeBSD$
|
||||
|
||||
BINDIR?= /usr/sbin
|
227
usr.sbin/wpa/l2_packet.c
Normal file
227
usr.sbin/wpa/l2_packet.c
Normal file
|
@ -0,0 +1,227 @@
|
|||
/*
|
||||
* WPA Supplicant - Layer2 packet handling
|
||||
* Copyright (c) 2003-2004, Jouni Malinen <jkmaline@cc.hut.fi>
|
||||
* Copyright (c) 2005, Sam Leffler <sam@errno.com>
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
/*
|
||||
* FreeBSD-specific implementation.
|
||||
*/
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
#include <pcap.h>
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/sysctl.h>
|
||||
|
||||
#include <net/if.h>
|
||||
#include <net/if_dl.h>
|
||||
#include <net/route.h>
|
||||
|
||||
#include "common.h"
|
||||
#include "eloop.h"
|
||||
#include "l2_packet.h"
|
||||
|
||||
struct l2_packet_data {
|
||||
pcap_t *pcap;
|
||||
char ifname[100];
|
||||
u8 own_addr[ETH_ALEN];
|
||||
void (*rx_callback)(void *ctx, unsigned char *src_addr,
|
||||
unsigned char *buf, size_t len);
|
||||
void *rx_callback_ctx;
|
||||
int rx_l2_hdr; /* whether to include layer 2 (Ethernet) header in calls
|
||||
* to rx_callback */
|
||||
};
|
||||
|
||||
int
|
||||
l2_packet_get_own_addr(struct l2_packet_data *l2, u8 *addr)
|
||||
{
|
||||
memcpy(addr, l2->own_addr, ETH_ALEN);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
l2_packet_set_rx_l2_hdr(struct l2_packet_data *l2, int rx_l2_hdr)
|
||||
{
|
||||
l2->rx_l2_hdr = rx_l2_hdr;
|
||||
}
|
||||
|
||||
int
|
||||
l2_packet_send(struct l2_packet_data *l2, u8 *buf, size_t len)
|
||||
{
|
||||
return pcap_inject(l2->pcap, buf, len);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
l2_packet_receive(int sock, void *eloop_ctx, void *sock_ctx)
|
||||
{
|
||||
struct l2_packet_data *l2 = eloop_ctx;
|
||||
pcap_t *pcap = sock_ctx;
|
||||
struct pcap_pkthdr hdr;
|
||||
const u_char *packet;
|
||||
struct l2_ethhdr *ethhdr;
|
||||
unsigned char *buf;
|
||||
size_t len;
|
||||
|
||||
packet = pcap_next(pcap, &hdr);
|
||||
|
||||
if (packet == NULL || hdr.caplen < sizeof(*ethhdr))
|
||||
return;
|
||||
|
||||
ethhdr = (struct l2_ethhdr *) packet;
|
||||
if (l2->rx_l2_hdr) {
|
||||
buf = (unsigned char *) ethhdr;
|
||||
len = hdr.caplen;
|
||||
} else {
|
||||
buf = (unsigned char *) (ethhdr + 1);
|
||||
len = hdr.caplen - sizeof(*ethhdr);
|
||||
}
|
||||
l2->rx_callback(l2->rx_callback_ctx, ethhdr->h_source, buf, len);
|
||||
}
|
||||
|
||||
static int
|
||||
l2_packet_init_libpcap(struct l2_packet_data *l2, unsigned short protocol)
|
||||
{
|
||||
bpf_u_int32 pcap_maskp, pcap_netp;
|
||||
char pcap_filter[100], pcap_err[PCAP_ERRBUF_SIZE];
|
||||
struct bpf_program pcap_fp;
|
||||
|
||||
pcap_lookupnet(l2->ifname, &pcap_netp, &pcap_maskp, pcap_err);
|
||||
l2->pcap = pcap_open_live(l2->ifname, 2500, 0, 10, pcap_err);
|
||||
if (l2->pcap == NULL) {
|
||||
fprintf(stderr, "pcap_open_live: %s\n", pcap_err);
|
||||
fprintf(stderr, "ifname='%s'\n", l2->ifname);
|
||||
return -1;
|
||||
}
|
||||
if (pcap_datalink(l2->pcap) != DLT_EN10MB &&
|
||||
pcap_set_datalink(l2->pcap, DLT_EN10MB) < 0) {
|
||||
fprintf(stderr, "pcap_set_datalinke(DLT_EN10MB): %s\n",
|
||||
pcap_geterr(l2->pcap));
|
||||
return -1;
|
||||
}
|
||||
snprintf(pcap_filter, sizeof(pcap_filter),
|
||||
"ether dst " MACSTR " and ether proto 0x%x",
|
||||
MAC2STR(l2->own_addr), protocol);
|
||||
if (pcap_compile(l2->pcap, &pcap_fp, pcap_filter, 1, pcap_netp) < 0) {
|
||||
fprintf(stderr, "pcap_compile: %s\n", pcap_geterr(l2->pcap));
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (pcap_setfilter(l2->pcap, &pcap_fp) < 0) {
|
||||
fprintf(stderr, "pcap_setfilter: %s\n", pcap_geterr(l2->pcap));
|
||||
return -1;
|
||||
}
|
||||
|
||||
pcap_freecode(&pcap_fp);
|
||||
/*
|
||||
* When libpcap uses BPF we must enable "immediate mode" to
|
||||
* receive frames right away; otherwise the system may
|
||||
* buffer them for us.
|
||||
*/
|
||||
{ unsigned int on = 1;
|
||||
if (ioctl(pcap_fileno(l2->pcap), BIOCIMMEDIATE, &on) < 0) {
|
||||
fprintf(stderr, "%s: cannot enable immediate mode on "
|
||||
"interface %s: %s\n",
|
||||
__func__, l2->ifname, strerror(errno));
|
||||
/* XXX should we fail? */
|
||||
}
|
||||
}
|
||||
|
||||
eloop_register_read_sock(pcap_get_selectable_fd(l2->pcap),
|
||||
l2_packet_receive, l2, l2->pcap);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
eth_get(const char *device, u8 ea[ETH_ALEN])
|
||||
{
|
||||
struct if_msghdr *ifm;
|
||||
struct sockaddr_dl *sdl;
|
||||
u_char *p, *buf;
|
||||
size_t len;
|
||||
int mib[] = { CTL_NET, AF_ROUTE, 0, AF_LINK, NET_RT_IFLIST, 0 };
|
||||
|
||||
if (sysctl(mib, 6, NULL, &len, NULL, 0) < 0)
|
||||
return -1;
|
||||
if ((buf = malloc(len)) == NULL)
|
||||
return -1;
|
||||
if (sysctl(mib, 6, buf, &len, NULL, 0) < 0) {
|
||||
free(buf);
|
||||
return -1;
|
||||
}
|
||||
for (p = buf; p < buf + len; p += ifm->ifm_msglen) {
|
||||
ifm = (struct if_msghdr *)p;
|
||||
sdl = (struct sockaddr_dl *)(ifm + 1);
|
||||
if (ifm->ifm_type != RTM_IFINFO ||
|
||||
(ifm->ifm_addrs & RTA_IFP) == 0)
|
||||
continue;
|
||||
if (sdl->sdl_family != AF_LINK || sdl->sdl_nlen == 0 ||
|
||||
memcmp(sdl->sdl_data, device, sdl->sdl_nlen) != 0)
|
||||
continue;
|
||||
memcpy(ea, LLADDR(sdl), sdl->sdl_alen);
|
||||
break;
|
||||
}
|
||||
free(buf);
|
||||
|
||||
if (p >= buf + len) {
|
||||
errno = ESRCH;
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct l2_packet_data *
|
||||
l2_packet_init(const char *ifname, const u8 *own_addr, unsigned short protocol,
|
||||
void (*rx_callback)(void *ctx, unsigned char *src_addr,
|
||||
unsigned char *buf, size_t len),
|
||||
void *rx_callback_ctx)
|
||||
{
|
||||
struct l2_packet_data *l2;
|
||||
|
||||
l2 = malloc(sizeof(struct l2_packet_data));
|
||||
if (l2 == NULL)
|
||||
return NULL;
|
||||
memset(l2, 0, sizeof(*l2));
|
||||
strncpy(l2->ifname, ifname, sizeof(l2->ifname));
|
||||
l2->rx_callback = rx_callback;
|
||||
l2->rx_callback_ctx = rx_callback_ctx;
|
||||
|
||||
if (eth_get(l2->ifname, l2->own_addr) < 0) {
|
||||
fprintf(stderr, "Failed to get link-level address for "
|
||||
"interface '%s'.\n", l2->ifname);
|
||||
free(l2);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (l2_packet_init_libpcap(l2, protocol) != 0) {
|
||||
free(l2);
|
||||
return NULL;
|
||||
}
|
||||
return l2;
|
||||
}
|
||||
|
||||
void
|
||||
l2_packet_deinit(struct l2_packet_data *l2)
|
||||
{
|
||||
if (l2 != NULL) {
|
||||
if (l2->pcap)
|
||||
pcap_close(l2->pcap);
|
||||
free(l2);
|
||||
}
|
||||
}
|
9
usr.sbin/wpa/wpa_cli/Makefile
Normal file
9
usr.sbin/wpa/wpa_cli/Makefile
Normal file
|
@ -0,0 +1,9 @@
|
|||
# $FreeBSD$
|
||||
|
||||
WPA_SUPPLICANT_DISTDIR?= ${.CURDIR}/../../../contrib/wpa_supplicant
|
||||
.PATH: ${WPA_SUPPLICANT_DISTDIR}
|
||||
|
||||
PROG= wpa_cli
|
||||
SRCS= wpa_cli.c wpa_ctrl.c
|
||||
|
||||
.include <bsd.prog.mk>
|
192
usr.sbin/wpa/wpa_cli/wpa_cli.1
Normal file
192
usr.sbin/wpa/wpa_cli/wpa_cli.1
Normal file
|
@ -0,0 +1,192 @@
|
|||
.\" Copyright (c) 2005 Sam Leffler <sam@errno.com>
|
||||
.\" All rights reserved.
|
||||
.\"
|
||||
.\" Redistribution and use in source and binary forms, with or without
|
||||
.\" modification, are permitted provided that the following conditions
|
||||
.\" are met:
|
||||
.\" 1. Redistributions of source code must retain the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer.
|
||||
.\" 2. Redistributions in binary form must reproduce the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer in the
|
||||
.\" documentation and/or other materials provided with the distribution.
|
||||
.\"
|
||||
.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
.\" SUCH DAMAGE.
|
||||
.\"
|
||||
.\" $FreeBSD$
|
||||
.\"
|
||||
.Dd June 3, 2005
|
||||
.Dt WPA_CLI 1
|
||||
.Os
|
||||
.Sh NAME
|
||||
.Nm wpa_cli
|
||||
.Nd "text-based frontend program for interacting with wpa_supplicant"
|
||||
.Sh SYNOPSIS
|
||||
.Nm
|
||||
.Op commands
|
||||
.Sh DESCRIPTION
|
||||
.Nm
|
||||
is a text-based frontend program for interacting with
|
||||
.Xr wpa_supplicant 1.
|
||||
.Nm
|
||||
is used to query current status,
|
||||
change configuration,
|
||||
trigger events,
|
||||
and
|
||||
request interactive user input.
|
||||
.Pp
|
||||
.Nm
|
||||
can show the
|
||||
current authentication status,
|
||||
selected security
|
||||
mode, dot11 and dot1x MIBs, etc.
|
||||
In addition,
|
||||
.Nm
|
||||
can configure EAPOL state machine
|
||||
parameters and trigger events like reassociation
|
||||
and IEEE 802.1X logoff/logon.
|
||||
.Nm
|
||||
provides a user interface to request authentication information,
|
||||
like username and password, if these are not included in the
|
||||
configuration.
|
||||
This can be used to implement,
|
||||
e.g., one-time-passwords or generic token card
|
||||
authentication where the authentication is based on a
|
||||
challenge-response that uses an external device for generating the
|
||||
response.
|
||||
.Pp
|
||||
The control interface of
|
||||
.Nm wpa_supplicant
|
||||
can be configured to allow
|
||||
non-root user access (ctrl_interface_group in the configuration file).
|
||||
This makes it possible to run
|
||||
.Nm
|
||||
with a normal user account.
|
||||
.Pp
|
||||
.Nm
|
||||
supports two modes: interactive and command line.
|
||||
Both modes share the same command set and the main difference
|
||||
is in interactive mode providing access to unsolicited messages
|
||||
(event messages, username/password requests).
|
||||
.Pp
|
||||
Interactive mode is started when
|
||||
.Nm
|
||||
is executed without with any parameters on the command line.
|
||||
Commands are then entered from the controlling terminal in
|
||||
response to the
|
||||
.Nm
|
||||
prompt.
|
||||
In command line mode, the same commands are
|
||||
entered as command line arguments.
|
||||
.Sh AUTHENTICATION PARAMETERS
|
||||
.Pp
|
||||
When
|
||||
.Nm wpa_supplicant
|
||||
needs authentication parameters, such as username and password,
|
||||
that are not present in the configuration file, it sends a
|
||||
request message to all attached frontend programs, e.g.,
|
||||
.Nm
|
||||
in interactive mode.
|
||||
.Nm
|
||||
shows these requests with
|
||||
"CTRL-REQ-<type>-<id>:<text>" prefix.
|
||||
<type> is IDENTITY, PASSWORD, or OTP (one-time-password).
|
||||
<id> is a unique identifier for the current network.
|
||||
<text> is description of the request.
|
||||
In case of OTP request, it includes the challenge from
|
||||
the authentication server.
|
||||
.Pp
|
||||
A user must supply
|
||||
.Nm wpa_supplicant
|
||||
the needed parameters in response to these requests.
|
||||
.Pp
|
||||
For example,
|
||||
.Bd -literal
|
||||
CTRL-REQ-PASSWORD-1:Password needed for SSID foobar
|
||||
> password 1 mysecretpassword
|
||||
|
||||
Example request for generic token card challenge-response:
|
||||
|
||||
CTRL-REQ-OTP-2:Challenge 1235663 needed for SSID foobar
|
||||
> otp 2 9876
|
||||
.Ed
|
||||
.Sh COMMANDS
|
||||
The following commands may be supplied on the command line
|
||||
or at a prompt when operating interactively.
|
||||
.Bl -tag -width indent
|
||||
.It status
|
||||
Report the current WPA/EAPOL/EAP status for the current interface.
|
||||
.It mib
|
||||
Report MIB variables (dot1x, dot11) for the current interface.
|
||||
.It help
|
||||
Show usage help.
|
||||
.It interface [ Ar ifname ]
|
||||
Show available interfaces and/or set the current interface
|
||||
when multiple are available.
|
||||
.It level <debug level>
|
||||
Change the debugging level in
|
||||
.Nm wpa_supplicant .
|
||||
Larger numbers generate more messages.
|
||||
.It license
|
||||
Display the full
|
||||
.Nm
|
||||
license for
|
||||
.Nm .
|
||||
.It logoff
|
||||
Send the IEEE 802.1X EAPOL state machine into the logoff state.
|
||||
.It logon
|
||||
Send the IEEE 802.1X EAPOL state machine into the logon state.
|
||||
.It set [ settings ]
|
||||
Set variables.
|
||||
When no arguments are supplied the known variables and their settings
|
||||
are displayed.
|
||||
.It pmksa
|
||||
Show the contents of the PMKSA cache.
|
||||
.It reassociate
|
||||
Force a reassociation to the current access point.
|
||||
.It reconfigure
|
||||
Force
|
||||
.Nm
|
||||
to re-read its configuration file.
|
||||
.It preauthenticate <BSSID>
|
||||
Force preauthentication of the specified BSSID.
|
||||
.It identity <network id> <identity>
|
||||
Configure an identity for an SSID.
|
||||
.It password <network id> <password>
|
||||
Configure a password for an SSID.
|
||||
.It otp <network id> <password>
|
||||
Configure a one-time-password for an SSID.
|
||||
.It terminate
|
||||
Force
|
||||
.Nm wpa_supplicant
|
||||
to terminate.
|
||||
.It quit
|
||||
Exit
|
||||
.Nm .
|
||||
.El
|
||||
.Sh SEE ALSO
|
||||
.Xr wpa_supplicant 1 ,
|
||||
.Xr wpa_supplicant.conf 5
|
||||
.Sh HISTORY
|
||||
The
|
||||
.Nm
|
||||
utility first appeared in
|
||||
.Fx 6.0 .
|
||||
.Sh AUTHORS
|
||||
The
|
||||
.Nm
|
||||
utility was written by
|
||||
.An Jouni Malinen Aq jkmaline@cc.hut.fi .
|
||||
This manual page is derived from the README file included in the
|
||||
.Nm
|
||||
distribution.
|
||||
.Sh BUGS
|
40
usr.sbin/wpa/wpa_supplicant/Makefile
Normal file
40
usr.sbin/wpa/wpa_supplicant/Makefile
Normal file
|
@ -0,0 +1,40 @@
|
|||
# $FreeBSD$
|
||||
|
||||
WPA_SUPPLICANT_DISTDIR?= ${.CURDIR}/../../../contrib/wpa_supplicant
|
||||
.PATH: ${.CURDIR}/.. ${WPA_SUPPLICANT_DISTDIR}
|
||||
|
||||
PROG= wpa_supplicant
|
||||
SRCS= config.c eloop.c common.c md5.c rc4.c sha1.c aes_wrap.c \
|
||||
wpa_supplicant.c wpa.c \
|
||||
ctrl_iface.c l2_packet.c drivers.c driver_freebsd.c
|
||||
|
||||
CFLAGS+= -I${.CURDIR} -I${WPA_SUPPLICANT_DISTDIR}
|
||||
CFLAGS+= -DCONFIG_DRIVER_BSD
|
||||
CFLAGS+= -DCONFIG_CTRL_IFACE
|
||||
CFLAGS+= -g
|
||||
DPADD+= ${LIBPCAP}
|
||||
LDADD+= -lpcap
|
||||
|
||||
.if defined(ENABLE_WPA_SUPPLICANT_EAPOL)
|
||||
SRCS+= eapol_sm.c eap.c
|
||||
CFLAGS+= -DIEEE8021X_EAPOL
|
||||
|
||||
.if !defined(NO_CRYPT) && !defined(NO_OPENSSL) && !defined(RELEASE_CRUNCH)
|
||||
CFLAGS+=-DEAP_TLS -DEAP_PEAP -DEAP_MSCHAPv2 -DEAP_LEAP -DEAP_PSK \
|
||||
-DEAP_TLV -DEAP_TLS_FUNCS
|
||||
SRCS+= eap_tls.c eap_peap.c eap_mschapv2.c eap_leap.c eap_psk.c \
|
||||
eap_tlv.c eap_tls_common.c tls_openssl.c ms_funcs.c crypto.c
|
||||
|
||||
# NB: requires patch to openssl
|
||||
#CFLAGS+= -DEAP_FAST
|
||||
#SRCS+= eap_fast.c
|
||||
|
||||
DPADD+= ${LIBCRYPTO}
|
||||
LDADD+= -lssl -lcrypto
|
||||
.else
|
||||
SRCS+= tls_none.c
|
||||
.endif
|
||||
|
||||
.endif
|
||||
|
||||
.include <bsd.prog.mk>
|
636
usr.sbin/wpa/wpa_supplicant/driver_freebsd.c
Normal file
636
usr.sbin/wpa/wpa_supplicant/driver_freebsd.c
Normal file
|
@ -0,0 +1,636 @@
|
|||
/*
|
||||
* WPA Supplicant - driver interaction with BSD net80211 layer
|
||||
* Copyright (c) 2004, Sam Leffler <sam@errno.com>
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "common.h"
|
||||
#include "driver.h"
|
||||
#include "eloop.h"
|
||||
#include "wpa_supplicant.h"
|
||||
#include "l2_packet.h"
|
||||
|
||||
#include <sys/socket.h>
|
||||
#include <net/if.h>
|
||||
|
||||
#include <net80211/ieee80211.h>
|
||||
#include <net80211/ieee80211_crypto.h>
|
||||
#include <net80211/ieee80211_ioctl.h>
|
||||
|
||||
struct wpa_driver_bsd_data {
|
||||
int sock; /* open socket for 802.11 ioctls */
|
||||
int route; /* routing socket for events */
|
||||
char ifname[IFNAMSIZ+1]; /* interface name */
|
||||
void *ctx;
|
||||
};
|
||||
|
||||
static int
|
||||
set80211var(struct wpa_driver_bsd_data *drv, int op, const void *arg, int arg_len)
|
||||
{
|
||||
struct ieee80211req ireq;
|
||||
|
||||
memset(&ireq, 0, sizeof(ireq));
|
||||
strncpy(ireq.i_name, drv->ifname, IFNAMSIZ);
|
||||
ireq.i_type = op;
|
||||
ireq.i_len = arg_len;
|
||||
ireq.i_data = (void *) arg;
|
||||
|
||||
if (ioctl(drv->sock, SIOCS80211, &ireq) < 0) {
|
||||
perror("ioctl[SIOCS80211]");
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
get80211var(struct wpa_driver_bsd_data *drv, int op, void *arg, int arg_len)
|
||||
{
|
||||
struct ieee80211req ireq;
|
||||
|
||||
memset(&ireq, 0, sizeof(ireq));
|
||||
strncpy(ireq.i_name, drv->ifname, IFNAMSIZ);
|
||||
ireq.i_type = op;
|
||||
ireq.i_len = arg_len;
|
||||
ireq.i_data = arg;
|
||||
|
||||
if (ioctl(drv->sock, SIOCG80211, &ireq) < 0) {
|
||||
perror("ioctl[SIOCG80211]");
|
||||
return -1;
|
||||
}
|
||||
return ireq.i_len;
|
||||
}
|
||||
|
||||
static int
|
||||
set80211param(struct wpa_driver_bsd_data *drv, int op, int arg)
|
||||
{
|
||||
struct ieee80211req ireq;
|
||||
|
||||
memset(&ireq, 0, sizeof(ireq));
|
||||
strncpy(ireq.i_name, drv->ifname, IFNAMSIZ);
|
||||
ireq.i_type = op;
|
||||
ireq.i_val = arg;
|
||||
|
||||
if (ioctl(drv->sock, SIOCS80211, &ireq) < 0) {
|
||||
perror("ioctl[SIOCS80211]");
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
getifflags(struct wpa_driver_bsd_data *drv, int *flags)
|
||||
{
|
||||
struct ifreq ifr;
|
||||
|
||||
memset(&ifr, 0, sizeof(ifr));
|
||||
strncpy(ifr.ifr_name, drv->ifname, sizeof (ifr.ifr_name));
|
||||
if (ioctl(drv->sock, SIOCGIFFLAGS, (caddr_t)&ifr) < 0) {
|
||||
perror("SIOCGIFFLAGS");
|
||||
return errno;
|
||||
}
|
||||
*flags = ifr.ifr_flags & 0xffff;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
setifflags(struct wpa_driver_bsd_data *drv, int flags)
|
||||
{
|
||||
struct ifreq ifr;
|
||||
|
||||
memset(&ifr, 0, sizeof(ifr));
|
||||
strncpy(ifr.ifr_name, drv->ifname, sizeof (ifr.ifr_name));
|
||||
ifr.ifr_flags = flags & 0xffff;
|
||||
if (ioctl(drv->sock, SIOCSIFFLAGS, (caddr_t)&ifr) < 0) {
|
||||
perror("SIOCSIFFLAGS");
|
||||
return errno;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
wpa_driver_bsd_get_bssid(void *priv, u8 *bssid)
|
||||
{
|
||||
struct wpa_driver_bsd_data *drv = priv;
|
||||
|
||||
return get80211var(drv, IEEE80211_IOC_BSSID,
|
||||
bssid, IEEE80211_ADDR_LEN) < 0 ? -1 : 0;
|
||||
}
|
||||
|
||||
#if 0
|
||||
static int
|
||||
wpa_driver_bsd_set_bssid(void *priv, const char *bssid)
|
||||
{
|
||||
struct wpa_driver_bsd_data *drv = priv;
|
||||
|
||||
return set80211var(drv, IEEE80211_IOC_BSSID,
|
||||
bssid, IEEE80211_ADDR_LEN);
|
||||
}
|
||||
#endif
|
||||
|
||||
static int
|
||||
wpa_driver_bsd_get_ssid(void *priv, u8 *ssid)
|
||||
{
|
||||
struct wpa_driver_bsd_data *drv = priv;
|
||||
|
||||
return get80211var(drv, IEEE80211_IOC_SSID,
|
||||
ssid, IEEE80211_NWID_LEN);
|
||||
}
|
||||
|
||||
static int
|
||||
wpa_driver_bsd_set_ssid(void *priv, const char *ssid,
|
||||
size_t ssid_len)
|
||||
{
|
||||
struct wpa_driver_bsd_data *drv = priv;
|
||||
|
||||
return set80211var(drv, IEEE80211_IOC_SSID, ssid, ssid_len);
|
||||
}
|
||||
|
||||
static int
|
||||
wpa_driver_bsd_set_wpa_ie(struct wpa_driver_bsd_data *drv,
|
||||
const char *wpa_ie, size_t wpa_ie_len)
|
||||
{
|
||||
return set80211var(drv, IEEE80211_IOC_OPTIE, wpa_ie, wpa_ie_len);
|
||||
}
|
||||
|
||||
static int
|
||||
wpa_driver_bsd_set_wpa(void *priv, int enabled)
|
||||
{
|
||||
struct wpa_driver_bsd_data *drv = priv;
|
||||
int ret = 0;
|
||||
|
||||
wpa_printf(MSG_DEBUG, "%s: enabled=%d", __FUNCTION__, enabled);
|
||||
|
||||
if (!enabled && wpa_driver_bsd_set_wpa_ie(drv, NULL, 0) < 0)
|
||||
ret = -1;
|
||||
if (set80211param(drv, IEEE80211_IOC_ROAMING, enabled ? 2 : 0) < 0)
|
||||
ret = -1;
|
||||
if (set80211param(drv, IEEE80211_IOC_PRIVACY, enabled) < 0)
|
||||
ret = -1;
|
||||
if (set80211param(drv, IEEE80211_IOC_WPA, enabled ? 3 : 0) < 0)
|
||||
ret = -1;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int
|
||||
wpa_driver_bsd_del_key(struct wpa_driver_bsd_data *drv, int key_idx,
|
||||
const unsigned char *addr)
|
||||
{
|
||||
struct ieee80211req_del_key wk;
|
||||
|
||||
wpa_printf(MSG_DEBUG, "%s: keyidx=%d", __FUNCTION__, key_idx);
|
||||
memset(&wk, 0, sizeof(wk));
|
||||
wk.idk_keyix = key_idx;
|
||||
if (addr != NULL)
|
||||
memcpy(wk.idk_macaddr, addr, IEEE80211_ADDR_LEN);
|
||||
|
||||
return set80211var(drv, IEEE80211_IOC_DELKEY, &wk, sizeof(wk));
|
||||
}
|
||||
|
||||
static int
|
||||
wpa_driver_bsd_set_key(void *priv, wpa_alg alg,
|
||||
const unsigned char *addr, int key_idx, int set_tx,
|
||||
const u8 *seq, size_t seq_len,
|
||||
const u8 *key, size_t key_len)
|
||||
{
|
||||
struct wpa_driver_bsd_data *drv = priv;
|
||||
struct ieee80211req_key wk;
|
||||
char *alg_name;
|
||||
u_int8_t cipher;
|
||||
|
||||
if (alg == WPA_ALG_NONE)
|
||||
return wpa_driver_bsd_del_key(drv, key_idx, addr);
|
||||
|
||||
switch (alg) {
|
||||
case WPA_ALG_WEP:
|
||||
alg_name = "WEP";
|
||||
cipher = IEEE80211_CIPHER_WEP;
|
||||
break;
|
||||
case WPA_ALG_TKIP:
|
||||
alg_name = "TKIP";
|
||||
cipher = IEEE80211_CIPHER_TKIP;
|
||||
break;
|
||||
case WPA_ALG_CCMP:
|
||||
alg_name = "CCMP";
|
||||
cipher = IEEE80211_CIPHER_AES_CCM;
|
||||
break;
|
||||
default:
|
||||
wpa_printf(MSG_DEBUG, "%s: unknown/unsupported algorithm %d",
|
||||
__FUNCTION__, alg);
|
||||
return -1;
|
||||
}
|
||||
|
||||
wpa_printf(MSG_DEBUG, "%s: alg=%s key_idx=%d set_tx=%d seq_len=%d "
|
||||
"key_len=%d", __FUNCTION__, alg_name, key_idx, set_tx,
|
||||
seq_len, key_len);
|
||||
|
||||
if (seq_len > sizeof(u_int64_t)) {
|
||||
wpa_printf(MSG_DEBUG, "%s: seq_len %d too big",
|
||||
__FUNCTION__, seq_len);
|
||||
return -2;
|
||||
}
|
||||
if (key_len > sizeof(wk.ik_keydata)) {
|
||||
wpa_printf(MSG_DEBUG, "%s: key length %d too big",
|
||||
__FUNCTION__, key_len);
|
||||
return -3;
|
||||
}
|
||||
|
||||
memset(&wk, 0, sizeof(wk));
|
||||
wk.ik_type = cipher;
|
||||
wk.ik_flags = IEEE80211_KEY_RECV;
|
||||
if (set_tx) {
|
||||
wk.ik_flags |= IEEE80211_KEY_XMIT | IEEE80211_KEY_DEFAULT;
|
||||
memcpy(wk.ik_macaddr, addr, IEEE80211_ADDR_LEN);
|
||||
} else
|
||||
memset(wk.ik_macaddr, 0, IEEE80211_ADDR_LEN);
|
||||
wk.ik_keyix = key_idx;
|
||||
wk.ik_keylen = key_len;
|
||||
memcpy(&wk.ik_keyrsc, seq, seq_len);
|
||||
memcpy(wk.ik_keydata, key, key_len);
|
||||
|
||||
return set80211var(drv, IEEE80211_IOC_WPAKEY, &wk, sizeof(wk));
|
||||
}
|
||||
|
||||
static int
|
||||
wpa_driver_bsd_set_countermeasures(void *priv, int enabled)
|
||||
{
|
||||
struct wpa_driver_bsd_data *drv = priv;
|
||||
|
||||
wpa_printf(MSG_DEBUG, "%s: enabled=%d", __FUNCTION__, enabled);
|
||||
return set80211param(drv, IEEE80211_IOC_COUNTERMEASURES, enabled);
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
wpa_driver_bsd_set_drop_unencrypted(void *priv, int enabled)
|
||||
{
|
||||
struct wpa_driver_bsd_data *drv = priv;
|
||||
|
||||
wpa_printf(MSG_DEBUG, "%s: enabled=%d", __FUNCTION__, enabled);
|
||||
return set80211param(drv, IEEE80211_IOC_DROPUNENCRYPTED, enabled);
|
||||
}
|
||||
|
||||
static int
|
||||
wpa_driver_bsd_deauthenticate(void *priv, const u8 *addr, int reason_code)
|
||||
{
|
||||
struct wpa_driver_bsd_data *drv = priv;
|
||||
struct ieee80211req_mlme mlme;
|
||||
|
||||
wpa_printf(MSG_DEBUG, "%s", __FUNCTION__);
|
||||
mlme.im_op = IEEE80211_MLME_DEAUTH;
|
||||
mlme.im_reason = reason_code;
|
||||
memcpy(mlme.im_macaddr, addr, IEEE80211_ADDR_LEN);
|
||||
return set80211var(drv, IEEE80211_IOC_MLME, &mlme, sizeof(mlme));
|
||||
}
|
||||
|
||||
static int
|
||||
wpa_driver_bsd_disassociate(void *priv, const u8 *addr, int reason_code)
|
||||
{
|
||||
struct wpa_driver_bsd_data *drv = priv;
|
||||
struct ieee80211req_mlme mlme;
|
||||
|
||||
wpa_printf(MSG_DEBUG, "%s", __FUNCTION__);
|
||||
mlme.im_op = IEEE80211_MLME_DISASSOC;
|
||||
mlme.im_reason = reason_code;
|
||||
memcpy(mlme.im_macaddr, addr, IEEE80211_ADDR_LEN);
|
||||
return set80211var(drv, IEEE80211_IOC_MLME, &mlme, sizeof(mlme));
|
||||
}
|
||||
|
||||
static int
|
||||
wpa_driver_bsd_associate(void *priv, struct wpa_driver_associate_params *params)
|
||||
{
|
||||
struct wpa_driver_bsd_data *drv = priv;
|
||||
struct ieee80211req_mlme mlme;
|
||||
|
||||
int ret = 0;
|
||||
|
||||
wpa_printf(MSG_DEBUG, "%s", __FUNCTION__);
|
||||
|
||||
/*
|
||||
* NB: Don't need to set the freq or cipher-related state as
|
||||
* this is implied by the bssid which is used to locate
|
||||
* the scanned node state which holds it. The ssid is
|
||||
* needed to disambiguate an AP that broadcasts multiple
|
||||
* ssid's but uses the same bssid.
|
||||
*/
|
||||
/* XXX error handling is wrong but unclear what to do... */
|
||||
if (wpa_driver_bsd_set_wpa_ie(drv, params->wpa_ie, params->wpa_ie_len) < 0)
|
||||
ret = -1;
|
||||
if (wpa_driver_bsd_set_ssid(drv, params->ssid, params->ssid_len) < 0)
|
||||
ret = -1;
|
||||
memset(&mlme, 0, sizeof(mlme));
|
||||
mlme.im_op = IEEE80211_MLME_ASSOC;
|
||||
memcpy(mlme.im_macaddr, params->bssid, IEEE80211_ADDR_LEN);
|
||||
if (set80211var(drv, IEEE80211_IOC_MLME, &mlme, sizeof(mlme)) < 0)
|
||||
ret = -1;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int
|
||||
wpa_driver_bsd_scan(void *priv, const u8 *ssid, size_t ssid_len)
|
||||
{
|
||||
struct wpa_driver_bsd_data *drv = priv;
|
||||
int flags;
|
||||
|
||||
/* NB: interface must be marked UP to do a scan */
|
||||
if (getifflags(drv, &flags) != 0 || setifflags(drv, flags | IFF_UP) != 0)
|
||||
return -1;
|
||||
|
||||
/* set desired ssid before scan */
|
||||
if (wpa_driver_bsd_set_ssid(drv, ssid, ssid_len) < 0)
|
||||
return -1;
|
||||
|
||||
/* NB: net80211 delivers a scan complete event so no need to poll */
|
||||
return set80211param(drv, IEEE80211_IOC_SCAN_REQ, 0);
|
||||
}
|
||||
|
||||
#include <net/route.h>
|
||||
#include <net80211/ieee80211_freebsd.h>
|
||||
|
||||
static void
|
||||
wpa_driver_bsd_event_receive(int sock, void *ctx, void *sock_ctx)
|
||||
{
|
||||
char buf[2048];
|
||||
struct if_announcemsghdr *ifan;
|
||||
struct rt_msghdr *rtm;
|
||||
union wpa_event_data event;
|
||||
struct ieee80211_michael_event *mic;
|
||||
int n;
|
||||
|
||||
n = read(sock, buf, sizeof(buf));
|
||||
if (n < 0) {
|
||||
if (errno != EINTR && errno != EAGAIN)
|
||||
perror("read(PF_ROUTE)");
|
||||
return;
|
||||
}
|
||||
|
||||
rtm = (struct rt_msghdr *) buf;
|
||||
if (rtm->rtm_version != RTM_VERSION) {
|
||||
wpa_printf(MSG_DEBUG, "Routing message version %d not "
|
||||
"understood\n", rtm->rtm_version);
|
||||
return;
|
||||
}
|
||||
ifan = (struct if_announcemsghdr *) rtm;
|
||||
switch (rtm->rtm_type) {
|
||||
case RTM_IFANNOUNCE:
|
||||
memset(&event, 0, sizeof(event));
|
||||
/* XXX name buffer must be >= IFNAMSIZ */
|
||||
/* XXX check return value */
|
||||
if_indextoname(ifan->ifan_index, event.interface_status.ifname);
|
||||
switch (ifan->ifan_what) {
|
||||
case IFAN_ARRIVAL:
|
||||
event.interface_status.ievent = EVENT_INTERFACE_ADDED;
|
||||
break;
|
||||
case IFAN_DEPARTURE:
|
||||
event.interface_status.ievent = EVENT_INTERFACE_REMOVED;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
wpa_printf(MSG_DEBUG, "RTM_IFANNOUNCE: Interface '%s' %s",
|
||||
event.interface_status.ifname,
|
||||
ifan->ifan_what == IFAN_DEPARTURE ?
|
||||
"removed" : "added");
|
||||
wpa_supplicant_event(ctx, EVENT_INTERFACE_STATUS, &event);
|
||||
break;
|
||||
case RTM_IEEE80211:
|
||||
switch (ifan->ifan_what) {
|
||||
case RTM_IEEE80211_ASSOC:
|
||||
case RTM_IEEE80211_REASSOC:
|
||||
wpa_supplicant_event(ctx, EVENT_ASSOC, NULL);
|
||||
break;
|
||||
case RTM_IEEE80211_DISASSOC:
|
||||
wpa_supplicant_event(ctx, EVENT_DISASSOC, NULL);
|
||||
break;
|
||||
case RTM_IEEE80211_SCAN:
|
||||
wpa_supplicant_event(ctx, EVENT_SCAN_RESULTS, NULL);
|
||||
break;
|
||||
case RTM_IEEE80211_REPLAY:
|
||||
/* ignore */
|
||||
break;
|
||||
case RTM_IEEE80211_MICHAEL:
|
||||
mic = (struct ieee80211_michael_event *) &ifan[1];
|
||||
wpa_printf(MSG_DEBUG,
|
||||
"Michael MIC failure wireless event: "
|
||||
"keyix=%u src_addr=" MACSTR, mic->iev_keyix,
|
||||
MAC2STR(mic->iev_src));
|
||||
|
||||
memset(&event, 0, sizeof(event));
|
||||
event.michael_mic_failure.unicast =
|
||||
!IEEE80211_IS_MULTICAST(mic->iev_dst);
|
||||
wpa_supplicant_event(ctx, EVENT_MICHAEL_MIC_FAILURE,
|
||||
&event);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Compare function for sorting scan results. Return >0 if @b is consider
|
||||
* better. */
|
||||
static int
|
||||
wpa_scan_result_compar(const void *a, const void *b)
|
||||
{
|
||||
const struct wpa_scan_result *wa = a;
|
||||
const struct wpa_scan_result *wb = b;
|
||||
|
||||
/* WPA/WPA2 support preferred */
|
||||
if ((wb->wpa_ie_len || wb->rsn_ie_len) &&
|
||||
!(wa->wpa_ie_len || wa->rsn_ie_len))
|
||||
return 1;
|
||||
if (!(wb->wpa_ie_len || wb->rsn_ie_len) &&
|
||||
(wa->wpa_ie_len || wa->rsn_ie_len))
|
||||
return -1;
|
||||
|
||||
/* privacy support preferred */
|
||||
if ((wa->caps & IEEE80211_CAPINFO_PRIVACY) &&
|
||||
(wb->caps & IEEE80211_CAPINFO_PRIVACY) == 0)
|
||||
return 1;
|
||||
if ((wa->caps & IEEE80211_CAPINFO_PRIVACY) == 0 &&
|
||||
(wb->caps & IEEE80211_CAPINFO_PRIVACY))
|
||||
return -1;
|
||||
|
||||
/* best/max rate preferred if signal level close enough XXX */
|
||||
if (wa->maxrate != wb->maxrate && abs(wb->level - wa->level) < 5)
|
||||
return wb->maxrate - wa->maxrate;
|
||||
|
||||
/* use freq for channel preference */
|
||||
|
||||
/* all things being equal, use signal level */
|
||||
return wb->level - wa->level;
|
||||
}
|
||||
|
||||
static int
|
||||
getmaxrate(uint8_t rates[15], uint8_t nrates)
|
||||
{
|
||||
int i, maxrate = -1;
|
||||
|
||||
for (i = 0; i < nrates; i++) {
|
||||
int rate = rates[i] & IEEE80211_RATE_VAL;
|
||||
if (rate > maxrate)
|
||||
rate = maxrate;
|
||||
}
|
||||
return maxrate;
|
||||
}
|
||||
|
||||
/* unalligned little endian access */
|
||||
#define LE_READ_4(p) \
|
||||
((u_int32_t) \
|
||||
((((const u_int8_t *)(p))[0] ) | \
|
||||
(((const u_int8_t *)(p))[1] << 8) | \
|
||||
(((const u_int8_t *)(p))[2] << 16) | \
|
||||
(((const u_int8_t *)(p))[3] << 24)))
|
||||
|
||||
static int __inline
|
||||
iswpaoui(const u_int8_t *frm)
|
||||
{
|
||||
return frm[1] > 3 && LE_READ_4(frm+2) == ((WPA_OUI_TYPE<<24)|WPA_OUI);
|
||||
}
|
||||
|
||||
static int
|
||||
wpa_driver_bsd_get_scan_results(void *priv,
|
||||
struct wpa_scan_result *results,
|
||||
size_t max_size)
|
||||
{
|
||||
#define min(a,b) ((a)>(b)?(b):(a))
|
||||
struct wpa_driver_bsd_data *drv = priv;
|
||||
uint8_t buf[24*1024];
|
||||
uint8_t *cp, *vp;
|
||||
struct ieee80211req_scan_result *sr;
|
||||
struct wpa_scan_result *wsr;
|
||||
int len, ielen;
|
||||
|
||||
memset(results, 0, max_size * sizeof(struct wpa_scan_result));
|
||||
|
||||
len = get80211var(drv, IEEE80211_IOC_SCAN_RESULTS, buf, sizeof(buf));
|
||||
if (len < 0)
|
||||
return -1;
|
||||
cp = buf;
|
||||
wsr = results;
|
||||
while (len >= sizeof(struct ieee80211req_scan_result)) {
|
||||
sr = (struct ieee80211req_scan_result *) cp;
|
||||
memcpy(wsr->bssid, sr->isr_bssid, IEEE80211_ADDR_LEN);
|
||||
wsr->ssid_len = sr->isr_ssid_len;
|
||||
wsr->freq = sr->isr_freq;
|
||||
wsr->noise = sr->isr_noise;
|
||||
wsr->qual = sr->isr_rssi;
|
||||
wsr->level = 0; /* XXX? */
|
||||
wsr->caps = sr->isr_capinfo;
|
||||
wsr->maxrate = getmaxrate(sr->isr_rates, sr->isr_nrates);
|
||||
vp = (u_int8_t *)(sr+1);
|
||||
memcpy(wsr->ssid, vp, sr->isr_ssid_len);
|
||||
if (sr->isr_ie_len > 0) {
|
||||
vp += sr->isr_ssid_len;
|
||||
ielen = sr->isr_ie_len;
|
||||
while (ielen > 0) {
|
||||
switch (vp[0]) {
|
||||
case IEEE80211_ELEMID_VENDOR:
|
||||
if (!iswpaoui(vp))
|
||||
break;
|
||||
wsr->wpa_ie_len =
|
||||
min(2+vp[1], SSID_MAX_WPA_IE_LEN);
|
||||
memcpy(wsr->wpa_ie, vp, wsr->wpa_ie_len);
|
||||
break;
|
||||
case IEEE80211_ELEMID_RSN:
|
||||
wsr->rsn_ie_len =
|
||||
min(2+vp[1], SSID_MAX_WPA_IE_LEN);
|
||||
memcpy(wsr->rsn_ie, vp, wsr->rsn_ie_len);
|
||||
break;
|
||||
}
|
||||
ielen -= 2+vp[1];
|
||||
vp += 2+vp[1];
|
||||
}
|
||||
}
|
||||
|
||||
cp += sr->isr_len, len -= sr->isr_len;
|
||||
wsr++;
|
||||
}
|
||||
qsort(results, wsr - results, sizeof(struct wpa_scan_result),
|
||||
wpa_scan_result_compar);
|
||||
|
||||
wpa_printf(MSG_DEBUG, "Received %d bytes of scan results (%d BSSes)",
|
||||
len, wsr - results);
|
||||
|
||||
return wsr - results;
|
||||
#undef min
|
||||
}
|
||||
|
||||
static void *
|
||||
wpa_driver_bsd_init(void *ctx, const char *ifname)
|
||||
{
|
||||
struct wpa_driver_bsd_data *drv;
|
||||
|
||||
drv = malloc(sizeof(*drv));
|
||||
if (drv == NULL)
|
||||
return NULL;
|
||||
memset(drv, 0, sizeof(*drv));
|
||||
drv->sock = socket(PF_INET, SOCK_DGRAM, 0);
|
||||
if (drv->sock < 0) {
|
||||
free(drv);
|
||||
return NULL;
|
||||
}
|
||||
drv->route = socket(PF_ROUTE, SOCK_RAW, 0);
|
||||
if (drv->route < 0) {
|
||||
close(drv->sock);
|
||||
free(drv);
|
||||
return NULL;
|
||||
}
|
||||
eloop_register_read_sock(drv->route,
|
||||
wpa_driver_bsd_event_receive, ctx, NULL);
|
||||
|
||||
drv->ctx = ctx;
|
||||
strncpy(drv->ifname, ifname, sizeof(drv->ifname));
|
||||
|
||||
return drv;
|
||||
}
|
||||
|
||||
static void
|
||||
wpa_driver_bsd_deinit(void *priv)
|
||||
{
|
||||
struct wpa_driver_bsd_data *drv = priv;
|
||||
int flags;
|
||||
|
||||
/* NB: mark interface down */
|
||||
if (getifflags(drv, &flags) == 0)
|
||||
(void) setifflags(drv, flags &~ IFF_UP);
|
||||
|
||||
(void) close(drv->route); /* ioctl socket */
|
||||
(void) close(drv->sock); /* event socket */
|
||||
free(drv);
|
||||
}
|
||||
|
||||
|
||||
struct wpa_driver_ops wpa_driver_bsd_ops = {
|
||||
.name = "bsd",
|
||||
.desc = "BSD 802.11 support (Atheros, etc.)",
|
||||
.init = wpa_driver_bsd_init,
|
||||
.deinit = wpa_driver_bsd_deinit,
|
||||
.get_bssid = wpa_driver_bsd_get_bssid,
|
||||
.get_ssid = wpa_driver_bsd_get_ssid,
|
||||
.set_wpa = wpa_driver_bsd_set_wpa,
|
||||
.set_key = wpa_driver_bsd_set_key,
|
||||
.set_countermeasures = wpa_driver_bsd_set_countermeasures,
|
||||
.set_drop_unencrypted = wpa_driver_bsd_set_drop_unencrypted,
|
||||
.scan = wpa_driver_bsd_scan,
|
||||
.get_scan_results = wpa_driver_bsd_get_scan_results,
|
||||
.deauthenticate = wpa_driver_bsd_deauthenticate,
|
||||
.disassociate = wpa_driver_bsd_disassociate,
|
||||
.associate = wpa_driver_bsd_associate,
|
||||
};
|
132
usr.sbin/wpa/wpa_supplicant/wpa_supplicant.1
Normal file
132
usr.sbin/wpa/wpa_supplicant/wpa_supplicant.1
Normal file
|
@ -0,0 +1,132 @@
|
|||
.\" Copyright (c) 2005 Sam Leffler <sam@errno.com>
|
||||
.\" All rights reserved.
|
||||
.\"
|
||||
.\" Redistribution and use in source and binary forms, with or without
|
||||
.\" modification, are permitted provided that the following conditions
|
||||
.\" are met:
|
||||
.\" 1. Redistributions of source code must retain the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer.
|
||||
.\" 2. Redistributions in binary form must reproduce the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer in the
|
||||
.\" documentation and/or other materials provided with the distribution.
|
||||
.\"
|
||||
.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
.\" SUCH DAMAGE.
|
||||
.\"
|
||||
.\" $FreeBSD$
|
||||
.\"
|
||||
.Dd June 3, 2005
|
||||
.Dt WPA_SUPPLICANT 8
|
||||
.Os
|
||||
.Sh NAME
|
||||
.Nm wpa_supplicant
|
||||
.Nd "WPA/802.11i Supplicant for wireless network devices"
|
||||
.Sh SYNOPSIS
|
||||
.Nm
|
||||
.Op Fl BddehLqqvw
|
||||
.Fl i Ar ifname
|
||||
.Fl c Ar config-file
|
||||
.Op Fl N i Ar ifname Fl c Ar config-file ....
|
||||
.Sh DESCRIPTION
|
||||
.Nm
|
||||
is an implementation of the WPA Supplicant component,
|
||||
i.e., the part that runs in the client stations.
|
||||
It implements WPA key negotiation with a WPA Authenticator
|
||||
and EAP authentication with Authentication Server.
|
||||
In addition, it controls the roaming and IEEE 802.11
|
||||
authentication/association of the wlan driver.
|
||||
.Pp
|
||||
.Nm
|
||||
is designed to be a "daemon" program that runs in the
|
||||
background and acts as the backend component controlling
|
||||
the wireless connection.
|
||||
.Nm
|
||||
supports separate frontend programs such as the
|
||||
text-based frontend,
|
||||
.Xr wpa_cli 8
|
||||
.Pp
|
||||
The following arguments must be specified on the command line:
|
||||
.Bl -tag -width indent
|
||||
.It Fl i Ar ifname
|
||||
Use the specified wireless interface.
|
||||
.It Fl c Ar config-file
|
||||
Use the settings in the specified configuration file when managing
|
||||
the specified wireless interface.
|
||||
See
|
||||
.Xr wpa_supplicant.conf 5
|
||||
for a description of the configuration file syntax.
|
||||
.Pp
|
||||
Changes to the configuration file can be reloaded by sending a
|
||||
.Nm SIGHUP
|
||||
to the
|
||||
.Nm
|
||||
processor or with the
|
||||
.Xr wpa_cli
|
||||
utility, using ``wpa_cli reconfigure''.
|
||||
.El
|
||||
.Sh OPTIONS
|
||||
The options are as follows:
|
||||
.Bl -tag -width indent
|
||||
.It Fl d
|
||||
Enable debugging messages.
|
||||
If this option is supplied twice more verbose messages are displayed.
|
||||
.It Fl e
|
||||
Use an external IEEE 802.1X Supplicant program and disable the
|
||||
internal Supplicant.
|
||||
This option is not normally used.
|
||||
.It Fl h
|
||||
Show help text.
|
||||
.It Fl q
|
||||
Decrease debugging verbosity (i.e. counteract the use of the
|
||||
.Fl d
|
||||
flag.
|
||||
.It Fl v
|
||||
Display version information on the terminal and exit.
|
||||
.It Fl w
|
||||
If the specified interface is not present, wait for it to be
|
||||
added; e.g. a cardbus device to be inserted.
|
||||
.It Fl B
|
||||
Detach from the controlling terminal and run as a daemon process
|
||||
in the background.
|
||||
.It Fl K
|
||||
Include key information in debugging output.
|
||||
.It Fl L
|
||||
Display the license for this program on the terminal and exit.
|
||||
.It Fl N Fl i Ar iface Fl Ar config-file
|
||||
Specify an additional interface and configuration file.
|
||||
If multiple interfaces are specified then
|
||||
.Nm
|
||||
will manage them all with a single process.
|
||||
.El
|
||||
.Sh SEE ALSO
|
||||
.Xr ath 4 ,
|
||||
.Xr iwi 4 ,
|
||||
.Xr ipw 4 ,
|
||||
.Xr ral 4 ,
|
||||
.Xr ural 4 ,
|
||||
.Xr wi 4 ,
|
||||
.Xr wpa_supplicant.conf 5 ,
|
||||
.Xr ifconfig 8
|
||||
.Sh HISTORY
|
||||
The
|
||||
.Nm
|
||||
utility first appeared in
|
||||
.Fx 6.0 .
|
||||
.Sh AUTHORS
|
||||
The
|
||||
.Nm
|
||||
utility was written by
|
||||
.An Jouni Malinen Aq jkmaline@cc.hut.fi .
|
||||
This manual page is derived from the README file included in the
|
||||
.Nm
|
||||
distribution.
|
||||
.Sh BUGS
|
157
usr.sbin/wpa/wpa_supplicant/wpa_supplicant.conf.5
Normal file
157
usr.sbin/wpa/wpa_supplicant/wpa_supplicant.conf.5
Normal file
|
@ -0,0 +1,157 @@
|
|||
.\" Copyright (c) 2005 Sam Leffler <sam@errno.com>
|
||||
.\" All rights reserved.
|
||||
.\"
|
||||
.\" Redistribution and use in source and binary forms, with or without
|
||||
.\" modification, are permitted provided that the following conditions
|
||||
.\" are met:
|
||||
.\" 1. Redistributions of source code must retain the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer.
|
||||
.\" 2. Redistributions in binary form must reproduce the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer in the
|
||||
.\" documentation and/or other materials provided with the distribution.
|
||||
.\"
|
||||
.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
.\" SUCH DAMAGE.
|
||||
.\"
|
||||
.\" $FreeBSD$
|
||||
.\"
|
||||
.Dd June 3, 2005
|
||||
.Dt WPA_SUPPLICANT.CONF 5
|
||||
.Os
|
||||
.Sh NAME
|
||||
.Nm wpa_supplicant.conf
|
||||
.Nd "configuration file for wpa_supplicant utility"
|
||||
.Sh DESCRIPTION
|
||||
The
|
||||
.Xr wpa_supplicant 1
|
||||
program is an implementation of the WPA Supplicant component,
|
||||
i.e., the part that runs in the client stations.
|
||||
.Nm wpa_supplicant
|
||||
implements WPA key negotiation with a WPA Authenticator
|
||||
and EAP authentication with Authentication Server using
|
||||
configuration information stored in a text file.
|
||||
.Pp
|
||||
The configuration file consists of one or more network blocks, e.g.
|
||||
one for each used SSID.
|
||||
.Nm wpa_supplicant
|
||||
will automatically select the best network based on the order of
|
||||
the network blocks in the configuration file, network security level
|
||||
(WPA/WPA2 is preferred), and signal strength.
|
||||
.Sh CERTIFICATES
|
||||
.Pp
|
||||
Some EAP authentication methods require use of certificates.
|
||||
EAP-TLS uses both server- and client-side certificates,
|
||||
whereas EAP-PEAP and EAP-TTLS only require a server-side certificate.
|
||||
When a client certificate is used, a matching private key file must
|
||||
also be included in configuration.
|
||||
If the private key uses a passphrase, this
|
||||
has to be configured in the wpa_supplicant.conf file as "private_key_passwd".
|
||||
.Pp
|
||||
.Nm wpa_supplicant
|
||||
supports X.509 certificates in PEM and DER formats.
|
||||
User certificate and private key can be included in the same file.
|
||||
.Pp
|
||||
If the user certificate and private key is received in PKCS#12/PFX
|
||||
format, they need to be converted to suitable PEM/DER format for
|
||||
use by
|
||||
.Nm wpa_supplicant.
|
||||
This can be done using the
|
||||
.Xr openssl 1
|
||||
program, e.g. with following commands:
|
||||
.Bd -literal
|
||||
# convert client certificate and private key to PEM format
|
||||
openssl pkcs12 -in example.pfx -out user.pem -clcerts
|
||||
# convert CA certificate (if included in PFX file) to PEM format
|
||||
openssl pkcs12 -in example.pfx -out ca.pem -cacerts -nokeys
|
||||
.Be
|
||||
.Sh EXAMPLES
|
||||
.Pp
|
||||
WPA-Personal (PSK) as a home network and WPA-Enterprise with EAP-TLS
|
||||
as a work network:
|
||||
.Bd -literal
|
||||
# allow frontend (e.g., wpa_cli) to be used by all users in 'wheel' group
|
||||
ctrl_interface=/var/run/wpa_supplicant
|
||||
ctrl_interface_group=wheel
|
||||
#
|
||||
# home network; allow all valid ciphers
|
||||
network={
|
||||
ssid="home"
|
||||
scan_ssid=1
|
||||
key_mgmt=WPA-PSK
|
||||
psk="very secret passphrase"
|
||||
}
|
||||
#
|
||||
# work network; use EAP-TLS with WPA; allow only CCMP and TKIP ciphers
|
||||
network={
|
||||
ssid="work"
|
||||
scan_ssid=1
|
||||
key_mgmt=WPA-EAP
|
||||
pairwise=CCMP TKIP
|
||||
group=CCMP TKIP
|
||||
eap=TLS
|
||||
identity="user@example.com"
|
||||
ca_cert="/etc/cert/ca.pem"
|
||||
client_cert="/etc/cert/user.pem"
|
||||
private_key="/etc/cert/user.prv"
|
||||
private_key_passwd="password"
|
||||
}
|
||||
.Ed
|
||||
.Pp
|
||||
WPA-RADIUS/EAP-PEAP/MSCHAPv2 with RADIUS servers that use old peaplabel
|
||||
(e.g., Funk Odyssey and SBR, Meetinghouse Aegis, Interlink RAD-Series):
|
||||
.Bd -literal
|
||||
ctrl_interface=/var/run/wpa_supplicant
|
||||
ctrl_interface_group=wheel
|
||||
network={
|
||||
ssid="example"
|
||||
scan_ssid=1
|
||||
key_mgmt=WPA-EAP
|
||||
eap=PEAP
|
||||
identity="user@example.com"
|
||||
password="foobar"
|
||||
ca_cert="/etc/cert/ca.pem"
|
||||
phase1="peaplabel=0"
|
||||
phase2="auth=MSCHAPV2"
|
||||
}
|
||||
.Ed
|
||||
.Pp
|
||||
EAP-TTLS/EAP-MD5-Challenge configuration with anonymous identity for the
|
||||
unencrypted use. Real identity is sent only within an encrypted TLS tunnel.
|
||||
.Bd -literal
|
||||
ctrl_interface=/var/run/wpa_supplicant
|
||||
ctrl_interface_group=wheel
|
||||
network={
|
||||
ssid="example"
|
||||
scan_ssid=1
|
||||
key_mgmt=WPA-EAP
|
||||
eap=TTLS
|
||||
identity="user@example.com"
|
||||
anonymous_identity="anonymous@example.com"
|
||||
password="foobar"
|
||||
ca_cert="/etc/cert/ca.pem"
|
||||
phase2="auth=MD5"
|
||||
}
|
||||
.Ed
|
||||
.Sh SEE ALSO
|
||||
.Xr wpa_supplicant 1
|
||||
.Sh HISTORY
|
||||
The
|
||||
.Nm
|
||||
manual page and
|
||||
.Nm wpa_supplicant
|
||||
functionality first appeared in
|
||||
.Fx 6.0 .
|
||||
.Sh AUTHORS
|
||||
This manual page is derived from the README file in the
|
||||
.Nm wpa_supplicant
|
||||
distribution provided by
|
||||
.An Jouni Malinen Aq jkmaline@cc.hut.fi .
|
Loading…
Reference in a new issue