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