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