1526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt/* 2526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * WPA Supplicant - Layer2 packet handling with FreeBSD 3526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * Copyright (c) 2003-2005, Jouni Malinen <j@w1.fi> 4526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * Copyright (c) 2005, Sam Leffler <sam@errno.com> 5526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * 6526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * This program is free software; you can redistribute it and/or modify 7526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * it under the terms of the GNU General Public License version 2 as 8526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * published by the Free Software Foundation. 9526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * 10526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * Alternatively, this software may be distributed under the terms of BSD 11526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * license. 12526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * 13526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * See README and COPYING for more details. 14526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt */ 15526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 16526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#include "includes.h" 17526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#ifdef __APPLE__ 18526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#include <net/bpf.h> 19526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#endif /* __APPLE__ */ 20526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#include <pcap.h> 21526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 22526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#include <sys/ioctl.h> 23526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#include <sys/sysctl.h> 24526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 25526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#include <net/if.h> 26526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#include <net/if_dl.h> 27526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#include <net/route.h> 28526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#include <netinet/in.h> 29526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 30526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#include "common.h" 31526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#include "eloop.h" 32526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#include "l2_packet.h" 33526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 34526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 35526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic const u8 pae_group_addr[ETH_ALEN] = 36526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{ 0x01, 0x80, 0xc2, 0x00, 0x00, 0x03 }; 37526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 38526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstruct l2_packet_data { 39526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt pcap_t *pcap; 40526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt char ifname[100]; 41526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt u8 own_addr[ETH_ALEN]; 42526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt void (*rx_callback)(void *ctx, const u8 *src_addr, 43526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt const u8 *buf, size_t len); 44526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt void *rx_callback_ctx; 45526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt int l2_hdr; /* whether to include layer 2 (Ethernet) header data 46526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * buffers */ 47526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}; 48526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 49526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 50526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtint l2_packet_get_own_addr(struct l2_packet_data *l2, u8 *addr) 51526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{ 52526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_memcpy(addr, l2->own_addr, ETH_ALEN); 53526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return 0; 54526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt} 55526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 56526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 57526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtint l2_packet_send(struct l2_packet_data *l2, const u8 *dst_addr, u16 proto, 58526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt const u8 *buf, size_t len) 59526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{ 60526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (!l2->l2_hdr) { 61526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt int ret; 62526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct l2_ethhdr *eth = os_malloc(sizeof(*eth) + len); 63526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (eth == NULL) 64526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return -1; 65526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_memcpy(eth->h_dest, dst_addr, ETH_ALEN); 66526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_memcpy(eth->h_source, l2->own_addr, ETH_ALEN); 67526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt eth->h_proto = htons(proto); 68526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_memcpy(eth + 1, buf, len); 69526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt ret = pcap_inject(l2->pcap, (u8 *) eth, len + sizeof(*eth)); 70526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_free(eth); 71526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return ret; 72526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } else 73526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return pcap_inject(l2->pcap, buf, len); 74526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt} 75526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 76526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 77526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic void l2_packet_receive(int sock, void *eloop_ctx, void *sock_ctx) 78526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{ 79526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct l2_packet_data *l2 = eloop_ctx; 80526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt pcap_t *pcap = sock_ctx; 81526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct pcap_pkthdr hdr; 82526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt const u_char *packet; 83526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct l2_ethhdr *ethhdr; 84526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt unsigned char *buf; 85526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt size_t len; 86526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 87526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt packet = pcap_next(pcap, &hdr); 88526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 89526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (packet == NULL || hdr.caplen < sizeof(*ethhdr)) 90526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return; 91526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 92526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt ethhdr = (struct l2_ethhdr *) packet; 93526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (l2->l2_hdr) { 94526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt buf = (unsigned char *) ethhdr; 95526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt len = hdr.caplen; 96526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } else { 97526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt buf = (unsigned char *) (ethhdr + 1); 98526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt len = hdr.caplen - sizeof(*ethhdr); 99526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 100526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt l2->rx_callback(l2->rx_callback_ctx, ethhdr->h_source, buf, len); 101526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt} 102526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 103526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 104526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic int l2_packet_init_libpcap(struct l2_packet_data *l2, 105526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt unsigned short protocol) 106526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{ 107526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt bpf_u_int32 pcap_maskp, pcap_netp; 108526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt char pcap_filter[200], pcap_err[PCAP_ERRBUF_SIZE]; 109526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct bpf_program pcap_fp; 110526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 111526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt pcap_lookupnet(l2->ifname, &pcap_netp, &pcap_maskp, pcap_err); 112526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt l2->pcap = pcap_open_live(l2->ifname, 2500, 0, 10, pcap_err); 113526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (l2->pcap == NULL) { 114526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt fprintf(stderr, "pcap_open_live: %s\n", pcap_err); 115526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt fprintf(stderr, "ifname='%s'\n", l2->ifname); 116526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return -1; 117526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 118526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (pcap_datalink(l2->pcap) != DLT_EN10MB && 119526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt pcap_set_datalink(l2->pcap, DLT_EN10MB) < 0) { 120526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt fprintf(stderr, "pcap_set_datalink(DLT_EN10MB): %s\n", 121526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt pcap_geterr(l2->pcap)); 122526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return -1; 123526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 124526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_snprintf(pcap_filter, sizeof(pcap_filter), 125526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "not ether src " MACSTR " and " 126526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "( ether dst " MACSTR " or ether dst " MACSTR " ) and " 127526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "ether proto 0x%x", 128526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt MAC2STR(l2->own_addr), /* do not receive own packets */ 129526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt MAC2STR(l2->own_addr), MAC2STR(pae_group_addr), 130526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt protocol); 131526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (pcap_compile(l2->pcap, &pcap_fp, pcap_filter, 1, pcap_netp) < 0) { 132526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt fprintf(stderr, "pcap_compile: %s\n", pcap_geterr(l2->pcap)); 133526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return -1; 134526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 135526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 136526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (pcap_setfilter(l2->pcap, &pcap_fp) < 0) { 137526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt fprintf(stderr, "pcap_setfilter: %s\n", pcap_geterr(l2->pcap)); 138526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return -1; 139526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 140526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 141526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt pcap_freecode(&pcap_fp); 142526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt /* 143526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * When libpcap uses BPF we must enable "immediate mode" to 144526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * receive frames right away; otherwise the system may 145526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * buffer them for us. 146526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt */ 147526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt { 148526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt unsigned int on = 1; 149526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (ioctl(pcap_fileno(l2->pcap), BIOCIMMEDIATE, &on) < 0) { 150526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt fprintf(stderr, "%s: cannot enable immediate mode on " 151526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "interface %s: %s\n", 152526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt __func__, l2->ifname, strerror(errno)); 153526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt /* XXX should we fail? */ 154526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 155526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 156526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 157526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt eloop_register_read_sock(pcap_get_selectable_fd(l2->pcap), 158526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt l2_packet_receive, l2, l2->pcap); 159526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 160526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return 0; 161526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt} 162526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 163526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 164526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic int eth_get(const char *device, u8 ea[ETH_ALEN]) 165526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{ 166526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct if_msghdr *ifm; 167526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct sockaddr_dl *sdl; 168526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt u_char *p, *buf; 169526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt size_t len; 170526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt int mib[] = { CTL_NET, AF_ROUTE, 0, AF_LINK, NET_RT_IFLIST, 0 }; 171526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 172526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (sysctl(mib, 6, NULL, &len, NULL, 0) < 0) 173526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return -1; 174526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if ((buf = os_malloc(len)) == NULL) 175526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return -1; 176526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (sysctl(mib, 6, buf, &len, NULL, 0) < 0) { 177526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_free(buf); 178526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return -1; 179526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 180526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt for (p = buf; p < buf + len; p += ifm->ifm_msglen) { 181526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt ifm = (struct if_msghdr *)p; 182526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt sdl = (struct sockaddr_dl *)(ifm + 1); 183526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (ifm->ifm_type != RTM_IFINFO || 184526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt (ifm->ifm_addrs & RTA_IFP) == 0) 185526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt continue; 186526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (sdl->sdl_family != AF_LINK || sdl->sdl_nlen == 0 || 187526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_memcmp(sdl->sdl_data, device, sdl->sdl_nlen) != 0) 188526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt continue; 189526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_memcpy(ea, LLADDR(sdl), sdl->sdl_alen); 190526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt break; 191526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 192526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_free(buf); 193526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 194526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (p >= buf + len) { 195526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt errno = ESRCH; 196526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return -1; 197526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 198526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return 0; 199526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt} 200526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 201526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 202526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstruct l2_packet_data * l2_packet_init( 203526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt const char *ifname, const u8 *own_addr, unsigned short protocol, 204526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt void (*rx_callback)(void *ctx, const u8 *src_addr, 205526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt const u8 *buf, size_t len), 206526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt void *rx_callback_ctx, int l2_hdr) 207526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{ 208526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct l2_packet_data *l2; 209526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 210526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt l2 = os_zalloc(sizeof(struct l2_packet_data)); 211526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (l2 == NULL) 212526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return NULL; 213526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_strlcpy(l2->ifname, ifname, sizeof(l2->ifname)); 214526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt l2->rx_callback = rx_callback; 215526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt l2->rx_callback_ctx = rx_callback_ctx; 216526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt l2->l2_hdr = l2_hdr; 217526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 218526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (eth_get(l2->ifname, l2->own_addr) < 0) { 219526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt fprintf(stderr, "Failed to get link-level address for " 220526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "interface '%s'.\n", l2->ifname); 221526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_free(l2); 222526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return NULL; 223526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 224526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 225526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (l2_packet_init_libpcap(l2, protocol)) { 226526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_free(l2); 227526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return NULL; 228526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 229526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 230526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return l2; 231526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt} 232526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 233526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 234526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtvoid l2_packet_deinit(struct l2_packet_data *l2) 235526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{ 236526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (l2 != NULL) { 237526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (l2->pcap) { 238526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt eloop_unregister_read_sock( 239526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt pcap_get_selectable_fd(l2->pcap)); 240526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt pcap_close(l2->pcap); 241526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 242526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_free(l2); 243526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 244526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt} 245526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 246526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 247526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtint l2_packet_get_ip_addr(struct l2_packet_data *l2, char *buf, size_t len) 248526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{ 249526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt pcap_if_t *devs, *dev; 250526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct pcap_addr *addr; 251526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct sockaddr_in *saddr; 252526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt int found = 0; 253526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt char err[PCAP_ERRBUF_SIZE + 1]; 254526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 255526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (pcap_findalldevs(&devs, err) < 0) { 256526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_DEBUG, "pcap_findalldevs: %s\n", err); 257526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return -1; 258526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 259526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 260526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt for (dev = devs; dev && !found; dev = dev->next) { 261526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (os_strcmp(dev->name, l2->ifname) != 0) 262526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt continue; 263526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 264526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt addr = dev->addresses; 265526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt while (addr) { 266526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt saddr = (struct sockaddr_in *) addr->addr; 267526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (saddr && saddr->sin_family == AF_INET) { 268526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_strlcpy(buf, inet_ntoa(saddr->sin_addr), 269526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt len); 270526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt found = 1; 271526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt break; 272526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 273526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt addr = addr->next; 274526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 275526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 276526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 277526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt pcap_freealldevs(devs); 278526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 279526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return found ? 0 : -1; 280526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt} 281526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 282526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 283526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtvoid l2_packet_notify_auth_start(struct l2_packet_data *l2) 284526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{ 285526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt} 286