1 /* 2 * WPA Supplicant - Layer2 packet handling with FreeBSD 3 * Copyright (c) 2003-2005, Jouni Malinen <j (at) w1.fi> 4 * Copyright (c) 2005, Sam Leffler <sam (at) errno.com> 5 * 6 * This program is free software; you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License version 2 as 8 * published by the Free Software Foundation. 9 * 10 * Alternatively, this software may be distributed under the terms of BSD 11 * license. 12 * 13 * See README and COPYING for more details. 14 */ 15 16 #include "includes.h" 17 #if defined(__APPLE__) || defined(__GLIBC__) 18 #include <net/bpf.h> 19 #endif /* __APPLE__ */ 20 #include <pcap.h> 21 22 #include <sys/ioctl.h> 23 #ifdef __sun__ 24 #include <libdlpi.h> 25 #else /* __sun__ */ 26 #include <sys/sysctl.h> 27 #endif /* __sun__ */ 28 29 #include <net/if.h> 30 #include <net/if_dl.h> 31 #include <net/route.h> 32 #include <netinet/in.h> 33 34 #include "common.h" 35 #include "eloop.h" 36 #include "l2_packet.h" 37 38 39 static const u8 pae_group_addr[ETH_ALEN] = 40 { 0x01, 0x80, 0xc2, 0x00, 0x00, 0x03 }; 41 42 struct l2_packet_data { 43 pcap_t *pcap; 44 char ifname[100]; 45 u8 own_addr[ETH_ALEN]; 46 void (*rx_callback)(void *ctx, const u8 *src_addr, 47 const u8 *buf, size_t len); 48 void *rx_callback_ctx; 49 int l2_hdr; /* whether to include layer 2 (Ethernet) header data 50 * buffers */ 51 }; 52 53 54 int l2_packet_get_own_addr(struct l2_packet_data *l2, u8 *addr) 55 { 56 os_memcpy(addr, l2->own_addr, ETH_ALEN); 57 return 0; 58 } 59 60 61 int l2_packet_send(struct l2_packet_data *l2, const u8 *dst_addr, u16 proto, 62 const u8 *buf, size_t len) 63 { 64 if (!l2->l2_hdr) { 65 int ret; 66 struct l2_ethhdr *eth = os_malloc(sizeof(*eth) + len); 67 if (eth == NULL) 68 return -1; 69 os_memcpy(eth->h_dest, dst_addr, ETH_ALEN); 70 os_memcpy(eth->h_source, l2->own_addr, ETH_ALEN); 71 eth->h_proto = htons(proto); 72 os_memcpy(eth + 1, buf, len); 73 ret = pcap_inject(l2->pcap, (u8 *) eth, len + sizeof(*eth)); 74 os_free(eth); 75 return ret; 76 } else 77 return pcap_inject(l2->pcap, buf, len); 78 } 79 80 81 static void l2_packet_receive(int sock, void *eloop_ctx, void *sock_ctx) 82 { 83 struct l2_packet_data *l2 = eloop_ctx; 84 pcap_t *pcap = sock_ctx; 85 struct pcap_pkthdr hdr; 86 const u_char *packet; 87 struct l2_ethhdr *ethhdr; 88 unsigned char *buf; 89 size_t len; 90 91 packet = pcap_next(pcap, &hdr); 92 93 if (packet == NULL || hdr.caplen < sizeof(*ethhdr)) 94 return; 95 96 ethhdr = (struct l2_ethhdr *) packet; 97 if (l2->l2_hdr) { 98 buf = (unsigned char *) ethhdr; 99 len = hdr.caplen; 100 } else { 101 buf = (unsigned char *) (ethhdr + 1); 102 len = hdr.caplen - sizeof(*ethhdr); 103 } 104 l2->rx_callback(l2->rx_callback_ctx, ethhdr->h_source, buf, len); 105 } 106 107 108 static int l2_packet_init_libpcap(struct l2_packet_data *l2, 109 unsigned short protocol) 110 { 111 bpf_u_int32 pcap_maskp, pcap_netp; 112 char pcap_filter[200], pcap_err[PCAP_ERRBUF_SIZE]; 113 struct bpf_program pcap_fp; 114 115 pcap_lookupnet(l2->ifname, &pcap_netp, &pcap_maskp, pcap_err); 116 l2->pcap = pcap_open_live(l2->ifname, 2500, 0, 10, pcap_err); 117 if (l2->pcap == NULL) { 118 fprintf(stderr, "pcap_open_live: %s\n", pcap_err); 119 fprintf(stderr, "ifname='%s'\n", l2->ifname); 120 return -1; 121 } 122 if (pcap_datalink(l2->pcap) != DLT_EN10MB && 123 pcap_set_datalink(l2->pcap, DLT_EN10MB) < 0) { 124 fprintf(stderr, "pcap_set_datalink(DLT_EN10MB): %s\n", 125 pcap_geterr(l2->pcap)); 126 return -1; 127 } 128 os_snprintf(pcap_filter, sizeof(pcap_filter), 129 "not ether src " MACSTR " and " 130 "( ether dst " MACSTR " or ether dst " MACSTR " ) and " 131 "ether proto 0x%x", 132 MAC2STR(l2->own_addr), /* do not receive own packets */ 133 MAC2STR(l2->own_addr), MAC2STR(pae_group_addr), 134 protocol); 135 if (pcap_compile(l2->pcap, &pcap_fp, pcap_filter, 1, pcap_netp) < 0) { 136 fprintf(stderr, "pcap_compile: %s\n", pcap_geterr(l2->pcap)); 137 return -1; 138 } 139 140 if (pcap_setfilter(l2->pcap, &pcap_fp) < 0) { 141 fprintf(stderr, "pcap_setfilter: %s\n", pcap_geterr(l2->pcap)); 142 return -1; 143 } 144 145 pcap_freecode(&pcap_fp); 146 #ifndef __sun__ 147 /* 148 * When libpcap uses BPF we must enable "immediate mode" to 149 * receive frames right away; otherwise the system may 150 * buffer them for us. 151 */ 152 { 153 unsigned int on = 1; 154 if (ioctl(pcap_fileno(l2->pcap), BIOCIMMEDIATE, &on) < 0) { 155 fprintf(stderr, "%s: cannot enable immediate mode on " 156 "interface %s: %s\n", 157 __func__, l2->ifname, strerror(errno)); 158 /* XXX should we fail? */ 159 } 160 } 161 #endif /* __sun__ */ 162 163 eloop_register_read_sock(pcap_get_selectable_fd(l2->pcap), 164 l2_packet_receive, l2, l2->pcap); 165 166 return 0; 167 } 168 169 170 static int eth_get(const char *device, u8 ea[ETH_ALEN]) 171 { 172 #ifdef __sun__ 173 dlpi_handle_t dh; 174 u32 physaddrlen = DLPI_PHYSADDR_MAX; 175 u8 physaddr[DLPI_PHYSADDR_MAX]; 176 int retval; 177 178 retval = dlpi_open(device, &dh, 0); 179 if (retval != DLPI_SUCCESS) { 180 wpa_printf(MSG_ERROR, "dlpi_open error: %s", 181 dlpi_strerror(retval)); 182 return -1; 183 } 184 185 retval = dlpi_get_physaddr(dh, DL_CURR_PHYS_ADDR, physaddr, 186 &physaddrlen); 187 if (retval != DLPI_SUCCESS) { 188 wpa_printf(MSG_ERROR, "dlpi_get_physaddr error: %s", 189 dlpi_strerror(retval)); 190 dlpi_close(dh); 191 return -1; 192 } 193 os_memcpy(ea, physaddr, ETH_ALEN); 194 dlpi_close(dh); 195 #else /* __sun__ */ 196 struct if_msghdr *ifm; 197 struct sockaddr_dl *sdl; 198 u_char *p, *buf; 199 size_t len; 200 int mib[] = { CTL_NET, AF_ROUTE, 0, AF_LINK, NET_RT_IFLIST, 0 }; 201 202 if (sysctl(mib, 6, NULL, &len, NULL, 0) < 0) 203 return -1; 204 if ((buf = os_malloc(len)) == NULL) 205 return -1; 206 if (sysctl(mib, 6, buf, &len, NULL, 0) < 0) { 207 os_free(buf); 208 return -1; 209 } 210 for (p = buf; p < buf + len; p += ifm->ifm_msglen) { 211 ifm = (struct if_msghdr *)p; 212 sdl = (struct sockaddr_dl *)(ifm + 1); 213 if (ifm->ifm_type != RTM_IFINFO || 214 (ifm->ifm_addrs & RTA_IFP) == 0) 215 continue; 216 if (sdl->sdl_family != AF_LINK || sdl->sdl_nlen == 0 || 217 os_memcmp(sdl->sdl_data, device, sdl->sdl_nlen) != 0) 218 continue; 219 os_memcpy(ea, LLADDR(sdl), sdl->sdl_alen); 220 break; 221 } 222 os_free(buf); 223 224 if (p >= buf + len) { 225 errno = ESRCH; 226 return -1; 227 } 228 #endif /* __sun__ */ 229 return 0; 230 } 231 232 233 struct l2_packet_data * l2_packet_init( 234 const char *ifname, const u8 *own_addr, unsigned short protocol, 235 void (*rx_callback)(void *ctx, const u8 *src_addr, 236 const u8 *buf, size_t len), 237 void *rx_callback_ctx, int l2_hdr) 238 { 239 struct l2_packet_data *l2; 240 241 l2 = os_zalloc(sizeof(struct l2_packet_data)); 242 if (l2 == NULL) 243 return NULL; 244 os_strlcpy(l2->ifname, ifname, sizeof(l2->ifname)); 245 l2->rx_callback = rx_callback; 246 l2->rx_callback_ctx = rx_callback_ctx; 247 l2->l2_hdr = l2_hdr; 248 249 if (eth_get(l2->ifname, l2->own_addr) < 0) { 250 fprintf(stderr, "Failed to get link-level address for " 251 "interface '%s'.\n", l2->ifname); 252 os_free(l2); 253 return NULL; 254 } 255 256 if (l2_packet_init_libpcap(l2, protocol)) { 257 os_free(l2); 258 return NULL; 259 } 260 261 return l2; 262 } 263 264 265 void l2_packet_deinit(struct l2_packet_data *l2) 266 { 267 if (l2 != NULL) { 268 if (l2->pcap) { 269 eloop_unregister_read_sock( 270 pcap_get_selectable_fd(l2->pcap)); 271 pcap_close(l2->pcap); 272 } 273 os_free(l2); 274 } 275 } 276 277 278 int l2_packet_get_ip_addr(struct l2_packet_data *l2, char *buf, size_t len) 279 { 280 pcap_if_t *devs, *dev; 281 struct pcap_addr *addr; 282 struct sockaddr_in *saddr; 283 int found = 0; 284 char err[PCAP_ERRBUF_SIZE + 1]; 285 286 if (pcap_findalldevs(&devs, err) < 0) { 287 wpa_printf(MSG_DEBUG, "pcap_findalldevs: %s\n", err); 288 return -1; 289 } 290 291 for (dev = devs; dev && !found; dev = dev->next) { 292 if (os_strcmp(dev->name, l2->ifname) != 0) 293 continue; 294 295 addr = dev->addresses; 296 while (addr) { 297 saddr = (struct sockaddr_in *) addr->addr; 298 if (saddr && saddr->sin_family == AF_INET) { 299 os_strlcpy(buf, inet_ntoa(saddr->sin_addr), 300 len); 301 found = 1; 302 break; 303 } 304 addr = addr->next; 305 } 306 } 307 308 pcap_freealldevs(devs); 309 310 return found ? 0 : -1; 311 } 312 313 314 void l2_packet_notify_auth_start(struct l2_packet_data *l2) 315 { 316 } 317