$search
00001 /* 00002 * Linux ioctl helper functions for driver wrappers 00003 * Copyright (c) 2002-2010, Jouni Malinen <j@w1.fi> 00004 * 00005 * This program is free software; you can redistribute it and/or modify 00006 * it under the terms of the GNU General Public License version 2 as 00007 * published by the Free Software Foundation. 00008 * 00009 * Alternatively, this software may be distributed under the terms of BSD 00010 * license. 00011 * 00012 * See README and COPYING for more details. 00013 */ 00014 00015 #include "utils/includes.h" 00016 #include <sys/ioctl.h> 00017 #include <net/if.h> 00018 #include <net/if_arp.h> 00019 00020 #include "utils/common.h" 00021 #include "linux_ioctl.h" 00022 00023 00024 int linux_set_iface_flags(int sock, const char *ifname, int dev_up) 00025 { 00026 struct ifreq ifr; 00027 00028 if (sock < 0) 00029 return -1; 00030 00031 os_memset(&ifr, 0, sizeof(ifr)); 00032 os_strlcpy(ifr.ifr_name, ifname, IFNAMSIZ); 00033 00034 if (ioctl(sock, SIOCGIFFLAGS, &ifr) != 0) { 00035 wpa_printf(MSG_ERROR, "Could not read interface %s flags: %s", 00036 ifname, strerror(errno)); 00037 return -1; 00038 } 00039 00040 if (dev_up) { 00041 if (ifr.ifr_flags & IFF_UP) 00042 return 0; 00043 ifr.ifr_flags |= IFF_UP; 00044 } else { 00045 if (!(ifr.ifr_flags & IFF_UP)) 00046 return 0; 00047 ifr.ifr_flags &= ~IFF_UP; 00048 } 00049 00050 if (ioctl(sock, SIOCSIFFLAGS, &ifr) != 0) { 00051 wpa_printf(MSG_ERROR, "Could not set interface %s flags: %s", 00052 ifname, strerror(errno)); 00053 return -1; 00054 } 00055 00056 return 0; 00057 } 00058 00059 00060 int linux_get_ifhwaddr(int sock, const char *ifname, u8 *addr) 00061 { 00062 struct ifreq ifr; 00063 00064 os_memset(&ifr, 0, sizeof(ifr)); 00065 os_strlcpy(ifr.ifr_name, ifname, IFNAMSIZ); 00066 if (ioctl(sock, SIOCGIFHWADDR, &ifr)) { 00067 wpa_printf(MSG_ERROR, "Could not get interface %s hwaddr: %s", 00068 ifname, strerror(errno)); 00069 return -1; 00070 } 00071 00072 if (ifr.ifr_hwaddr.sa_family != ARPHRD_ETHER) { 00073 wpa_printf(MSG_ERROR, "%s: Invalid HW-addr family 0x%04x", 00074 ifname, ifr.ifr_hwaddr.sa_family); 00075 return -1; 00076 } 00077 os_memcpy(addr, ifr.ifr_hwaddr.sa_data, ETH_ALEN); 00078 00079 return 0; 00080 } 00081 00082 00083 int linux_set_ifhwaddr(int sock, const char *ifname, const u8 *addr) 00084 { 00085 struct ifreq ifr; 00086 00087 os_memset(&ifr, 0, sizeof(ifr)); 00088 os_strlcpy(ifr.ifr_name, ifname, IFNAMSIZ); 00089 os_memcpy(ifr.ifr_hwaddr.sa_data, addr, ETH_ALEN); 00090 ifr.ifr_hwaddr.sa_family = ARPHRD_ETHER; 00091 00092 if (ioctl(sock, SIOCSIFHWADDR, &ifr)) { 00093 wpa_printf(MSG_DEBUG, "Could not set interface %s hwaddr: %s", 00094 ifname, strerror(errno)); 00095 return -1; 00096 } 00097 00098 return 0; 00099 } 00100 00101 00102 #ifndef SIOCBRADDBR 00103 #define SIOCBRADDBR 0x89a0 00104 #endif 00105 #ifndef SIOCBRDELBR 00106 #define SIOCBRDELBR 0x89a1 00107 #endif 00108 #ifndef SIOCBRADDIF 00109 #define SIOCBRADDIF 0x89a2 00110 #endif 00111 #ifndef SIOCBRDELIF 00112 #define SIOCBRDELIF 0x89a3 00113 #endif 00114 00115 00116 int linux_br_add(int sock, const char *brname) 00117 { 00118 if (ioctl(sock, SIOCBRADDBR, brname) < 0) { 00119 wpa_printf(MSG_DEBUG, "Could not add bridge %s: %s", 00120 brname, strerror(errno)); 00121 return -1; 00122 } 00123 00124 return 0; 00125 } 00126 00127 00128 int linux_br_del(int sock, const char *brname) 00129 { 00130 if (ioctl(sock, SIOCBRDELBR, brname) < 0) { 00131 wpa_printf(MSG_DEBUG, "Could not remove bridge %s: %s", 00132 brname, strerror(errno)); 00133 return -1; 00134 } 00135 00136 return 0; 00137 } 00138 00139 00140 int linux_br_add_if(int sock, const char *brname, const char *ifname) 00141 { 00142 struct ifreq ifr; 00143 int ifindex; 00144 00145 ifindex = if_nametoindex(ifname); 00146 if (ifindex == 0) 00147 return -1; 00148 00149 os_memset(&ifr, 0, sizeof(ifr)); 00150 os_strlcpy(ifr.ifr_name, brname, IFNAMSIZ); 00151 ifr.ifr_ifindex = ifindex; 00152 if (ioctl(sock, SIOCBRADDIF, &ifr) < 0) { 00153 wpa_printf(MSG_DEBUG, "Could not add interface %s into bridge " 00154 "%s: %s", ifname, brname, strerror(errno)); 00155 return -1; 00156 } 00157 00158 return 0; 00159 } 00160 00161 00162 int linux_br_del_if(int sock, const char *brname, const char *ifname) 00163 { 00164 struct ifreq ifr; 00165 int ifindex; 00166 00167 ifindex = if_nametoindex(ifname); 00168 if (ifindex == 0) 00169 return -1; 00170 00171 os_memset(&ifr, 0, sizeof(ifr)); 00172 os_strlcpy(ifr.ifr_name, brname, IFNAMSIZ); 00173 ifr.ifr_ifindex = ifindex; 00174 if (ioctl(sock, SIOCBRDELIF, &ifr) < 0) { 00175 wpa_printf(MSG_DEBUG, "Could not remove interface %s from " 00176 "bridge %s: %s", ifname, brname, strerror(errno)); 00177 return -1; 00178 } 00179 00180 return 0; 00181 } 00182 00183 00184 int linux_br_get(char *brname, const char *ifname) 00185 { 00186 char path[128], brlink[128], *pos; 00187 os_snprintf(path, sizeof(path), "/sys/class/net/%s/brport/bridge", 00188 ifname); 00189 os_memset(brlink, 0, sizeof(brlink)); 00190 if (readlink(path, brlink, sizeof(brlink) - 1) < 0) 00191 return -1; 00192 pos = os_strrchr(brlink, '/'); 00193 if (pos == NULL) 00194 return -1; 00195 pos++; 00196 os_strlcpy(brname, pos, IFNAMSIZ); 00197 return 0; 00198 }