blob: 940b69afe3767d983e4641e56b5e1c6713ffcd92 [file] [log] [blame]
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001/*
2 * Linux ioctl helper functions for driver wrappers
3 * Copyright (c) 2002-2010, Jouni Malinen <j@w1.fi>
4 *
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005 * This software may be distributed under the terms of the BSD license.
6 * See README for more details.
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007 */
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
18int linux_set_iface_flags(int sock, const char *ifname, int dev_up)
19{
20 struct ifreq ifr;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080021 int ret;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070022
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) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080030 ret = errno ? -errno : -999;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070031 wpa_printf(MSG_ERROR, "Could not read interface %s flags: %s",
32 ifname, strerror(errno));
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080033 return ret;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070034 }
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) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080047 ret = errno ? -errno : -999;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070048 wpa_printf(MSG_ERROR, "Could not set interface %s flags: %s",
49 ifname, strerror(errno));
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080050 return ret;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070051 }
52
53 return 0;
54}
55
56
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080057int 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
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070079int 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
102int 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
135int 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
147int 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
159int 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
181int 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
203int 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}