diff options
author | grehan <grehan@FreeBSD.org> | 2013-07-05 05:47:10 +0000 |
---|---|---|
committer | grehan <grehan@FreeBSD.org> | 2013-07-05 05:47:10 +0000 |
commit | 6a7baaf83640e0eaa135d2f7a3c1d4401f1683bf (patch) | |
tree | 83ae82cf8f72af4b819f49aa52acdd97f74c6328 /contrib/wpa/src/l2_packet | |
parent | 2cb5a953f0a60811764ccaca7c37b51ff007c711 (diff) | |
parent | 8e6b84b998690dcfc1a4957dc7a483ac5b600db8 (diff) | |
download | FreeBSD-src-6a7baaf83640e0eaa135d2f7a3c1d4401f1683bf.zip FreeBSD-src-6a7baaf83640e0eaa135d2f7a3c1d4401f1683bf.tar.gz |
IFC @ r252763
Diffstat (limited to 'contrib/wpa/src/l2_packet')
-rw-r--r-- | contrib/wpa/src/l2_packet/Makefile | 8 | ||||
-rw-r--r-- | contrib/wpa/src/l2_packet/l2_packet.h | 10 | ||||
-rw-r--r-- | contrib/wpa/src/l2_packet/l2_packet_freebsd.c | 41 | ||||
-rw-r--r-- | contrib/wpa/src/l2_packet/l2_packet_ndis.c | 10 | ||||
-rw-r--r-- | contrib/wpa/src/l2_packet/l2_packet_none.c | 10 | ||||
-rw-r--r-- | contrib/wpa/src/l2_packet/l2_packet_privsep.c | 261 |
6 files changed, 300 insertions, 40 deletions
diff --git a/contrib/wpa/src/l2_packet/Makefile b/contrib/wpa/src/l2_packet/Makefile deleted file mode 100644 index 9c41962..0000000 --- a/contrib/wpa/src/l2_packet/Makefile +++ /dev/null @@ -1,8 +0,0 @@ -all: - @echo Nothing to be made. - -clean: - rm -f *~ *.o *.d - -install: - @echo Nothing to be made. diff --git a/contrib/wpa/src/l2_packet/l2_packet.h b/contrib/wpa/src/l2_packet/l2_packet.h index c7b5014..dd825b5 100644 --- a/contrib/wpa/src/l2_packet/l2_packet.h +++ b/contrib/wpa/src/l2_packet/l2_packet.h @@ -2,14 +2,8 @@ * WPA Supplicant - Layer2 packet interface definition * Copyright (c) 2003-2005, 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. + * This software may be distributed under the terms of the BSD license. + * See README for more details. * * This file defines an interface for layer 2 (link layer) packet sending and * receiving. l2_packet_linux.c is one implementation for such a layer 2 diff --git a/contrib/wpa/src/l2_packet/l2_packet_freebsd.c b/contrib/wpa/src/l2_packet/l2_packet_freebsd.c index 009e02c..2e9a04c 100644 --- a/contrib/wpa/src/l2_packet/l2_packet_freebsd.c +++ b/contrib/wpa/src/l2_packet/l2_packet_freebsd.c @@ -3,14 +3,8 @@ * Copyright (c) 2003-2005, Jouni Malinen <j@w1.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. + * This software may be distributed under the terms of the BSD license. + * See README for more details. */ #include "includes.h" @@ -20,7 +14,11 @@ #include <pcap.h> #include <sys/ioctl.h> +#ifdef __sun__ +#include <libdlpi.h> +#else /* __sun__ */ #include <sys/sysctl.h> +#endif /* __sun__ */ #include <net/if.h> #include <net/if_dl.h> @@ -139,6 +137,7 @@ static int l2_packet_init_libpcap(struct l2_packet_data *l2, } pcap_freecode(&pcap_fp); +#ifndef __sun__ /* * When libpcap uses BPF we must enable "immediate mode" to * receive frames right away; otherwise the system may @@ -153,6 +152,7 @@ static int l2_packet_init_libpcap(struct l2_packet_data *l2, /* XXX should we fail? */ } } +#endif /* __sun__ */ eloop_register_read_sock(pcap_get_selectable_fd(l2->pcap), l2_packet_receive, l2, l2->pcap); @@ -163,6 +163,30 @@ static int l2_packet_init_libpcap(struct l2_packet_data *l2, static int eth_get(const char *device, u8 ea[ETH_ALEN]) { +#ifdef __sun__ + dlpi_handle_t dh; + u32 physaddrlen = DLPI_PHYSADDR_MAX; + u8 physaddr[DLPI_PHYSADDR_MAX]; + int retval; + + retval = dlpi_open(device, &dh, 0); + if (retval != DLPI_SUCCESS) { + wpa_printf(MSG_ERROR, "dlpi_open error: %s", + dlpi_strerror(retval)); + return -1; + } + + retval = dlpi_get_physaddr(dh, DL_CURR_PHYS_ADDR, physaddr, + &physaddrlen); + if (retval != DLPI_SUCCESS) { + wpa_printf(MSG_ERROR, "dlpi_get_physaddr error: %s", + dlpi_strerror(retval)); + dlpi_close(dh); + return -1; + } + os_memcpy(ea, physaddr, ETH_ALEN); + dlpi_close(dh); +#else /* __sun__ */ struct if_msghdr *ifm; struct sockaddr_dl *sdl; u_char *p, *buf; @@ -195,6 +219,7 @@ static int eth_get(const char *device, u8 ea[ETH_ALEN]) errno = ESRCH; return -1; } +#endif /* __sun__ */ return 0; } diff --git a/contrib/wpa/src/l2_packet/l2_packet_ndis.c b/contrib/wpa/src/l2_packet/l2_packet_ndis.c index 6ce29aa..23b8ddc 100644 --- a/contrib/wpa/src/l2_packet/l2_packet_ndis.c +++ b/contrib/wpa/src/l2_packet/l2_packet_ndis.c @@ -2,14 +2,8 @@ * WPA Supplicant - Layer2 packet handling with Microsoft NDISUIO * Copyright (c) 2003-2006, 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. + * This software may be distributed under the terms of the BSD license. + * See README for more details. * * This implementation requires Windows specific event loop implementation, * i.e., eloop_win.c. In addition, the NDISUIO connection is shared with diff --git a/contrib/wpa/src/l2_packet/l2_packet_none.c b/contrib/wpa/src/l2_packet/l2_packet_none.c index 5e3f6e9..b01e830 100644 --- a/contrib/wpa/src/l2_packet/l2_packet_none.c +++ b/contrib/wpa/src/l2_packet/l2_packet_none.c @@ -2,14 +2,8 @@ * WPA Supplicant - Layer2 packet handling example with dummy functions * Copyright (c) 2003-2005, 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. + * This software may be distributed under the terms of the BSD license. + * See README for more details. * * This file can be used as a starting point for layer2 packet implementation. */ diff --git a/contrib/wpa/src/l2_packet/l2_packet_privsep.c b/contrib/wpa/src/l2_packet/l2_packet_privsep.c new file mode 100644 index 0000000..6b117ca --- /dev/null +++ b/contrib/wpa/src/l2_packet/l2_packet_privsep.c @@ -0,0 +1,261 @@ +/* + * WPA Supplicant - Layer2 packet handling with privilege separation + * Copyright (c) 2007, Jouni Malinen <j@w1.fi> + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#include "includes.h" +#include <sys/un.h> + +#include "common.h" +#include "eloop.h" +#include "l2_packet.h" +#include "common/privsep_commands.h" + + +struct l2_packet_data { + int fd; /* UNIX domain socket for privsep access */ + void (*rx_callback)(void *ctx, const u8 *src_addr, + const u8 *buf, size_t len); + void *rx_callback_ctx; + u8 own_addr[ETH_ALEN]; + char *own_socket_path; + struct sockaddr_un priv_addr; +}; + + +static int wpa_priv_cmd(struct l2_packet_data *l2, int cmd, + const void *data, size_t data_len) +{ + struct msghdr msg; + struct iovec io[2]; + + io[0].iov_base = &cmd; + io[0].iov_len = sizeof(cmd); + io[1].iov_base = (u8 *) data; + io[1].iov_len = data_len; + + os_memset(&msg, 0, sizeof(msg)); + msg.msg_iov = io; + msg.msg_iovlen = data ? 2 : 1; + msg.msg_name = &l2->priv_addr; + msg.msg_namelen = sizeof(l2->priv_addr); + + if (sendmsg(l2->fd, &msg, 0) < 0) { + perror("L2: sendmsg(cmd)"); + return -1; + } + + return 0; +} + + +int l2_packet_get_own_addr(struct l2_packet_data *l2, u8 *addr) +{ + os_memcpy(addr, l2->own_addr, ETH_ALEN); + return 0; +} + + +int l2_packet_send(struct l2_packet_data *l2, const u8 *dst_addr, u16 proto, + const u8 *buf, size_t len) +{ + struct msghdr msg; + struct iovec io[4]; + int cmd = PRIVSEP_CMD_L2_SEND; + + io[0].iov_base = &cmd; + io[0].iov_len = sizeof(cmd); + io[1].iov_base = &dst_addr; + io[1].iov_len = ETH_ALEN; + io[2].iov_base = &proto; + io[2].iov_len = 2; + io[3].iov_base = (u8 *) buf; + io[3].iov_len = len; + + os_memset(&msg, 0, sizeof(msg)); + msg.msg_iov = io; + msg.msg_iovlen = 4; + msg.msg_name = &l2->priv_addr; + msg.msg_namelen = sizeof(l2->priv_addr); + + if (sendmsg(l2->fd, &msg, 0) < 0) { + perror("L2: sendmsg(packet_send)"); + return -1; + } + + return 0; +} + + +static void l2_packet_receive(int sock, void *eloop_ctx, void *sock_ctx) +{ + struct l2_packet_data *l2 = eloop_ctx; + u8 buf[2300]; + int res; + struct sockaddr_un from; + socklen_t fromlen = sizeof(from); + + os_memset(&from, 0, sizeof(from)); + res = recvfrom(sock, buf, sizeof(buf), 0, (struct sockaddr *) &from, + &fromlen); + if (res < 0) { + perror("l2_packet_receive - recvfrom"); + return; + } + if (res < ETH_ALEN) { + wpa_printf(MSG_DEBUG, "L2: Too show packet received"); + return; + } + + if (from.sun_family != AF_UNIX || + os_strncmp(from.sun_path, l2->priv_addr.sun_path, + sizeof(from.sun_path)) != 0) { + wpa_printf(MSG_DEBUG, "L2: Received message from unexpected " + "source"); + return; + } + + l2->rx_callback(l2->rx_callback_ctx, buf, buf + ETH_ALEN, + res - ETH_ALEN); +} + + +struct l2_packet_data * l2_packet_init( + const char *ifname, const u8 *own_addr, unsigned short protocol, + void (*rx_callback)(void *ctx, const u8 *src_addr, + const u8 *buf, size_t len), + void *rx_callback_ctx, int l2_hdr) +{ + struct l2_packet_data *l2; + char *own_dir = "/tmp"; + char *priv_dir = "/var/run/wpa_priv"; + size_t len; + static unsigned int counter = 0; + struct sockaddr_un addr; + fd_set rfds; + struct timeval tv; + int res; + u8 reply[ETH_ALEN + 1]; + int reg_cmd[2]; + + l2 = os_zalloc(sizeof(struct l2_packet_data)); + if (l2 == NULL) + return NULL; + l2->rx_callback = rx_callback; + l2->rx_callback_ctx = rx_callback_ctx; + + len = os_strlen(own_dir) + 50; + l2->own_socket_path = os_malloc(len); + if (l2->own_socket_path == NULL) { + os_free(l2); + return NULL; + } + os_snprintf(l2->own_socket_path, len, "%s/wpa_privsep-l2-%d-%d", + own_dir, getpid(), counter++); + + l2->priv_addr.sun_family = AF_UNIX; + os_snprintf(l2->priv_addr.sun_path, sizeof(l2->priv_addr.sun_path), + "%s/%s", priv_dir, ifname); + + l2->fd = socket(PF_UNIX, SOCK_DGRAM, 0); + if (l2->fd < 0) { + perror("socket(PF_UNIX)"); + os_free(l2->own_socket_path); + l2->own_socket_path = NULL; + os_free(l2); + return NULL; + } + + os_memset(&addr, 0, sizeof(addr)); + addr.sun_family = AF_UNIX; + os_strlcpy(addr.sun_path, l2->own_socket_path, sizeof(addr.sun_path)); + if (bind(l2->fd, (struct sockaddr *) &addr, sizeof(addr)) < 0) { + perror("l2-pkt-privsep: bind(PF_UNIX)"); + goto fail; + } + + reg_cmd[0] = protocol; + reg_cmd[1] = l2_hdr; + if (wpa_priv_cmd(l2, PRIVSEP_CMD_L2_REGISTER, reg_cmd, sizeof(reg_cmd)) + < 0) { + wpa_printf(MSG_ERROR, "L2: Failed to register with wpa_priv"); + goto fail; + } + + FD_ZERO(&rfds); + FD_SET(l2->fd, &rfds); + tv.tv_sec = 5; + tv.tv_usec = 0; + res = select(l2->fd + 1, &rfds, NULL, NULL, &tv); + if (res < 0 && errno != EINTR) { + perror("select"); + goto fail; + } + + if (FD_ISSET(l2->fd, &rfds)) { + res = recv(l2->fd, reply, sizeof(reply), 0); + if (res < 0) { + perror("recv"); + goto fail; + } + } else { + wpa_printf(MSG_DEBUG, "L2: Timeout while waiting for " + "registration reply"); + goto fail; + } + + if (res != ETH_ALEN) { + wpa_printf(MSG_DEBUG, "L2: Unexpected registration reply " + "(len=%d)", res); + } + os_memcpy(l2->own_addr, reply, ETH_ALEN); + + eloop_register_read_sock(l2->fd, l2_packet_receive, l2, NULL); + + return l2; + +fail: + close(l2->fd); + l2->fd = -1; + unlink(l2->own_socket_path); + os_free(l2->own_socket_path); + l2->own_socket_path = NULL; + os_free(l2); + return NULL; +} + + +void l2_packet_deinit(struct l2_packet_data *l2) +{ + if (l2 == NULL) + return; + + if (l2->fd >= 0) { + wpa_priv_cmd(l2, PRIVSEP_CMD_L2_UNREGISTER, NULL, 0); + eloop_unregister_read_sock(l2->fd); + close(l2->fd); + } + + if (l2->own_socket_path) { + unlink(l2->own_socket_path); + os_free(l2->own_socket_path); + } + + os_free(l2); +} + + +int l2_packet_get_ip_addr(struct l2_packet_data *l2, char *buf, size_t len) +{ + /* TODO */ + return -1; +} + + +void l2_packet_notify_auth_start(struct l2_packet_data *l2) +{ + wpa_priv_cmd(l2, PRIVSEP_CMD_L2_NOTIFY_AUTH_START, NULL, 0); +} |