1 /* 2 * iwinfo - Wireless Information Library - Linux Wireless Extension Backend 3 * 4 * Copyright (C) 2009 Jo-Philipp Wich <xm@subsignal.org> 5 * 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. 9 * 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. 14 * 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/. 17 * 18 * Parts of this code are derived from the Linux wireless tools, iwlib.c, 19 * iwlist.c and iwconfig.c in particular. 20 */ 21 22 #include "iwinfo.h" 23 #include "iwinfo_wext.h" 24 25 static double wext_freq2float(const struct iw_freq *in) 26 { 27 int i; 28 double res = (double) in->m; 29 for(i = 0; i < in->e; i++) res *= 10; 30 return res; 31 } 32 33 static inline int wext_freq2mhz(const struct iw_freq *in) 34 { 35 if( in->e == 6 ) 36 { 37 return in->m; 38 } 39 else 40 { 41 return (int)(wext_freq2float(in) / 1000000); 42 } 43 } 44 45 static inline int wext_ioctl(const char *ifname, int cmd, struct iwreq *wrq) 46 { 47 if( !strncmp(ifname, "mon.", 4) ) 48 strncpy(wrq->ifr_name, &ifname[4], IFNAMSIZ); 49 else 50 strncpy(wrq->ifr_name, ifname, IFNAMSIZ); 51 52 return iwinfo_ioctl(cmd, wrq); 53 } 54 55 56 static int wext_probe(const char *ifname) 57 { 58 struct iwreq wrq; 59 60 if(wext_ioctl(ifname, SIOCGIWNAME, &wrq) >= 0) 61 return 1; 62 63 return 0; 64 } 65 66 static void wext_close(void) 67 { 68 /* Nop */ 69 } 70 71 static int wext_get_mode(const char *ifname, int *buf) 72 { 73 struct iwreq wrq; 74 75 if(wext_ioctl(ifname, SIOCGIWMODE, &wrq) >= 0) 76 { 77 switch(wrq.u.mode) 78 { 79 case 1: 80 *buf = IWINFO_OPMODE_ADHOC; 81 break; 82 83 case 2: 84 *buf = IWINFO_OPMODE_CLIENT; 85 break; 86 87 case 3: 88 *buf = IWINFO_OPMODE_MASTER; 89 break; 90 91 case 6: 92 *buf = IWINFO_OPMODE_MONITOR; 93 break; 94 95 default: 96 *buf = IWINFO_OPMODE_UNKNOWN; 97 break; 98 } 99 100 return 0; 101 } 102 103 return -1; 104 } 105 106 static int wext_get_ssid(const char *ifname, char *buf) 107 { 108 struct iwreq wrq; 109 110 wrq.u.essid.pointer = (caddr_t) buf; 111 wrq.u.essid.length = IW_ESSID_MAX_SIZE + 1; 112 wrq.u.essid.flags = 0; 113 114 if(wext_ioctl(ifname, SIOCGIWESSID, &wrq) >= 0) 115 return 0; 116 117 return -1; 118 } 119 120 static int wext_get_bssid(const char *ifname, char *buf) 121 { 122 struct iwreq wrq; 123 124 if(wext_ioctl(ifname, SIOCGIWAP, &wrq) >= 0) 125 { 126 sprintf(buf, "%02X:%02X:%02X:%02X:%02X:%02X", 127 (uint8_t)wrq.u.ap_addr.sa_data[0], (uint8_t)wrq.u.ap_addr.sa_data[1], 128 (uint8_t)wrq.u.ap_addr.sa_data[2], (uint8_t)wrq.u.ap_addr.sa_data[3], 129 (uint8_t)wrq.u.ap_addr.sa_data[4], (uint8_t)wrq.u.ap_addr.sa_data[5]); 130 131 return 0; 132 } 133 134 return -1; 135 } 136 137 static int wext_get_bitrate(const char *ifname, int *buf) 138 { 139 struct iwreq wrq; 140 141 if(wext_ioctl(ifname, SIOCGIWRATE, &wrq) >= 0) 142 { 143 *buf = (wrq.u.bitrate.value / 1000); 144 return 0; 145 } 146 147 return -1; 148 } 149 150 static int wext_get_channel(const char *ifname, int *buf) 151 { 152 struct iwreq wrq; 153 struct iw_range range; 154 double freq; 155 int i; 156 157 if(wext_ioctl(ifname, SIOCGIWFREQ, &wrq) >= 0) 158 { 159 if( wrq.u.freq.m >= 1000 ) 160 { 161 freq = wext_freq2float(&wrq.u.freq); 162 wrq.u.data.pointer = (caddr_t) ⦥ 163 wrq.u.data.length = sizeof(struct iw_range); 164 wrq.u.data.flags = 0; 165 166 if(wext_ioctl(ifname, SIOCGIWRANGE, &wrq) >= 0) 167 { 168 for(i = 0; i < range.num_frequency; i++) 169 { 170 if( wext_freq2float(&range.freq[i]) == freq ) 171 { 172 *buf = range.freq[i].i; 173 return 0; 174 } 175 } 176 } 177 } 178 else 179 { 180 *buf = wrq.u.freq.m; 181 return 0; 182 } 183 } 184 185 return -1; 186 } 187 188 static int wext_get_center_chan1(const char *ifname, int *buf) 189 { 190 /* Not Supported */ 191 return -1; 192 } 193 194 static int wext_get_center_chan2(const char *ifname, int *buf) 195 { 196 /* Not Supported */ 197 return -1; 198 } 199 200 static int wext_get_frequency(const char *ifname, int *buf) 201 { 202 struct iwreq wrq; 203 struct iw_range range; 204 int i, channel; 205 206 if(wext_ioctl(ifname, SIOCGIWFREQ, &wrq) >= 0) 207 { 208 /* We got a channel number instead ... */ 209 if( wrq.u.freq.m < 1000 ) 210 { 211 channel = wrq.u.freq.m; 212 wrq.u.data.pointer = (caddr_t) ⦥ 213 wrq.u.data.length = sizeof(struct iw_range); 214 wrq.u.data.flags = 0; 215 216 if(wext_ioctl(ifname, SIOCGIWRANGE, &wrq) >= 0) 217 { 218 for(i = 0; i < range.num_frequency; i++) 219 { 220 if( range.freq[i].i == channel ) 221 { 222 *buf = wext_freq2mhz(&range.freq[i]); 223 return 0; 224 } 225 } 226 } 227 } 228 else 229 { 230 *buf = wext_freq2mhz(&wrq.u.freq); 231 return 0; 232 } 233 } 234 235 return -1; 236 } 237 238 static int wext_get_txpower(const char *ifname, int *buf) 239 { 240 struct iwreq wrq; 241 242 wrq.u.txpower.flags = 0; 243 244 if(wext_ioctl(ifname, SIOCGIWTXPOW, &wrq) >= 0) 245 { 246 if(wrq.u.txpower.flags & IW_TXPOW_MWATT) 247 *buf = iwinfo_mw2dbm(wrq.u.txpower.value); 248 else 249 *buf = wrq.u.txpower.value; 250 251 return 0; 252 } 253 254 return -1; 255 } 256 257 static int wext_get_signal(const char *ifname, int *buf) 258 { 259 struct iwreq wrq; 260 struct iw_statistics stats; 261 262 wrq.u.data.pointer = (caddr_t) &stats; 263 wrq.u.data.length = sizeof(struct iw_statistics); 264 wrq.u.data.flags = 1; 265 266 if(wext_ioctl(ifname, SIOCGIWSTATS, &wrq) >= 0) 267 { 268 *buf = (stats.qual.updated & IW_QUAL_DBM) 269 ? (stats.qual.level - 0x100) : stats.qual.level; 270 271 return 0; 272 } 273 274 return -1; 275 } 276 277 static int wext_get_noise(const char *ifname, int *buf) 278 { 279 struct iwreq wrq; 280 struct iw_statistics stats; 281 282 wrq.u.data.pointer = (caddr_t) &stats; 283 wrq.u.data.length = sizeof(struct iw_statistics); 284 wrq.u.data.flags = 1; 285 286 if(wext_ioctl(ifname, SIOCGIWSTATS, &wrq) >= 0) 287 { 288 *buf = (stats.qual.updated & IW_QUAL_DBM) 289 ? (stats.qual.noise - 0x100) : stats.qual.noise; 290 291 return 0; 292 } 293 294 return -1; 295 } 296 297 static int wext_get_quality(const char *ifname, int *buf) 298 { 299 struct iwreq wrq; 300 struct iw_statistics stats; 301 302 wrq.u.data.pointer = (caddr_t) &stats; 303 wrq.u.data.length = sizeof(struct iw_statistics); 304 wrq.u.data.flags = 1; 305 306 if(wext_ioctl(ifname, SIOCGIWSTATS, &wrq) >= 0) 307 { 308 *buf = stats.qual.qual; 309 return 0; 310 } 311 312 return -1; 313 } 314 315 static int wext_get_quality_max(const char *ifname, int *buf) 316 { 317 struct iwreq wrq; 318 struct iw_range range; 319 320 wrq.u.data.pointer = (caddr_t) ⦥ 321 wrq.u.data.length = sizeof(struct iw_range); 322 wrq.u.data.flags = 0; 323 324 if(wext_ioctl(ifname, SIOCGIWRANGE, &wrq) >= 0) 325 { 326 *buf = range.max_qual.qual; 327 return 0; 328 } 329 330 return -1; 331 } 332 333 static int wext_get_assoclist(const char *ifname, char *buf, int *len) 334 { 335 /* Stub */ 336 return -1; 337 } 338 339 static int wext_get_txpwrlist(const char *ifname, char *buf, int *len) 340 { 341 struct iwreq wrq; 342 struct iw_range range; 343 struct iwinfo_txpwrlist_entry entry; 344 int i; 345 346 wrq.u.data.pointer = (caddr_t) ⦥ 347 wrq.u.data.length = sizeof(struct iw_range); 348 wrq.u.data.flags = 0; 349 350 if( (wext_ioctl(ifname, SIOCGIWRANGE, &wrq) >= 0) && 351 (range.num_txpower > 0) && (range.num_txpower <= IW_MAX_TXPOWER) && 352 !(range.txpower_capa & IW_TXPOW_RELATIVE) 353 ) { 354 for( i = 0; i < range.num_txpower; i++ ) 355 { 356 if( range.txpower_capa & IW_TXPOW_MWATT ) 357 { 358 entry.dbm = iwinfo_mw2dbm(range.txpower[i]); 359 entry.mw = range.txpower[i]; 360 } 361 362 /* Madwifi does neither set mW not dBm caps, also iwlist assumes 363 * dBm if mW is not set, so don't check here... */ 364 else /* if( range.txpower_capa & IW_TXPOW_DBM ) */ 365 { 366 entry.dbm = range.txpower[i]; 367 entry.mw = iwinfo_dbm2mw(range.txpower[i]); 368 } 369 370 memcpy(&buf[i*sizeof(entry)], &entry, sizeof(entry)); 371 } 372 373 *len = i * sizeof(entry); 374 return 0; 375 } 376 377 return -1; 378 } 379 380 static int wext_get_freqlist(const char *ifname, char *buf, int *len) 381 { 382 struct iwreq wrq; 383 struct iw_range range; 384 struct iwinfo_freqlist_entry entry; 385 int i, bl; 386 387 wrq.u.data.pointer = (caddr_t) ⦥ 388 wrq.u.data.length = sizeof(struct iw_range); 389 wrq.u.data.flags = 0; 390 391 if(wext_ioctl(ifname, SIOCGIWRANGE, &wrq) >= 0) 392 { 393 bl = 0; 394 395 for(i = 0; i < range.num_frequency; i++) 396 { 397 entry.mhz = wext_freq2mhz(&range.freq[i]); 398 entry.channel = range.freq[i].i; 399 entry.restricted = 0; 400 401 memcpy(&buf[bl], &entry, sizeof(struct iwinfo_freqlist_entry)); 402 bl += sizeof(struct iwinfo_freqlist_entry); 403 } 404 405 *len = bl; 406 return 0; 407 } 408 409 return -1; 410 } 411 412 static int wext_get_country(const char *ifname, char *buf) 413 { 414 sprintf(buf, "00"); 415 return 0; 416 } 417 418 static int wext_get_countrylist(const char *ifname, char *buf, int *len) 419 { 420 /* Stub */ 421 return -1; 422 } 423 424 static int wext_get_hwmodelist(const char *ifname, int *buf) 425 { 426 char chans[IWINFO_BUFSIZE] = { 0 }; 427 struct iwinfo_freqlist_entry *e = NULL; 428 int len = 0; 429 430 *buf = 0; 431 432 if( !wext_get_freqlist(ifname, chans, &len) ) 433 { 434 for( e = (struct iwinfo_freqlist_entry *)chans; e->channel; e++ ) 435 { 436 if( e->channel <= 14 ) 437 { 438 *buf |= IWINFO_80211_B; 439 *buf |= IWINFO_80211_G; 440 } 441 else 442 { 443 *buf |= IWINFO_80211_A; 444 } 445 } 446 447 return 0; 448 } 449 450 return -1; 451 } 452 453 static int wext_get_htmodelist(const char *ifname, int *buf) 454 { 455 /* Stub */ 456 return -1; 457 } 458 459 static int wext_get_encryption(const char *ifname, char *buf) 460 { 461 /* No reliable crypto info in wext */ 462 return -1; 463 } 464 465 static int wext_get_phyname(const char *ifname, char *buf) 466 { 467 /* No suitable api in wext */ 468 strcpy(buf, ifname); 469 return 0; 470 } 471 472 static int wext_get_mbssid_support(const char *ifname, int *buf) 473 { 474 /* No multi bssid support atm */ 475 return -1; 476 } 477 478 static char * wext_sysfs_ifname_file(const char *ifname, const char *path) 479 { 480 FILE *f; 481 static char buf[128]; 482 char *rv = NULL; 483 484 snprintf(buf, sizeof(buf), "/sys/class/net/%s/%s", ifname, path); 485 486 if ((f = fopen(buf, "r")) != NULL) 487 { 488 memset(buf, 0, sizeof(buf)); 489 490 if (fread(buf, 1, sizeof(buf), f)) 491 rv = buf; 492 493 fclose(f); 494 } 495 496 return rv; 497 } 498 499 static int wext_get_hardware_id(const char *ifname, char *buf) 500 { 501 char *data; 502 struct iwinfo_hardware_id *id = (struct iwinfo_hardware_id *)buf; 503 504 memset(id, 0, sizeof(struct iwinfo_hardware_id)); 505 506 data = wext_sysfs_ifname_file(ifname, "device/vendor"); 507 if (data) 508 id->vendor_id = strtoul(data, NULL, 16); 509 510 data = wext_sysfs_ifname_file(ifname, "device/device"); 511 if (data) 512 id->device_id = strtoul(data, NULL, 16); 513 514 data = wext_sysfs_ifname_file(ifname, "device/subsystem_device"); 515 if (data) 516 id->subsystem_device_id = strtoul(data, NULL, 16); 517 518 data = wext_sysfs_ifname_file(ifname, "device/subsystem_vendor"); 519 if (data) 520 id->subsystem_vendor_id = strtoul(data, NULL, 16); 521 522 return (id->vendor_id > 0 && id->device_id > 0) ? 0 : -1; 523 } 524 525 static int wext_get_hardware_name(const char *ifname, char *buf) 526 { 527 sprintf(buf, "Generic WEXT"); 528 return 0; 529 } 530 531 static int wext_get_txpower_offset(const char *ifname, int *buf) 532 { 533 /* Stub */ 534 *buf = 0; 535 return -1; 536 } 537 538 static int wext_get_frequency_offset(const char *ifname, int *buf) 539 { 540 /* Stub */ 541 *buf = 0; 542 return -1; 543 } 544 545 const struct iwinfo_ops wext_ops = { 546 .name = "wext", 547 .probe = wext_probe, 548 .channel = wext_get_channel, 549 .center_chan1 = wext_get_center_chan1, 550 .center_chan2 = wext_get_center_chan2, 551 .frequency = wext_get_frequency, 552 .frequency_offset = wext_get_frequency_offset, 553 .txpower = wext_get_txpower, 554 .txpower_offset = wext_get_txpower_offset, 555 .bitrate = wext_get_bitrate, 556 .signal = wext_get_signal, 557 .noise = wext_get_noise, 558 .quality = wext_get_quality, 559 .quality_max = wext_get_quality_max, 560 .mbssid_support = wext_get_mbssid_support, 561 .hwmodelist = wext_get_hwmodelist, 562 .htmodelist = wext_get_htmodelist, 563 .mode = wext_get_mode, 564 .ssid = wext_get_ssid, 565 .bssid = wext_get_bssid, 566 .country = wext_get_country, 567 .hardware_id = wext_get_hardware_id, 568 .hardware_name = wext_get_hardware_name, 569 .encryption = wext_get_encryption, 570 .phyname = wext_get_phyname, 571 .assoclist = wext_get_assoclist, 572 .txpwrlist = wext_get_txpwrlist, 573 .scanlist = wext_get_scanlist, 574 .freqlist = wext_get_freqlist, 575 .countrylist = wext_get_countrylist, 576 .close = wext_close 577 }; 578
This page was automatically generated by LXR 0.3.1. • OpenWrt