1 /* 2 * Linux ioctl helper functions for driver wrappers 3 * Copyright (c) 2002-2010, Jouni Malinen <j (at) w1.fi> 4 * 5 * This program is free software; you can redistribute it and/or modify 6 * it under the terms of the GNU General Public License version 2 as 7 * published by the Free Software Foundation. 8 * 9 * Alternatively, this software may be distributed under the terms of BSD 10 * license. 11 * 12 * See README and COPYING for more details. 13 */ 14 15 #include "utils/includes.h" 16 #include <sys/ioctl.h> 17 #include <net/if.h> 18 #include <net/if_arp.h> 19 20 #include "utils/common.h" 21 #include "linux_ioctl.h" 22 23 24 int linux_set_iface_flags(int sock, const char *ifname, int dev_up) 25 { 26 struct ifreq ifr; 27 28 if (sock < 0) 29 return -1; 30 31 os_memset(&ifr, 0, sizeof(ifr)); 32 os_strlcpy(ifr.ifr_name, ifname, IFNAMSIZ); 33 34 if (ioctl(sock, SIOCGIFFLAGS, &ifr) != 0) { 35 wpa_printf(MSG_ERROR, "Could not read interface %s flags: %s", 36 ifname, strerror(errno)); 37 return -1; 38 } 39 40 if (dev_up) { 41 if (ifr.ifr_flags & IFF_UP) 42 return 0; 43 ifr.ifr_flags |= IFF_UP; 44 } else { 45 if (!(ifr.ifr_flags & IFF_UP)) 46 return 0; 47 ifr.ifr_flags &= ~IFF_UP; 48 } 49 50 if (ioctl(sock, SIOCSIFFLAGS, &ifr) != 0) { 51 wpa_printf(MSG_ERROR, "Could not set interface %s flags: %s", 52 ifname, strerror(errno)); 53 return -1; 54 } 55 56 return 0; 57 } 58 59 60 int linux_get_ifhwaddr(int sock, const char *ifname, u8 *addr) 61 { 62 struct ifreq ifr; 63 64 os_memset(&ifr, 0, sizeof(ifr)); 65 os_strlcpy(ifr.ifr_name, ifname, IFNAMSIZ); 66 if (ioctl(sock, SIOCGIFHWADDR, &ifr)) { 67 wpa_printf(MSG_ERROR, "Could not get interface %s hwaddr: %s", 68 ifname, strerror(errno)); 69 return -1; 70 } 71 72 if (ifr.ifr_hwaddr.sa_family != ARPHRD_ETHER) { 73 wpa_printf(MSG_ERROR, "%s: Invalid HW-addr family 0x%04x", 74 ifname, ifr.ifr_hwaddr.sa_family); 75 return -1; 76 } 77 os_memcpy(addr, ifr.ifr_hwaddr.sa_data, ETH_ALEN); 78 79 return 0; 80 } 81 82 83 int linux_set_ifhwaddr(int sock, const char *ifname, const u8 *addr) 84 { 85 struct ifreq ifr; 86 87 os_memset(&ifr, 0, sizeof(ifr)); 88 os_strlcpy(ifr.ifr_name, ifname, IFNAMSIZ); 89 os_memcpy(ifr.ifr_hwaddr.sa_data, addr, ETH_ALEN); 90 ifr.ifr_hwaddr.sa_family = ARPHRD_ETHER; 91 92 if (ioctl(sock, SIOCSIFHWADDR, &ifr)) { 93 wpa_printf(MSG_DEBUG, "Could not set interface %s hwaddr: %s", 94 ifname, strerror(errno)); 95 return -1; 96 } 97 98 return 0; 99 } 100 101 102 #ifndef SIOCBRADDBR 103 #define SIOCBRADDBR 0x89a0 104 #endif 105 #ifndef SIOCBRDELBR 106 #define SIOCBRDELBR 0x89a1 107 #endif 108 #ifndef SIOCBRADDIF 109 #define SIOCBRADDIF 0x89a2 110 #endif 111 #ifndef SIOCBRDELIF 112 #define SIOCBRDELIF 0x89a3 113 #endif 114 115 116 int linux_br_add(int sock, const char *brname) 117 { 118 if (ioctl(sock, SIOCBRADDBR, brname) < 0) { 119 wpa_printf(MSG_DEBUG, "Could not add bridge %s: %s", 120 brname, strerror(errno)); 121 return -1; 122 } 123 124 return 0; 125 } 126 127 128 int linux_br_del(int sock, const char *brname) 129 { 130 if (ioctl(sock, SIOCBRDELBR, brname) < 0) { 131 wpa_printf(MSG_DEBUG, "Could not remove bridge %s: %s", 132 brname, strerror(errno)); 133 return -1; 134 } 135 136 return 0; 137 } 138 139 140 int linux_br_add_if(int sock, const char *brname, const char *ifname) 141 { 142 struct ifreq ifr; 143 int ifindex; 144 145 ifindex = if_nametoindex(ifname); 146 if (ifindex == 0) 147 return -1; 148 149 os_memset(&ifr, 0, sizeof(ifr)); 150 os_strlcpy(ifr.ifr_name, brname, IFNAMSIZ); 151 ifr.ifr_ifindex = ifindex; 152 if (ioctl(sock, SIOCBRADDIF, &ifr) < 0) { 153 wpa_printf(MSG_DEBUG, "Could not add interface %s into bridge " 154 "%s: %s", ifname, brname, strerror(errno)); 155 return -1; 156 } 157 158 return 0; 159 } 160 161 162 int linux_br_del_if(int sock, const char *brname, const char *ifname) 163 { 164 struct ifreq ifr; 165 int ifindex; 166 167 ifindex = if_nametoindex(ifname); 168 if (ifindex == 0) 169 return -1; 170 171 os_memset(&ifr, 0, sizeof(ifr)); 172 os_strlcpy(ifr.ifr_name, brname, IFNAMSIZ); 173 ifr.ifr_ifindex = ifindex; 174 if (ioctl(sock, SIOCBRDELIF, &ifr) < 0) { 175 wpa_printf(MSG_DEBUG, "Could not remove interface %s from " 176 "bridge %s: %s", ifname, brname, strerror(errno)); 177 return -1; 178 } 179 180 return 0; 181 } 182 183 184 int linux_br_get(char *brname, const char *ifname) 185 { 186 char path[128], brlink[128], *pos; 187 os_snprintf(path, sizeof(path), "/sys/class/net/%s/brport/bridge", 188 ifname); 189 os_memset(brlink, 0, sizeof(brlink)); 190 if (readlink(path, brlink, sizeof(brlink) - 1) < 0) 191 return -1; 192 pos = os_strrchr(brlink, '/'); 193 if (pos == NULL) 194 return -1; 195 pos++; 196 os_strlcpy(brname, pos, IFNAMSIZ); 197 return 0; 198 } 199