linux_ioctl.c revision 8d520ff1dc2da35cdca849e982051b86468016d8
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 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 60int 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 83int 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 116int 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 128int 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 140int 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 162int 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 184int 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