1 /* $OpenBSD: llc.c,v 1.7 2019/05/10 01:29:31 guenther 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/ioctl.h> 20 #include <sys/types.h> 21 #include <sys/socket.h> 22 #include <sys/time.h> 23 24 #include <net/if.h> 25 #include <net/if_media.h> 26 #include <net/if_arp.h> 27 #include <net/if_llc.h> 28 #include <net/bpf.h> 29 30 #include <netinet/in.h> 31 #include <netinet/if_ether.h> 32 #include <arpa/inet.h> 33 34 #include <fcntl.h> 35 #include <stdio.h> 36 #include <stdlib.h> 37 #include <string.h> 38 #include <unistd.h> 39 #include <limits.h> 40 41 #include "hostapd.h" 42 43 void 44 hostapd_llc_init(struct hostapd_config *cfg) 45 { 46 struct hostapd_iapp *iapp = &cfg->c_iapp; 47 struct ifreq ifr; 48 u_int i; 49 50 iapp->i_raw = hostapd_bpf_open(O_WRONLY); 51 cfg->c_flags |= HOSTAPD_CFG_F_RAW; 52 53 bzero(&ifr, sizeof(struct ifreq)); 54 (void)strlcpy(ifr.ifr_name, iapp->i_iface, sizeof(ifr.ifr_name)); 55 56 /* Associate the wired network interface to the BPF descriptor */ 57 if (ioctl(iapp->i_raw, BIOCSETIF, &ifr) == -1) 58 hostapd_fatal("failed to set BPF interface \"%s\": %s\n", 59 iapp->i_iface, strerror(errno)); 60 61 i = 1; 62 if (ioctl(iapp->i_raw, BIOCSHDRCMPLT, &i) == -1) 63 hostapd_fatal("failed to set BPF header completion: %s\n", 64 strerror(errno)); 65 66 /* Lock the BPF descriptor, no further configuration */ 67 if (ioctl(iapp->i_raw, BIOCLOCK, NULL) == -1) 68 hostapd_fatal("failed to lock BPF interface on \"%s\": %s\n", 69 iapp->i_iface, strerror(errno)); 70 } 71 72 int 73 hostapd_llc_send_xid(struct hostapd_config *cfg, struct hostapd_node *node) 74 { 75 struct hostapd_iapp *iapp = &cfg->c_iapp; 76 struct hostapd_llc *llc; 77 u_int8_t buf[ETHER_HDR_LEN + (LLC_UFRAMELEN * 2)]; 78 79 /* 80 * Send an IEEE 802.3 LLC XID frame which will possibly force 81 * our switch port on the wired network to learn the station's 82 * new MAC address. 83 */ 84 bzero(&buf, sizeof(buf)); 85 llc = (struct hostapd_llc *)&buf; 86 memset(&llc->x_hdr.ether_dhost, 0xff, 87 sizeof(llc->x_hdr.ether_dhost)); 88 bcopy(&node->ni_macaddr, &llc->x_hdr.ether_shost, 89 sizeof(llc->x_hdr.ether_shost)); 90 llc->x_hdr.ether_type = htons(sizeof(buf)); 91 llc->x_llc.llc_control = IAPP_LLC; 92 llc->x_llc.llc_fid = IAPP_LLC_XID; 93 llc->x_llc.llc_class = IAPP_LLC_CLASS; 94 llc->x_llc.llc_window = IAPP_LLC_WINDOW; 95 96 if (write(iapp->i_raw, &buf, sizeof(buf)) == -1) 97 return (errno); 98 return (0); 99 } 100