1 /* $OpenBSD: llc.c,v 1.5 2007/02/08 11:15:55 reyk Exp $ */ 2 3 /* 4 * Copyright (c) 2004, 2005 Reyk Floeter <reyk@openbsd.org> 5 * 6 * Permission to use, copy, modify, and distribute this software for any 7 * purpose with or without fee is hereby granted, provided that the above 8 * copyright notice and this permission notice appear in all copies. 9 * 10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 */ 18 19 #include <sys/param.h> 20 #include <sys/ioctl.h> 21 #include <sys/types.h> 22 #include <sys/socket.h> 23 #include <sys/time.h> 24 25 #include <net/if.h> 26 #include <net/if_dl.h> 27 #include <net/if_media.h> 28 #include <net/if_arp.h> 29 #include <net/if_llc.h> 30 #include <net/bpf.h> 31 32 #include <netinet/in.h> 33 #include <netinet/if_ether.h> 34 #include <arpa/inet.h> 35 36 #include <fcntl.h> 37 #include <stdio.h> 38 #include <stdlib.h> 39 #include <string.h> 40 #include <unistd.h> 41 42 #include "hostapd.h" 43 44 void 45 hostapd_llc_init(struct hostapd_config *cfg) 46 { 47 struct hostapd_iapp *iapp = &cfg->c_iapp; 48 struct ifreq ifr; 49 u_int i; 50 51 iapp->i_raw = hostapd_bpf_open(O_WRONLY); 52 cfg->c_flags |= HOSTAPD_CFG_F_RAW; 53 54 bzero(&ifr, sizeof(struct ifreq)); 55 (void)strlcpy(ifr.ifr_name, iapp->i_iface, sizeof(ifr.ifr_name)); 56 57 /* Associate the wired network interface to the BPF descriptor */ 58 if (ioctl(iapp->i_raw, BIOCSETIF, &ifr) == -1) 59 hostapd_fatal("failed to set BPF interface \"%s\": %s\n", 60 iapp->i_iface, strerror(errno)); 61 62 i = 1; 63 if (ioctl(iapp->i_raw, BIOCSHDRCMPLT, &i) == -1) 64 hostapd_fatal("failed to set BPF header completion: %s\n", 65 strerror(errno)); 66 67 /* Lock the BPF descriptor, no further configuration */ 68 if (ioctl(iapp->i_raw, BIOCLOCK, NULL) == -1) 69 hostapd_fatal("failed to lock BPF interface on \"%s\": %s\n", 70 iapp->i_iface, strerror(errno)); 71 } 72 73 int 74 hostapd_llc_send_xid(struct hostapd_config *cfg, struct hostapd_node *node) 75 { 76 struct hostapd_iapp *iapp = &cfg->c_iapp; 77 struct hostapd_llc *llc; 78 u_int8_t buf[ETHER_HDR_LEN + (LLC_UFRAMELEN * 2)]; 79 80 /* 81 * Send an IEEE 802.3 LLC XID frame which will possibly force 82 * our switch port on the wired network to learn the station's 83 * new MAC address. 84 */ 85 bzero(&buf, sizeof(buf)); 86 llc = (struct hostapd_llc *)&buf; 87 memset(&llc->x_hdr.ether_dhost, 0xff, 88 sizeof(llc->x_hdr.ether_dhost)); 89 bcopy(&node->ni_macaddr, &llc->x_hdr.ether_shost, 90 sizeof(llc->x_hdr.ether_shost)); 91 llc->x_hdr.ether_type = htons(sizeof(buf)); 92 llc->x_llc.llc_control = IAPP_LLC; 93 llc->x_llc.llc_fid = IAPP_LLC_XID; 94 llc->x_llc.llc_class = IAPP_LLC_CLASS; 95 llc->x_llc.llc_window = IAPP_LLC_WINDOW; 96 97 if (write(iapp->i_raw, &buf, sizeof(buf)) == -1) 98 return (errno); 99 return (0); 100 } 101