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 ifname, strerror(errno)); 50 return ret; 51 } 52 53 return 0; 54 } 55 56 57 int linux_iface_up(int sock, const char *ifname) 58 { 59 struct ifreq ifr; 60 int ret; 61 62 if (sock < 0) 63 return -1; 64 65 os_memset(&ifr, 0, sizeof(ifr)); 66 os_strlcpy(ifr.ifr_name, ifname, IFNAMSIZ); 67 68 if (ioctl(sock, SIOCGIFFLAGS, &ifr) != 0) { 69 ret = errno ? -errno : -999; 70 wpa_printf(MSG_ERROR, "Could not read interface %s flags: %s", 71 ifname, strerror(errno)); 72 return ret; 73 } 74 75 return !!(ifr.ifr_flags & IFF_UP); 76 } 77 78 79 int linux_get_ifhwaddr(int sock, const char *ifname, u8 *addr) 80 { 81 struct ifreq ifr; 82 83 os_memset(&ifr, 0, sizeof(ifr)); 84 os_strlcpy(ifr.ifr_name, ifname, IFNAMSIZ); 85 if (ioctl(sock, SIOCGIFHWADDR, &ifr)) { 86 wpa_printf(MSG_ERROR, "Could not get interface %s hwaddr: %s", 87 ifname, strerror(errno)); 88 return -1; 89 } 90 91 if (ifr.ifr_hwaddr.sa_family != ARPHRD_ETHER) { 92 wpa_printf(MSG_ERROR, "%s: Invalid HW-addr family 0x%04x", 93 ifname, ifr.ifr_hwaddr.sa_family); 94 return -1; 95 } 96 os_memcpy(addr, ifr.ifr_hwaddr.sa_data, ETH_ALEN); 97 98 return 0; 99 } 100 101 102 int linux_set_ifhwaddr(int sock, const char *ifname, const u8 *addr) 103 { 104 struct ifreq ifr; 105 106 os_memset(&ifr, 0, sizeof(ifr)); 107 os_strlcpy(ifr.ifr_name, ifname, IFNAMSIZ); 108 os_memcpy(ifr.ifr_hwaddr.sa_data, addr, ETH_ALEN); 109 ifr.ifr_hwaddr.sa_family = ARPHRD_ETHER; 110 111 if (ioctl(sock, SIOCSIFHWADDR, &ifr)) { 112 wpa_printf(MSG_DEBUG, "Could not set interface %s hwaddr: %s", 113 ifname, strerror(errno)); 114 return -1; 115 } 116 117 return 0; 118 } 119 120 121 #ifndef SIOCBRADDBR 122 #define SIOCBRADDBR 0x89a0 123 #endif 124 #ifndef SIOCBRDELBR 125 #define SIOCBRDELBR 0x89a1 126 #endif 127 #ifndef SIOCBRADDIF 128 #define SIOCBRADDIF 0x89a2 129 #endif 130 #ifndef SIOCBRDELIF 131 #define SIOCBRDELIF 0x89a3 132 #endif 133 134 135 int linux_br_add(int sock, const char *brname) 136 { 137 if (ioctl(sock, SIOCBRADDBR, brname) < 0) { 138 wpa_printf(MSG_DEBUG, "Could not add bridge %s: %s", 139 brname, strerror(errno)); 140 return -1; 141 } 142 143 return 0; 144 } 145 146 147 int linux_br_del(int sock, const char *brname) 148 { 149 if (ioctl(sock, SIOCBRDELBR, brname) < 0) { 150 wpa_printf(MSG_DEBUG, "Could not remove bridge %s: %s", 151 brname, strerror(errno)); 152 return -1; 153 } 154 155 return 0; 156 } 157 158 159 int linux_br_add_if(int sock, const char *brname, const char *ifname) 160 { 161 struct ifreq ifr; 162 int ifindex; 163 164 ifindex = if_nametoindex(ifname); 165 if (ifindex == 0) 166 return -1; 167 168 os_memset(&ifr, 0, sizeof(ifr)); 169 os_strlcpy(ifr.ifr_name, brname, IFNAMSIZ); 170 ifr.ifr_ifindex = ifindex; 171 if (ioctl(sock, SIOCBRADDIF, &ifr) < 0) { 172 wpa_printf(MSG_DEBUG, "Could not add interface %s into bridge " 173 "%s: %s", ifname, brname, strerror(errno)); 174 return -1; 175 } 176 177 return 0; 178 } 179 180 181 int linux_br_del_if(int sock, const char *brname, const char *ifname) 182 { 183 struct ifreq ifr; 184 int ifindex; 185 186 ifindex = if_nametoindex(ifname); 187 if (ifindex == 0) 188 return -1; 189 190 os_memset(&ifr, 0, sizeof(ifr)); 191 os_strlcpy(ifr.ifr_name, brname, IFNAMSIZ); 192 ifr.ifr_ifindex = ifindex; 193 if (ioctl(sock, SIOCBRDELIF, &ifr) < 0) { 194 wpa_printf(MSG_DEBUG, "Could not remove interface %s from " 195 "bridge %s: %s", ifname, brname, strerror(errno)); 196 return -1; 197 } 198 199 return 0; 200 } 201 202 203 int linux_br_get(char *brname, const char *ifname) 204 { 205 char path[128], brlink[128], *pos; 206 os_snprintf(path, sizeof(path), "/sys/class/net/%s/brport/bridge", 207 ifname); 208 os_memset(brlink, 0, sizeof(brlink)); 209 if (readlink(path, brlink, sizeof(brlink) - 1) < 0) 210 return -1; 211 pos = os_strrchr(brlink, '/'); 212 if (pos == NULL) 213 return -1; 214 pos++; 215 os_strlcpy(brname, pos, IFNAMSIZ); 216 return 0; 217 } 218