PageRenderTime 26ms CodeModel.GetById 22ms RepoModel.GetById 1ms app.codeStats 0ms

/package/network/utils/iwinfo/src/iwinfo_utils.c

https://gitlab.com/gl-xinshouyong/1407-mifi-customer-tmp
C | 367 lines | 265 code | 74 blank | 28 comment | 78 complexity | d9381876f877f8f30476ea9d4f605582 MD5 | raw file
  1. /*
  2. * iwinfo - Wireless Information Library - Shared utility routines
  3. *
  4. * Copyright (C) 2010 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. * 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.
  21. */
  22. #include "iwinfo/utils.h"
  23. static int ioctl_socket = -1;
  24. static int iwinfo_ioctl_socket(void)
  25. {
  26. /* Prepare socket */
  27. if (ioctl_socket == -1)
  28. {
  29. ioctl_socket = socket(AF_INET, SOCK_DGRAM, 0);
  30. fcntl(ioctl_socket, F_SETFD, fcntl(ioctl_socket, F_GETFD) | FD_CLOEXEC);
  31. }
  32. return ioctl_socket;
  33. }
  34. int iwinfo_ioctl(int cmd, void *ifr)
  35. {
  36. int s = iwinfo_ioctl_socket();
  37. return ioctl(s, cmd, ifr);
  38. }
  39. int iwinfo_dbm2mw(int in)
  40. {
  41. double res = 1.0;
  42. int ip = in / 10;
  43. int fp = in % 10;
  44. int k;
  45. for(k = 0; k < ip; k++) res *= 10;
  46. for(k = 0; k < fp; k++) res *= LOG10_MAGIC;
  47. return (int)res;
  48. }
  49. int iwinfo_mw2dbm(int in)
  50. {
  51. double fin = (double) in;
  52. int res = 0;
  53. while(fin > 10.0)
  54. {
  55. res += 10;
  56. fin /= 10.0;
  57. }
  58. while(fin > 1.000001)
  59. {
  60. res += 1;
  61. fin /= LOG10_MAGIC;
  62. }
  63. return (int)res;
  64. }
  65. int iwinfo_ifup(const char *ifname)
  66. {
  67. struct ifreq ifr;
  68. strncpy(ifr.ifr_name, ifname, IFNAMSIZ);
  69. if (iwinfo_ioctl(SIOCGIFFLAGS, &ifr))
  70. return 0;
  71. ifr.ifr_flags |= (IFF_UP | IFF_RUNNING);
  72. return !iwinfo_ioctl(SIOCSIFFLAGS, &ifr);
  73. }
  74. int iwinfo_ifdown(const char *ifname)
  75. {
  76. struct ifreq ifr;
  77. strncpy(ifr.ifr_name, ifname, IFNAMSIZ);
  78. if (iwinfo_ioctl(SIOCGIFFLAGS, &ifr))
  79. return 0;
  80. ifr.ifr_flags &= ~(IFF_UP | IFF_RUNNING);
  81. return !iwinfo_ioctl(SIOCSIFFLAGS, &ifr);
  82. }
  83. int iwinfo_ifmac(const char *ifname)
  84. {
  85. struct ifreq ifr;
  86. strncpy(ifr.ifr_name, ifname, IFNAMSIZ);
  87. if (iwinfo_ioctl(SIOCGIFHWADDR, &ifr))
  88. return 0;
  89. ifr.ifr_hwaddr.sa_data[0] |= 0x02;
  90. ifr.ifr_hwaddr.sa_data[1]++;
  91. ifr.ifr_hwaddr.sa_data[2]++;
  92. return !iwinfo_ioctl(SIOCSIFHWADDR, &ifr);
  93. }
  94. void iwinfo_close(void)
  95. {
  96. if (ioctl_socket > -1)
  97. close(ioctl_socket);
  98. ioctl_socket = -1;
  99. }
  100. struct iwinfo_hardware_entry * iwinfo_hardware(struct iwinfo_hardware_id *id)
  101. {
  102. FILE *db;
  103. char buf[256] = { 0 };
  104. static struct iwinfo_hardware_entry e;
  105. struct iwinfo_hardware_entry *rv = NULL;
  106. if (!(db = fopen(IWINFO_HARDWARE_FILE, "r")))
  107. return NULL;
  108. while (fgets(buf, sizeof(buf) - 1, db) != NULL)
  109. {
  110. memset(&e, 0, sizeof(e));
  111. if (sscanf(buf, "%hx %hx %hx %hx %hd %hd \"%63[^\"]\" \"%63[^\"]\"",
  112. &e.vendor_id, &e.device_id,
  113. &e.subsystem_vendor_id, &e.subsystem_device_id,
  114. &e.txpower_offset, &e.frequency_offset,
  115. e.vendor_name, e.device_name) < 8)
  116. continue;
  117. if ((e.vendor_id != 0xffff) && (e.vendor_id != id->vendor_id))
  118. continue;
  119. if ((e.device_id != 0xffff) && (e.device_id != id->device_id))
  120. continue;
  121. if ((e.subsystem_vendor_id != 0xffff) &&
  122. (e.subsystem_vendor_id != id->subsystem_vendor_id))
  123. continue;
  124. if ((e.subsystem_device_id != 0xffff) &&
  125. (e.subsystem_device_id != id->subsystem_device_id))
  126. continue;
  127. rv = &e;
  128. break;
  129. }
  130. fclose(db);
  131. return rv;
  132. }
  133. int iwinfo_hardware_id_from_mtd(struct iwinfo_hardware_id *id)
  134. {
  135. FILE *mtd;
  136. uint16_t *bc;
  137. int fd, len, off;
  138. char buf[128];
  139. if (!(mtd = fopen("/proc/mtd", "r")))
  140. return -1;
  141. while (fgets(buf, sizeof(buf), mtd) > 0)
  142. {
  143. if (fscanf(mtd, "mtd%d: %x %*x %127s", &off, &len, buf) < 3 ||
  144. (strcmp(buf, "\"boardconfig\"") && strcmp(buf, "\"EEPROM\"") &&
  145. strcmp(buf, "\"factory\"")))
  146. {
  147. off = -1;
  148. continue;
  149. }
  150. break;
  151. }
  152. fclose(mtd);
  153. if (off < 0)
  154. return -1;
  155. snprintf(buf, sizeof(buf), "/dev/mtdblock%d", off);
  156. if ((fd = open(buf, O_RDONLY)) < 0)
  157. return -1;
  158. bc = mmap(NULL, len, PROT_READ, MAP_PRIVATE|MAP_LOCKED, fd, 0);
  159. if ((void *)bc != MAP_FAILED)
  160. {
  161. id->vendor_id = 0;
  162. id->device_id = 0;
  163. for (off = len / 2 - 0x800; off >= 0; off -= 0x800)
  164. {
  165. /* AR531X board data magic */
  166. if ((bc[off] == 0x3533) && (bc[off + 1] == 0x3131))
  167. {
  168. id->vendor_id = bc[off + 0x7d];
  169. id->device_id = bc[off + 0x7c];
  170. id->subsystem_vendor_id = bc[off + 0x84];
  171. id->subsystem_device_id = bc[off + 0x83];
  172. break;
  173. }
  174. /* AR5416 EEPROM magic */
  175. else if ((bc[off] == 0xA55A) || (bc[off] == 0x5AA5))
  176. {
  177. id->vendor_id = bc[off + 0x0D];
  178. id->device_id = bc[off + 0x0E];
  179. id->subsystem_vendor_id = bc[off + 0x13];
  180. id->subsystem_device_id = bc[off + 0x14];
  181. break;
  182. }
  183. /* Rt3xxx SoC */
  184. else if ((bc[off] == 0x3352) || (bc[off] == 0x5233) ||
  185. (bc[off] == 0x3350) || (bc[off] == 0x5033) ||
  186. (bc[off] == 0x3050) || (bc[off] == 0x5030) ||
  187. (bc[off] == 0x3052) || (bc[off] == 0x5230))
  188. {
  189. /* vendor: RaLink */
  190. id->vendor_id = 0x1814;
  191. id->subsystem_vendor_id = 0x1814;
  192. /* device */
  193. if (bc[off] & 0xf0 == 0x30)
  194. id->device_id = (bc[off] >> 8) | (bc[off] & 0x00ff) << 8;
  195. else
  196. id->device_id = bc[off];
  197. /* subsystem from EEPROM_NIC_CONF0_RF_TYPE */
  198. id->subsystem_device_id = (bc[off + 0x1a] & 0x0f00) >> 8;
  199. }
  200. }
  201. munmap(bc, len);
  202. }
  203. close(fd);
  204. return (id->vendor_id && id->device_id) ? 0 : -1;
  205. }
  206. void iwinfo_parse_rsn(struct iwinfo_crypto_entry *c, uint8_t *data, uint8_t len,
  207. uint8_t defcipher, uint8_t defauth)
  208. {
  209. uint16_t i, count;
  210. static unsigned char ms_oui[3] = { 0x00, 0x50, 0xf2 };
  211. static unsigned char ieee80211_oui[3] = { 0x00, 0x0f, 0xac };
  212. data += 2;
  213. len -= 2;
  214. if (!memcmp(data, ms_oui, 3))
  215. c->wpa_version += 1;
  216. else if (!memcmp(data, ieee80211_oui, 3))
  217. c->wpa_version += 2;
  218. if (len < 4)
  219. {
  220. c->group_ciphers |= defcipher;
  221. c->pair_ciphers |= defcipher;
  222. c->auth_suites |= defauth;
  223. return;
  224. }
  225. if (!memcmp(data, ms_oui, 3) || !memcmp(data, ieee80211_oui, 3))
  226. {
  227. switch (data[3])
  228. {
  229. case 1: c->group_ciphers |= IWINFO_CIPHER_WEP40; break;
  230. case 2: c->group_ciphers |= IWINFO_CIPHER_TKIP; break;
  231. case 4: c->group_ciphers |= IWINFO_CIPHER_CCMP; break;
  232. case 5: c->group_ciphers |= IWINFO_CIPHER_WEP104; break;
  233. case 6: /* AES-128-CMAC */ break;
  234. default: /* proprietary */ break;
  235. }
  236. }
  237. data += 4;
  238. len -= 4;
  239. if (len < 2)
  240. {
  241. c->pair_ciphers |= defcipher;
  242. c->auth_suites |= defauth;
  243. return;
  244. }
  245. count = data[0] | (data[1] << 8);
  246. if (2 + (count * 4) > len)
  247. return;
  248. for (i = 0; i < count; i++)
  249. {
  250. if (!memcmp(data + 2 + (i * 4), ms_oui, 3) ||
  251. !memcmp(data + 2 + (i * 4), ieee80211_oui, 3))
  252. {
  253. switch (data[2 + (i * 4) + 3])
  254. {
  255. case 1: c->pair_ciphers |= IWINFO_CIPHER_WEP40; break;
  256. case 2: c->pair_ciphers |= IWINFO_CIPHER_TKIP; break;
  257. case 4: c->pair_ciphers |= IWINFO_CIPHER_CCMP; break;
  258. case 5: c->pair_ciphers |= IWINFO_CIPHER_WEP104; break;
  259. case 6: /* AES-128-CMAC */ break;
  260. default: /* proprietary */ break;
  261. }
  262. }
  263. }
  264. data += 2 + (count * 4);
  265. len -= 2 + (count * 4);
  266. if (len < 2)
  267. {
  268. c->auth_suites |= defauth;
  269. return;
  270. }
  271. count = data[0] | (data[1] << 8);
  272. if (2 + (count * 4) > len)
  273. return;
  274. for (i = 0; i < count; i++)
  275. {
  276. if (!memcmp(data + 2 + (i * 4), ms_oui, 3) ||
  277. !memcmp(data + 2 + (i * 4), ieee80211_oui, 3))
  278. {
  279. switch (data[2 + (i * 4) + 3])
  280. {
  281. case 1: c->auth_suites |= IWINFO_KMGMT_8021x; break;
  282. case 2: c->auth_suites |= IWINFO_KMGMT_PSK; break;
  283. case 3: /* FT/IEEE 802.1X */ break;
  284. case 4: /* FT/PSK */ break;
  285. case 5: /* IEEE 802.1X/SHA-256 */ break;
  286. case 6: /* PSK/SHA-256 */ break;
  287. default: /* proprietary */ break;
  288. }
  289. }
  290. }
  291. data += 2 + (count * 4);
  292. len -= 2 + (count * 4);
  293. }