164e51f847ad72c95f2b6348d2e2dd7872186ed1
2 * iwinfo - Wireless Information Library - Shared utility routines
4 * Copyright (C) 2010 Jo-Philipp Wich <xm@subsignal.org>
6 * The iwinfo library is free software: you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License version 2
8 * as published by the Free Software Foundation.
10 * The iwinfo library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13 * See the GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License along
16 * with the iwinfo library. If not, see http://www.gnu.org/licenses/.
18 * The signal handling code is derived from the official madwifi tools,
19 * wlanconfig.c in particular. The encryption property handling was
20 * inspired by the hostapd madwifi driver.
23 #include "iwinfo/utils.h"
26 static int ioctl_socket
= -1;
28 static int iwinfo_ioctl_socket(void)
31 if( ioctl_socket
== -1 )
33 ioctl_socket
= socket(AF_INET
, SOCK_DGRAM
, 0);
34 fcntl(ioctl_socket
, F_SETFD
, fcntl(ioctl_socket
, F_GETFD
) | FD_CLOEXEC
);
40 int iwinfo_ioctl(int cmd
, void *ifr
)
42 int s
= iwinfo_ioctl_socket();
43 return ioctl(s
, cmd
, ifr
);
46 int iwinfo_dbm2mw(int in
)
53 for(k
= 0; k
< ip
; k
++) res
*= 10;
54 for(k
= 0; k
< fp
; k
++) res
*= LOG10_MAGIC
;
59 int iwinfo_mw2dbm(int in
)
61 double fin
= (double) in
;
79 int iwinfo_ifup(const char *ifname
)
83 strncpy(ifr
.ifr_name
, ifname
, IFNAMSIZ
);
85 if( iwinfo_ioctl(SIOCGIFFLAGS
, &ifr
) )
88 ifr
.ifr_flags
|= (IFF_UP
| IFF_RUNNING
);
90 return !iwinfo_ioctl(SIOCSIFFLAGS
, &ifr
);
93 int iwinfo_ifdown(const char *ifname
)
97 strncpy(ifr
.ifr_name
, ifname
, IFNAMSIZ
);
99 if( iwinfo_ioctl(SIOCGIFFLAGS
, &ifr
) )
102 ifr
.ifr_flags
&= ~(IFF_UP
| IFF_RUNNING
);
104 return !iwinfo_ioctl(SIOCSIFFLAGS
, &ifr
);
107 int iwinfo_ifmac(const char *ifname
)
111 strncpy(ifr
.ifr_name
, ifname
, IFNAMSIZ
);
113 if( iwinfo_ioctl(SIOCGIFHWADDR
, &ifr
) )
116 ifr
.ifr_hwaddr
.sa_data
[1]++;
117 ifr
.ifr_hwaddr
.sa_data
[2]++;
119 return !iwinfo_ioctl(SIOCSIFHWADDR
, &ifr
);
122 void iwinfo_close(void)
124 if( ioctl_socket
> -1 )
128 struct iwinfo_hardware_entry
* iwinfo_hardware(struct iwinfo_hardware_id
*id
)
130 const struct iwinfo_hardware_entry
*e
;
132 for (e
= IWINFO_HARDWARE_ENTRIES
; e
->vendor_name
; e
++)
134 if ((e
->vendor_id
!= 0xffff) && (e
->vendor_id
!= id
->vendor_id
))
137 if ((e
->device_id
!= 0xffff) && (e
->device_id
!= id
->device_id
))
140 if ((e
->subsystem_vendor_id
!= 0xffff) &&
141 (e
->subsystem_vendor_id
!= id
->subsystem_vendor_id
))
144 if ((e
->subsystem_device_id
!= 0xffff) &&
145 (e
->subsystem_device_id
!= id
->subsystem_device_id
))
148 return (struct iwinfo_hardware_entry
*)e
;
154 int iwinfo_hardware_id_from_mtd(struct iwinfo_hardware_id
*id
)
162 if (!(mtd
= fopen("/proc/mtd", "r")))
165 while (fgets(buf
, sizeof(buf
), mtd
) > 0)
167 if (fscanf(mtd
, "mtd%d: %*x %x %127s", &off
, &len
, buf
) < 3 ||
168 (strcmp(buf
, "\"boardconfig\"") && strcmp(buf
, "\"EEPROM\"") &&
169 strcmp(buf
, "\"factory\"")))
183 snprintf(buf
, sizeof(buf
), "/dev/mtdblock%d", off
);
185 if ((fd
= open(buf
, O_RDONLY
)) < 0)
188 bc
= mmap(NULL
, len
, PROT_READ
, MAP_PRIVATE
|MAP_LOCKED
, fd
, 0);
190 if ((void *)bc
!= MAP_FAILED
)
195 for (off
= len
/ 2 - 0x800; off
>= 0; off
-= 0x800)
197 /* AR531X board data magic */
198 if ((bc
[off
] == 0x3533) && (bc
[off
+ 1] == 0x3131))
200 id
->vendor_id
= bc
[off
+ 0x7d];
201 id
->device_id
= bc
[off
+ 0x7c];
202 id
->subsystem_vendor_id
= bc
[off
+ 0x84];
203 id
->subsystem_device_id
= bc
[off
+ 0x83];
207 /* AR5416 EEPROM magic */
208 else if ((bc
[off
] == 0xA55A) || (bc
[off
] == 0x5AA5))
210 id
->vendor_id
= bc
[off
+ 0x0D];
211 id
->device_id
= bc
[off
+ 0x0E];
212 id
->subsystem_vendor_id
= bc
[off
+ 0x13];
213 id
->subsystem_device_id
= bc
[off
+ 0x14];
218 else if ((bc
[off
] == 0x3352) || (bc
[off
] == 0x5233) ||
219 (bc
[off
] == 0x3350) || (bc
[off
] == 0x5033) ||
220 (bc
[off
] == 0x3050) || (bc
[off
] == 0x5030) ||
221 (bc
[off
] == 0x3052) || (bc
[off
] == 0x5230))
224 id
->vendor_id
= 0x1814;
225 id
->subsystem_vendor_id
= 0x1814;
228 if (bc
[off
] & 0xf0 == 0x30)
229 id
->device_id
= (bc
[off
] >> 8) | (bc
[off
] & 0x00ff) << 8;
231 id
->device_id
= bc
[off
];
233 /* subsystem from EEPROM_NIC_CONF0_RF_TYPE */
234 id
->subsystem_device_id
= (bc
[off
+ 0x1a] & 0x0f00) >> 8;
243 return (id
->vendor_id
&& id
->device_id
) ? 0 : -1;
246 void iwinfo_parse_rsn(struct iwinfo_crypto_entry
*c
, uint8_t *data
, uint8_t len
,
247 uint8_t defcipher
, uint8_t defauth
)
251 static unsigned char ms_oui
[3] = { 0x00, 0x50, 0xf2 };
252 static unsigned char ieee80211_oui
[3] = { 0x00, 0x0f, 0xac };
257 if (!memcmp(data
, ms_oui
, 3))
259 else if (!memcmp(data
, ieee80211_oui
, 3))
264 c
->group_ciphers
|= defcipher
;
265 c
->pair_ciphers
|= defcipher
;
266 c
->auth_suites
|= defauth
;
270 if (!memcmp(data
, ms_oui
, 3) || !memcmp(data
, ieee80211_oui
, 3))
274 case 1: c
->group_ciphers
|= IWINFO_CIPHER_WEP40
; break;
275 case 2: c
->group_ciphers
|= IWINFO_CIPHER_TKIP
; break;
276 case 4: c
->group_ciphers
|= IWINFO_CIPHER_CCMP
; break;
277 case 5: c
->group_ciphers
|= IWINFO_CIPHER_WEP104
; break;
278 case 6: /* AES-128-CMAC */ break;
279 default: /* proprietary */ break;
288 c
->pair_ciphers
|= defcipher
;
289 c
->auth_suites
|= defauth
;
293 count
= data
[0] | (data
[1] << 8);
294 if (2 + (count
* 4) > len
)
297 for (i
= 0; i
< count
; i
++)
299 if (!memcmp(data
+ 2 + (i
* 4), ms_oui
, 3) ||
300 !memcmp(data
+ 2 + (i
* 4), ieee80211_oui
, 3))
302 switch (data
[2 + (i
* 4) + 3])
304 case 1: c
->pair_ciphers
|= IWINFO_CIPHER_WEP40
; break;
305 case 2: c
->pair_ciphers
|= IWINFO_CIPHER_TKIP
; break;
306 case 4: c
->pair_ciphers
|= IWINFO_CIPHER_CCMP
; break;
307 case 5: c
->pair_ciphers
|= IWINFO_CIPHER_WEP104
; break;
308 case 6: /* AES-128-CMAC */ break;
309 default: /* proprietary */ break;
314 data
+= 2 + (count
* 4);
315 len
-= 2 + (count
* 4);
319 c
->auth_suites
|= defauth
;
323 count
= data
[0] | (data
[1] << 8);
324 if (2 + (count
* 4) > len
)
327 for (i
= 0; i
< count
; i
++)
329 if (!memcmp(data
+ 2 + (i
* 4), ms_oui
, 3) ||
330 !memcmp(data
+ 2 + (i
* 4), ieee80211_oui
, 3))
332 switch (data
[2 + (i
* 4) + 3])
334 case 1: c
->auth_suites
|= IWINFO_KMGMT_8021x
; break;
335 case 2: c
->auth_suites
|= IWINFO_KMGMT_PSK
; break;
336 case 3: /* FT/IEEE 802.1X */ break;
337 case 4: /* FT/PSK */ break;
338 case 5: /* IEEE 802.1X/SHA-256 */ break;
339 case 6: /* PSK/SHA-256 */ break;
340 default: /* proprietary */ break;
345 data
+= 2 + (count
* 4);
346 len
-= 2 + (count
* 4);