iwlib.c 87 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214
  1. /*
  2. * Wireless Tools
  3. *
  4. * Jean II - HPLB 97->99 - HPL 99->07
  5. *
  6. * Common subroutines to all the wireless tools...
  7. *
  8. * This file is released under the GPL license.
  9. * Copyright (c) 1997-2007 Jean Tourrilhes <jt@hpl.hp.com>
  10. */
  11. /***************************** INCLUDES *****************************/
  12. #include "iwlib.h" /* Header */
  13. /************************ CONSTANTS & MACROS ************************/
  14. /*
  15. * Constants fof WE-9->15
  16. */
  17. #define IW15_MAX_FREQUENCIES 16
  18. #define IW15_MAX_BITRATES 8
  19. #define IW15_MAX_TXPOWER 8
  20. #define IW15_MAX_ENCODING_SIZES 8
  21. #define IW15_MAX_SPY 8
  22. #define IW15_MAX_AP 8
  23. /****************************** TYPES ******************************/
  24. /*
  25. * Struct iw_range up to WE-15
  26. */
  27. struct iw15_range
  28. {
  29. __u32 throughput;
  30. __u32 min_nwid;
  31. __u32 max_nwid;
  32. __u16 num_channels;
  33. __u8 num_frequency;
  34. struct iw_freq freq[IW15_MAX_FREQUENCIES];
  35. __s32 sensitivity;
  36. struct iw_quality max_qual;
  37. __u8 num_bitrates;
  38. __s32 bitrate[IW15_MAX_BITRATES];
  39. __s32 min_rts;
  40. __s32 max_rts;
  41. __s32 min_frag;
  42. __s32 max_frag;
  43. __s32 min_pmp;
  44. __s32 max_pmp;
  45. __s32 min_pmt;
  46. __s32 max_pmt;
  47. __u16 pmp_flags;
  48. __u16 pmt_flags;
  49. __u16 pm_capa;
  50. __u16 encoding_size[IW15_MAX_ENCODING_SIZES];
  51. __u8 num_encoding_sizes;
  52. __u8 max_encoding_tokens;
  53. __u16 txpower_capa;
  54. __u8 num_txpower;
  55. __s32 txpower[IW15_MAX_TXPOWER];
  56. __u8 we_version_compiled;
  57. __u8 we_version_source;
  58. __u16 retry_capa;
  59. __u16 retry_flags;
  60. __u16 r_time_flags;
  61. __s32 min_retry;
  62. __s32 max_retry;
  63. __s32 min_r_time;
  64. __s32 max_r_time;
  65. struct iw_quality avg_qual;
  66. };
  67. /*
  68. * Union for all the versions of iwrange.
  69. * Fortunately, I mostly only add fields at the end, and big-bang
  70. * reorganisations are few.
  71. */
  72. union iw_range_raw
  73. {
  74. struct iw15_range range15; /* WE 9->15 */
  75. struct iw_range range; /* WE 16->current */
  76. };
  77. /*
  78. * Offsets in iw_range struct
  79. */
  80. #define iwr15_off(f) ( ((char *) &(((struct iw15_range *) NULL)->f)) - \
  81. (char *) NULL)
  82. #define iwr_off(f) ( ((char *) &(((struct iw_range *) NULL)->f)) - \
  83. (char *) NULL)
  84. /**************************** VARIABLES ****************************/
  85. /* Modes as human readable strings */
  86. const char * const iw_operation_mode[] = { "Auto",
  87. "Ad-Hoc",
  88. "Managed",
  89. "Master",
  90. "Repeater",
  91. "Secondary",
  92. "Monitor",
  93. "Unknown/bug" };
  94. /* Modulations as human readable strings */
  95. const struct iw_modul_descr iw_modul_list[] = {
  96. /* Start with aggregate types, so that they display first */
  97. { IW_MODUL_11AG, "11ag",
  98. "IEEE 802.11a + 802.11g (2.4 & 5 GHz, up to 54 Mb/s)" },
  99. { IW_MODUL_11AB, "11ab",
  100. "IEEE 802.11a + 802.11b (2.4 & 5 GHz, up to 54 Mb/s)" },
  101. { IW_MODUL_11G, "11g", "IEEE 802.11g (2.4 GHz, up to 54 Mb/s)" },
  102. { IW_MODUL_11A, "11a", "IEEE 802.11a (5 GHz, up to 54 Mb/s)" },
  103. { IW_MODUL_11B, "11b", "IEEE 802.11b (2.4 GHz, up to 11 Mb/s)" },
  104. /* Proprietary aggregates */
  105. { IW_MODUL_TURBO | IW_MODUL_11A, "turboa",
  106. "Atheros turbo mode at 5 GHz (up to 108 Mb/s)" },
  107. { IW_MODUL_TURBO | IW_MODUL_11G, "turbog",
  108. "Atheros turbo mode at 2.4 GHz (up to 108 Mb/s)" },
  109. { IW_MODUL_PBCC | IW_MODUL_11B, "11+",
  110. "TI 802.11+ (2.4 GHz, up to 22 Mb/s)" },
  111. /* Individual modulations */
  112. { IW_MODUL_OFDM_G, "OFDMg",
  113. "802.11g higher rates, OFDM at 2.4 GHz (up to 54 Mb/s)" },
  114. { IW_MODUL_OFDM_A, "OFDMa", "802.11a, OFDM at 5 GHz (up to 54 Mb/s)" },
  115. { IW_MODUL_CCK, "CCK", "802.11b higher rates (2.4 GHz, up to 11 Mb/s)" },
  116. { IW_MODUL_DS, "DS", "802.11 Direct Sequence (2.4 GHz, up to 2 Mb/s)" },
  117. { IW_MODUL_FH, "FH", "802.11 Frequency Hopping (2,4 GHz, up to 2 Mb/s)" },
  118. /* Proprietary modulations */
  119. { IW_MODUL_TURBO, "turbo",
  120. "Atheros turbo mode, channel bonding (up to 108 Mb/s)" },
  121. { IW_MODUL_PBCC, "PBCC",
  122. "TI 802.11+ higher rates (2.4 GHz, up to 22 Mb/s)" },
  123. { IW_MODUL_CUSTOM, "custom",
  124. "Driver specific modulation (check driver documentation)" },
  125. };
  126. /* Disable runtime version warning in iw_get_range_info() */
  127. int iw_ignore_version = 0;
  128. /************************ SOCKET SUBROUTINES *************************/
  129. /*------------------------------------------------------------------*/
  130. /*
  131. * Open a socket.
  132. * Depending on the protocol present, open the right socket. The socket
  133. * will allow us to talk to the driver.
  134. */
  135. int
  136. iw_sockets_open(void)
  137. {
  138. static const int families[] = {
  139. AF_INET, AF_IPX, AF_AX25, AF_APPLETALK
  140. };
  141. unsigned int i;
  142. int sock;
  143. /*
  144. * Now pick any (exisiting) useful socket family for generic queries
  145. * Note : don't open all the socket, only returns when one matches,
  146. * all protocols might not be valid.
  147. * Workaround by Jim Kaba <jkaba@sarnoff.com>
  148. * Note : in 99% of the case, we will just open the inet_sock.
  149. * The remaining 1% case are not fully correct...
  150. */
  151. /* Try all families we support */
  152. for(i = 0; i < sizeof(families)/sizeof(int); ++i)
  153. {
  154. /* Try to open the socket, if success returns it */
  155. sock = socket(families[i], SOCK_DGRAM, 0);
  156. if(sock >= 0)
  157. return sock;
  158. }
  159. return -1;
  160. }
  161. /*------------------------------------------------------------------*/
  162. /*
  163. * Extract the interface name out of /proc/net/wireless or /proc/net/dev.
  164. */
  165. static inline char *
  166. iw_get_ifname(char * name, /* Where to store the name */
  167. int nsize, /* Size of name buffer */
  168. char * buf) /* Current position in buffer */
  169. {
  170. char * end;
  171. /* Skip leading spaces */
  172. while(isspace(*buf))
  173. buf++;
  174. #ifndef IW_RESTRIC_ENUM
  175. /* Get name up to the last ':'. Aliases may contain ':' in them,
  176. * but the last one should be the separator */
  177. end = strrchr(buf, ':');
  178. #else
  179. /* Get name up to ": "
  180. * Note : we compare to ": " to make sure to process aliased interfaces
  181. * properly. Doesn't work on /proc/net/dev, because it doesn't guarantee
  182. * a ' ' after the ':'*/
  183. end = strstr(buf, ": ");
  184. #endif
  185. /* Not found ??? To big ??? */
  186. if((end == NULL) || (((end - buf) + 1) > nsize))
  187. return(NULL);
  188. /* Copy */
  189. memcpy(name, buf, (end - buf));
  190. name[end - buf] = '\0';
  191. /* Return value currently unused, just make sure it's non-NULL */
  192. return(end);
  193. }
  194. /*------------------------------------------------------------------*/
  195. /*
  196. * Enumerate devices and call specified routine
  197. * The new way just use /proc/net/wireless, so get all wireless interfaces,
  198. * whether configured or not. This is the default if available.
  199. * The old way use SIOCGIFCONF, so get only configured interfaces (wireless
  200. * or not).
  201. */
  202. void
  203. iw_enum_devices(int skfd,
  204. iw_enum_handler fn,
  205. char * args[],
  206. int count)
  207. {
  208. char buff[1024];
  209. FILE * fh;
  210. struct ifconf ifc;
  211. struct ifreq *ifr;
  212. int i;
  213. #ifndef IW_RESTRIC_ENUM
  214. /* Check if /proc/net/dev is available */
  215. fh = fopen(PROC_NET_DEV, "r");
  216. #else
  217. /* Check if /proc/net/wireless is available */
  218. fh = fopen(PROC_NET_WIRELESS, "r");
  219. #endif
  220. if(fh != NULL)
  221. {
  222. /* Success : use data from /proc/net/wireless */
  223. /* Eat 2 lines of header */
  224. fgets(buff, sizeof(buff), fh);
  225. fgets(buff, sizeof(buff), fh);
  226. /* Read each device line */
  227. while(fgets(buff, sizeof(buff), fh))
  228. {
  229. char name[IFNAMSIZ + 1];
  230. char *s;
  231. /* Skip empty or almost empty lines. It seems that in some
  232. * cases fgets return a line with only a newline. */
  233. if((buff[0] == '\0') || (buff[1] == '\0'))
  234. continue;
  235. /* Extract interface name */
  236. s = iw_get_ifname(name, sizeof(name), buff);
  237. if(!s)
  238. {
  239. /* Failed to parse, complain and continue */
  240. #ifndef IW_RESTRIC_ENUM
  241. fprintf(stderr, "Cannot parse " PROC_NET_DEV "\n");
  242. #else
  243. fprintf(stderr, "Cannot parse " PROC_NET_WIRELESS "\n");
  244. #endif
  245. }
  246. else
  247. /* Got it, print info about this interface */
  248. (*fn)(skfd, name, args, count);
  249. }
  250. fclose(fh);
  251. }
  252. else
  253. {
  254. /* Get list of configured devices using "traditional" way */
  255. ifc.ifc_len = sizeof(buff);
  256. ifc.ifc_buf = buff;
  257. if(ioctl(skfd, SIOCGIFCONF, &ifc) < 0)
  258. {
  259. fprintf(stderr, "SIOCGIFCONF: %s\n", strerror(errno));
  260. return;
  261. }
  262. ifr = ifc.ifc_req;
  263. /* Print them */
  264. for(i = ifc.ifc_len / sizeof(struct ifreq); --i >= 0; ifr++)
  265. (*fn)(skfd, ifr->ifr_name, args, count);
  266. }
  267. }
  268. /*********************** WIRELESS SUBROUTINES ************************/
  269. /*------------------------------------------------------------------*/
  270. /*
  271. * Extract WE version number from /proc/net/wireless
  272. * In most cases, you really want to get version information from
  273. * the range info (range->we_version_compiled), see below...
  274. *
  275. * If we have WE-16 and later, the WE version is available at the
  276. * end of the header line of the file.
  277. * For version prior to that, we can only detect the change from
  278. * v11 to v12, so we do an approximate job. Fortunately, v12 to v15
  279. * are highly binary compatible (on the struct level).
  280. */
  281. int
  282. iw_get_kernel_we_version(void)
  283. {
  284. char buff[1024];
  285. FILE * fh;
  286. char * p;
  287. int v;
  288. /* Check if /proc/net/wireless is available */
  289. fh = fopen(PROC_NET_WIRELESS, "r");
  290. if(fh == NULL)
  291. {
  292. fprintf(stderr, "Cannot read " PROC_NET_WIRELESS "\n");
  293. return(-1);
  294. }
  295. /* Read the first line of buffer */
  296. fgets(buff, sizeof(buff), fh);
  297. if(strstr(buff, "| WE") == NULL)
  298. {
  299. /* Prior to WE16, so explicit version not present */
  300. /* Black magic */
  301. if(strstr(buff, "| Missed") == NULL)
  302. v = 11;
  303. else
  304. v = 15;
  305. fclose(fh);
  306. return(v);
  307. }
  308. /* Read the second line of buffer */
  309. fgets(buff, sizeof(buff), fh);
  310. /* Get to the last separator, to get the version */
  311. p = strrchr(buff, '|');
  312. if((p == NULL) || (sscanf(p + 1, "%d", &v) != 1))
  313. {
  314. fprintf(stderr, "Cannot parse " PROC_NET_WIRELESS "\n");
  315. fclose(fh);
  316. return(-1);
  317. }
  318. fclose(fh);
  319. return(v);
  320. }
  321. /*------------------------------------------------------------------*/
  322. /*
  323. * Print the WE versions of the interface.
  324. */
  325. static int
  326. print_iface_version_info(int skfd,
  327. char * ifname,
  328. char * args[], /* Command line args */
  329. int count) /* Args count */
  330. {
  331. struct iwreq wrq;
  332. char buffer[sizeof(iwrange) * 2]; /* Large enough */
  333. struct iw_range * range;
  334. /* Avoid "Unused parameter" warning */
  335. args = args; count = count;
  336. /* If no wireless name : no wireless extensions.
  337. * This enable us to treat the SIOCGIWRANGE failure below properly. */
  338. if(iw_get_ext(skfd, ifname, SIOCGIWNAME, &wrq) < 0)
  339. return(-1);
  340. /* Cleanup */
  341. memset(buffer, 0, sizeof(buffer));
  342. wrq.u.data.pointer = (caddr_t) buffer;
  343. wrq.u.data.length = sizeof(buffer);
  344. wrq.u.data.flags = 0;
  345. if(iw_get_ext(skfd, ifname, SIOCGIWRANGE, &wrq) < 0)
  346. {
  347. /* Interface support WE (see above), but not IWRANGE */
  348. fprintf(stderr, "%-8.16s Driver has no Wireless Extension version information.\n\n", ifname);
  349. return(0);
  350. }
  351. /* Copy stuff at the right place, ignore extra */
  352. range = (struct iw_range *) buffer;
  353. /* For new versions, we can check the version directly, for old versions
  354. * we use magic. 300 bytes is a also magic number, don't touch... */
  355. if(wrq.u.data.length >= 300)
  356. {
  357. /* Version is always at the same offset, so it's ok */
  358. printf("%-8.16s Recommend Wireless Extension v%d or later,\n",
  359. ifname, range->we_version_source);
  360. printf(" Currently compiled with Wireless Extension v%d.\n\n",
  361. range->we_version_compiled);
  362. }
  363. else
  364. {
  365. fprintf(stderr, "%-8.16s Wireless Extension version too old.\n\n",
  366. ifname);
  367. }
  368. return(0);
  369. }
  370. /*------------------------------------------------------------------*/
  371. /*
  372. * Print the WE versions of the tools.
  373. */
  374. int
  375. iw_print_version_info(const char * toolname)
  376. {
  377. int skfd; /* generic raw socket desc. */
  378. int we_kernel_version;
  379. /* Create a channel to the NET kernel. */
  380. if((skfd = iw_sockets_open()) < 0)
  381. {
  382. perror("socket");
  383. return -1;
  384. }
  385. /* Information about the tools themselves */
  386. if(toolname != NULL)
  387. printf("%-8.16s Wireless-Tools version %d\n", toolname, WT_VERSION);
  388. printf(" Compatible with Wireless Extension v11 to v%d.\n\n",
  389. WE_MAX_VERSION);
  390. /* Get version from kernel */
  391. we_kernel_version = iw_get_kernel_we_version();
  392. /* Only version >= 16 can be verified, other are guessed */
  393. if(we_kernel_version > 15)
  394. printf("Kernel Currently compiled with Wireless Extension v%d.\n\n",
  395. we_kernel_version);
  396. /* Version for each device */
  397. iw_enum_devices(skfd, &print_iface_version_info, NULL, 0);
  398. iw_sockets_close(skfd);
  399. return 0;
  400. }
  401. /*------------------------------------------------------------------*/
  402. /*
  403. * Get the range information out of the driver
  404. */
  405. int
  406. iw_get_range_info(int skfd,
  407. const char * ifname,
  408. iwrange * range)
  409. {
  410. struct iwreq wrq;
  411. char buffer[sizeof(iwrange) * 2]; /* Large enough */
  412. union iw_range_raw * range_raw;
  413. /* Cleanup */
  414. bzero(buffer, sizeof(buffer));
  415. wrq.u.data.pointer = (caddr_t) buffer;
  416. wrq.u.data.length = sizeof(buffer);
  417. wrq.u.data.flags = 0;
  418. if(iw_get_ext(skfd, ifname, SIOCGIWRANGE, &wrq) < 0)
  419. return(-1);
  420. /* Point to the buffer */
  421. range_raw = (union iw_range_raw *) buffer;
  422. /* For new versions, we can check the version directly, for old versions
  423. * we use magic. 300 bytes is a also magic number, don't touch... */
  424. if(wrq.u.data.length < 300)
  425. {
  426. /* That's v10 or earlier. Ouch ! Let's make a guess...*/
  427. range_raw->range.we_version_compiled = 9;
  428. }
  429. /* Check how it needs to be processed */
  430. if(range_raw->range.we_version_compiled > 15)
  431. {
  432. /* This is our native format, that's easy... */
  433. /* Copy stuff at the right place, ignore extra */
  434. memcpy((char *) range, buffer, sizeof(iwrange));
  435. }
  436. else
  437. {
  438. /* Zero unknown fields */
  439. bzero((char *) range, sizeof(struct iw_range));
  440. /* Initial part unmoved */
  441. memcpy((char *) range,
  442. buffer,
  443. iwr15_off(num_channels));
  444. /* Frequencies pushed futher down towards the end */
  445. memcpy((char *) range + iwr_off(num_channels),
  446. buffer + iwr15_off(num_channels),
  447. iwr15_off(sensitivity) - iwr15_off(num_channels));
  448. /* This one moved up */
  449. memcpy((char *) range + iwr_off(sensitivity),
  450. buffer + iwr15_off(sensitivity),
  451. iwr15_off(num_bitrates) - iwr15_off(sensitivity));
  452. /* This one goes after avg_qual */
  453. memcpy((char *) range + iwr_off(num_bitrates),
  454. buffer + iwr15_off(num_bitrates),
  455. iwr15_off(min_rts) - iwr15_off(num_bitrates));
  456. /* Number of bitrates has changed, put it after */
  457. memcpy((char *) range + iwr_off(min_rts),
  458. buffer + iwr15_off(min_rts),
  459. iwr15_off(txpower_capa) - iwr15_off(min_rts));
  460. /* Added encoding_login_index, put it after */
  461. memcpy((char *) range + iwr_off(txpower_capa),
  462. buffer + iwr15_off(txpower_capa),
  463. iwr15_off(txpower) - iwr15_off(txpower_capa));
  464. /* Hum... That's an unexpected glitch. Bummer. */
  465. memcpy((char *) range + iwr_off(txpower),
  466. buffer + iwr15_off(txpower),
  467. iwr15_off(avg_qual) - iwr15_off(txpower));
  468. /* Avg qual moved up next to max_qual */
  469. memcpy((char *) range + iwr_off(avg_qual),
  470. buffer + iwr15_off(avg_qual),
  471. sizeof(struct iw_quality));
  472. }
  473. /* We are now checking much less than we used to do, because we can
  474. * accomodate more WE version. But, there are still cases where things
  475. * will break... */
  476. if(!iw_ignore_version)
  477. {
  478. /* We don't like very old version (unfortunately kernel 2.2.X) */
  479. if(range->we_version_compiled <= 10)
  480. {
  481. fprintf(stderr, "Warning: Driver for device %s has been compiled with an ancient version\n", ifname);
  482. fprintf(stderr, "of Wireless Extension, while this program support version 11 and later.\n");
  483. fprintf(stderr, "Some things may be broken...\n\n");
  484. }
  485. /* We don't like future versions of WE, because we can't cope with
  486. * the unknown */
  487. if(range->we_version_compiled > WE_MAX_VERSION)
  488. {
  489. fprintf(stderr, "Warning: Driver for device %s has been compiled with version %d\n", ifname, range->we_version_compiled);
  490. fprintf(stderr, "of Wireless Extension, while this program supports up to version %d.\n", WE_MAX_VERSION);
  491. fprintf(stderr, "Some things may be broken...\n\n");
  492. }
  493. /* Driver version verification */
  494. if((range->we_version_compiled > 10) &&
  495. (range->we_version_compiled < range->we_version_source))
  496. {
  497. fprintf(stderr, "Warning: Driver for device %s recommend version %d of Wireless Extension,\n", ifname, range->we_version_source);
  498. fprintf(stderr, "but has been compiled with version %d, therefore some driver features\n", range->we_version_compiled);
  499. fprintf(stderr, "may not be available...\n\n");
  500. }
  501. /* Note : we are only trying to catch compile difference, not source.
  502. * If the driver source has not been updated to the latest, it doesn't
  503. * matter because the new fields are set to zero */
  504. }
  505. /* Don't complain twice.
  506. * In theory, the test apply to each individual driver, but usually
  507. * all drivers are compiled from the same kernel. */
  508. iw_ignore_version = 1;
  509. return(0);
  510. }
  511. /*------------------------------------------------------------------*/
  512. /*
  513. * Get information about what private ioctls are supported by the driver
  514. *
  515. * Note : there is one danger using this function. If it return 0, you
  516. * still need to free() the buffer. Beware.
  517. */
  518. int
  519. iw_get_priv_info(int skfd,
  520. const char * ifname,
  521. iwprivargs ** ppriv)
  522. {
  523. struct iwreq wrq;
  524. iwprivargs * priv = NULL; /* Not allocated yet */
  525. int maxpriv = 16; /* Minimum for compatibility WE<13 */
  526. iwprivargs * newpriv;
  527. /* Some driver may return a very large number of ioctls. Some
  528. * others a very small number. We now use a dynamic allocation
  529. * of the array to satisfy everybody. Of course, as we don't know
  530. * in advance the size of the array, we try various increasing
  531. * sizes. Jean II */
  532. do
  533. {
  534. /* (Re)allocate the buffer */
  535. newpriv = realloc(priv, maxpriv * sizeof(priv[0]));
  536. if(newpriv == NULL)
  537. {
  538. fprintf(stderr, "%s: Allocation failed\n", __FUNCTION__);
  539. break;
  540. }
  541. priv = newpriv;
  542. /* Ask the driver if it's large enough */
  543. wrq.u.data.pointer = (caddr_t) priv;
  544. wrq.u.data.length = maxpriv;
  545. wrq.u.data.flags = 0;
  546. if(iw_get_ext(skfd, ifname, SIOCGIWPRIV, &wrq) >= 0)
  547. {
  548. /* Success. Pass the buffer by pointer */
  549. *ppriv = priv;
  550. /* Return the number of ioctls */
  551. return(wrq.u.data.length);
  552. }
  553. /* Only E2BIG means the buffer was too small, abort on other errors */
  554. if(errno != E2BIG)
  555. {
  556. /* Most likely "not supported". Don't barf. */
  557. break;
  558. }
  559. /* Failed. We probably need a bigger buffer. Check if the kernel
  560. * gave us any hints. */
  561. if(wrq.u.data.length > maxpriv)
  562. maxpriv = wrq.u.data.length;
  563. else
  564. maxpriv *= 2;
  565. }
  566. while(maxpriv < 1000);
  567. /* Cleanup */
  568. if(priv)
  569. free(priv);
  570. *ppriv = NULL;
  571. return(-1);
  572. }
  573. /*------------------------------------------------------------------*/
  574. /*
  575. * Get essential wireless config from the device driver
  576. * We will call all the classical wireless ioctl on the driver through
  577. * the socket to know what is supported and to get the settings...
  578. * Note : compare to the version in iwconfig, we extract only
  579. * what's *really* needed to configure a device...
  580. */
  581. int
  582. iw_get_basic_config(int skfd,
  583. const char * ifname,
  584. wireless_config * info)
  585. {
  586. struct iwreq wrq;
  587. memset((char *) info, 0, sizeof(struct wireless_config));
  588. /* Get wireless name */
  589. if(iw_get_ext(skfd, ifname, SIOCGIWNAME, &wrq) < 0)
  590. /* If no wireless name : no wireless extensions */
  591. return(-1);
  592. else
  593. {
  594. strncpy(info->name, wrq.u.name, IFNAMSIZ);
  595. info->name[IFNAMSIZ] = '\0';
  596. }
  597. /* Get network ID */
  598. if(iw_get_ext(skfd, ifname, SIOCGIWNWID, &wrq) >= 0)
  599. {
  600. info->has_nwid = 1;
  601. memcpy(&(info->nwid), &(wrq.u.nwid), sizeof(iwparam));
  602. }
  603. /* Get frequency / channel */
  604. if(iw_get_ext(skfd, ifname, SIOCGIWFREQ, &wrq) >= 0)
  605. {
  606. info->has_freq = 1;
  607. info->freq = iw_freq2float(&(wrq.u.freq));
  608. info->freq_flags = wrq.u.freq.flags;
  609. }
  610. /* Get encryption information */
  611. wrq.u.data.pointer = (caddr_t) info->key;
  612. wrq.u.data.length = IW_ENCODING_TOKEN_MAX;
  613. wrq.u.data.flags = 0;
  614. if(iw_get_ext(skfd, ifname, SIOCGIWENCODE, &wrq) >= 0)
  615. {
  616. info->has_key = 1;
  617. info->key_size = wrq.u.data.length;
  618. info->key_flags = wrq.u.data.flags;
  619. }
  620. /* Get ESSID */
  621. wrq.u.essid.pointer = (caddr_t) info->essid;
  622. wrq.u.essid.length = IW_ESSID_MAX_SIZE + 1;
  623. wrq.u.essid.flags = 0;
  624. if(iw_get_ext(skfd, ifname, SIOCGIWESSID, &wrq) >= 0)
  625. {
  626. info->has_essid = 1;
  627. info->essid_on = wrq.u.data.flags;
  628. }
  629. /* Get operation mode */
  630. if(iw_get_ext(skfd, ifname, SIOCGIWMODE, &wrq) >= 0)
  631. {
  632. info->has_mode = 1;
  633. /* Note : event->u.mode is unsigned, no need to check <= 0 */
  634. if(wrq.u.mode < IW_NUM_OPER_MODE)
  635. info->mode = wrq.u.mode;
  636. else
  637. info->mode = IW_NUM_OPER_MODE; /* Unknown/bug */
  638. }
  639. return(0);
  640. }
  641. /*------------------------------------------------------------------*/
  642. /*
  643. * Set essential wireless config in the device driver
  644. * We will call all the classical wireless ioctl on the driver through
  645. * the socket to know what is supported and to set the settings...
  646. * We support only the restricted set as above...
  647. */
  648. int
  649. iw_set_basic_config(int skfd,
  650. const char * ifname,
  651. wireless_config * info)
  652. {
  653. struct iwreq wrq;
  654. int ret = 0;
  655. /* Get wireless name (check if interface is valid) */
  656. if(iw_get_ext(skfd, ifname, SIOCGIWNAME, &wrq) < 0)
  657. /* If no wireless name : no wireless extensions */
  658. return(-2);
  659. /* Set the current mode of operation
  660. * Mode need to be first : some settings apply only in a specific mode
  661. * (such as frequency).
  662. */
  663. if(info->has_mode)
  664. {
  665. strncpy(wrq.ifr_name, ifname, IFNAMSIZ);
  666. wrq.u.mode = info->mode;
  667. if(iw_get_ext(skfd, ifname, SIOCSIWMODE, &wrq) < 0)
  668. {
  669. fprintf(stderr, "SIOCSIWMODE: %s\n", strerror(errno));
  670. ret = -1;
  671. }
  672. }
  673. /* Set frequency / channel */
  674. if(info->has_freq)
  675. {
  676. iw_float2freq(info->freq, &(wrq.u.freq));
  677. if(iw_set_ext(skfd, ifname, SIOCSIWFREQ, &wrq) < 0)
  678. {
  679. fprintf(stderr, "SIOCSIWFREQ: %s\n", strerror(errno));
  680. ret = -1;
  681. }
  682. }
  683. /* Set encryption information */
  684. if(info->has_key)
  685. {
  686. int flags = info->key_flags;
  687. /* Check if there is a key index */
  688. if((flags & IW_ENCODE_INDEX) > 0)
  689. {
  690. /* Set the index */
  691. wrq.u.data.pointer = (caddr_t) NULL;
  692. wrq.u.data.flags = (flags & (IW_ENCODE_INDEX)) | IW_ENCODE_NOKEY;
  693. wrq.u.data.length = 0;
  694. if(iw_set_ext(skfd, ifname, SIOCSIWENCODE, &wrq) < 0)
  695. {
  696. fprintf(stderr, "SIOCSIWENCODE(%d): %s\n",
  697. errno, strerror(errno));
  698. ret = -1;
  699. }
  700. }
  701. /* Mask out index to minimise probability of reject when setting key */
  702. flags = flags & (~IW_ENCODE_INDEX);
  703. /* Set the key itself (set current key in this case) */
  704. wrq.u.data.pointer = (caddr_t) info->key;
  705. wrq.u.data.length = info->key_size;
  706. wrq.u.data.flags = flags;
  707. /* Compatibility with WE<13 */
  708. if(flags & IW_ENCODE_NOKEY)
  709. wrq.u.data.pointer = NULL;
  710. if(iw_set_ext(skfd, ifname, SIOCSIWENCODE, &wrq) < 0)
  711. {
  712. fprintf(stderr, "SIOCSIWENCODE(%d): %s\n",
  713. errno, strerror(errno));
  714. ret = -1;
  715. }
  716. }
  717. /* Set Network ID, if available (this is for non-802.11 cards) */
  718. if(info->has_nwid)
  719. {
  720. memcpy(&(wrq.u.nwid), &(info->nwid), sizeof(iwparam));
  721. wrq.u.nwid.fixed = 1; /* Hum... When in Rome... */
  722. if(iw_set_ext(skfd, ifname, SIOCSIWNWID, &wrq) < 0)
  723. {
  724. fprintf(stderr, "SIOCSIWNWID: %s\n", strerror(errno));
  725. ret = -1;
  726. }
  727. }
  728. /* Set ESSID (extended network), if available.
  729. * ESSID need to be last : most device re-perform the scanning/discovery
  730. * when this is set, and things like encryption keys are better be
  731. * defined if we want to discover the right set of APs/nodes.
  732. */
  733. if(info->has_essid)
  734. {
  735. int we_kernel_version;
  736. we_kernel_version = iw_get_kernel_we_version();
  737. wrq.u.essid.pointer = (caddr_t) info->essid;
  738. wrq.u.essid.length = strlen(info->essid);
  739. wrq.u.data.flags = info->essid_on;
  740. if(we_kernel_version < 21)
  741. wrq.u.essid.length++;
  742. if(iw_set_ext(skfd, ifname, SIOCSIWESSID, &wrq) < 0)
  743. {
  744. fprintf(stderr, "SIOCSIWESSID: %s\n", strerror(errno));
  745. ret = -1;
  746. }
  747. }
  748. return(ret);
  749. }
  750. /*********************** PROTOCOL SUBROUTINES ***********************/
  751. /*
  752. * Fun stuff with protocol identifiers (SIOCGIWNAME).
  753. * We assume that drivers are returning sensible values in there,
  754. * which is not always the case :-(
  755. */
  756. /*------------------------------------------------------------------*/
  757. /*
  758. * Compare protocol identifiers.
  759. * We don't want to know if the two protocols are the exactly same,
  760. * but if they interoperate at some level, and also if they accept the
  761. * same type of config (ESSID vs NWID, freq...).
  762. * This is supposed to work around the alphabet soup.
  763. * Return 1 if protocols are compatible, 0 otherwise
  764. */
  765. int
  766. iw_protocol_compare(const char * protocol1,
  767. const char * protocol2)
  768. {
  769. const char * dot11 = "IEEE 802.11";
  770. const char * dot11_ds = "Dbg";
  771. const char * dot11_5g = "a";
  772. /* If the strings are the same -> easy */
  773. if(!strncmp(protocol1, protocol2, IFNAMSIZ))
  774. return(1);
  775. /* Are we dealing with one of the 802.11 variant ? */
  776. if( (!strncmp(protocol1, dot11, strlen(dot11))) &&
  777. (!strncmp(protocol2, dot11, strlen(dot11))) )
  778. {
  779. const char * sub1 = protocol1 + strlen(dot11);
  780. const char * sub2 = protocol2 + strlen(dot11);
  781. unsigned int i;
  782. int isds1 = 0;
  783. int isds2 = 0;
  784. int is5g1 = 0;
  785. int is5g2 = 0;
  786. /* Check if we find the magic letters telling it's DS compatible */
  787. for(i = 0; i < strlen(dot11_ds); i++)
  788. {
  789. if(strchr(sub1, dot11_ds[i]) != NULL)
  790. isds1 = 1;
  791. if(strchr(sub2, dot11_ds[i]) != NULL)
  792. isds2 = 1;
  793. }
  794. if(isds1 && isds2)
  795. return(1);
  796. /* Check if we find the magic letters telling it's 5GHz compatible */
  797. for(i = 0; i < strlen(dot11_5g); i++)
  798. {
  799. if(strchr(sub1, dot11_5g[i]) != NULL)
  800. is5g1 = 1;
  801. if(strchr(sub2, dot11_5g[i]) != NULL)
  802. is5g2 = 1;
  803. }
  804. if(is5g1 && is5g2)
  805. return(1);
  806. }
  807. /* Not compatible */
  808. return(0);
  809. }
  810. /********************** FREQUENCY SUBROUTINES ***********************/
  811. /*
  812. * Note : the two functions below are the cause of troubles on
  813. * various embeeded platforms, as they are the reason we require
  814. * libm (math library).
  815. * In this case, please use enable BUILD_NOLIBM in the makefile
  816. *
  817. * FIXME : check negative mantissa and exponent
  818. */
  819. /*------------------------------------------------------------------*/
  820. /*
  821. * Convert a floating point the our internal representation of
  822. * frequencies.
  823. * The kernel doesn't want to hear about floating point, so we use
  824. * this custom format instead.
  825. */
  826. void
  827. iw_float2freq(double in,
  828. iwfreq * out)
  829. {
  830. #ifdef WE_NOLIBM
  831. /* Version without libm : slower */
  832. out->e = 0;
  833. while(in > 1e9)
  834. {
  835. in /= 10;
  836. out->e++;
  837. }
  838. out->m = (long) in;
  839. #else /* WE_NOLIBM */
  840. /* Version with libm : faster */
  841. out->e = (short) (floor(log10(in)));
  842. if(out->e > 8)
  843. {
  844. out->m = ((long) (floor(in / pow(10,out->e - 6)))) * 100;
  845. out->e -= 8;
  846. }
  847. else
  848. {
  849. out->m = (long) in;
  850. out->e = 0;
  851. }
  852. #endif /* WE_NOLIBM */
  853. }
  854. /*------------------------------------------------------------------*/
  855. /*
  856. * Convert our internal representation of frequencies to a floating point.
  857. */
  858. double
  859. iw_freq2float(const iwfreq * in)
  860. {
  861. #ifdef WE_NOLIBM
  862. /* Version without libm : slower */
  863. int i;
  864. double res = (double) in->m;
  865. for(i = 0; i < in->e; i++)
  866. res *= 10;
  867. return(res);
  868. #else /* WE_NOLIBM */
  869. /* Version with libm : faster */
  870. return ((double) in->m) * pow(10,in->e);
  871. #endif /* WE_NOLIBM */
  872. }
  873. /*------------------------------------------------------------------*/
  874. /*
  875. * Output a frequency with proper scaling
  876. */
  877. void
  878. iw_print_freq_value(char * buffer,
  879. int buflen,
  880. double freq)
  881. {
  882. if(freq < KILO)
  883. snprintf(buffer, buflen, "%g", freq);
  884. else
  885. {
  886. char scale;
  887. int divisor;
  888. if(freq >= GIGA)
  889. {
  890. scale = 'G';
  891. divisor = GIGA;
  892. }
  893. else
  894. {
  895. if(freq >= MEGA)
  896. {
  897. scale = 'M';
  898. divisor = MEGA;
  899. }
  900. else
  901. {
  902. scale = 'k';
  903. divisor = KILO;
  904. }
  905. }
  906. snprintf(buffer, buflen, "%g %cHz", freq / divisor, scale);
  907. }
  908. }
  909. /*------------------------------------------------------------------*/
  910. /*
  911. * Output a frequency with proper scaling
  912. */
  913. void
  914. iw_print_freq(char * buffer,
  915. int buflen,
  916. double freq,
  917. int channel,
  918. int freq_flags)
  919. {
  920. char sep = ((freq_flags & IW_FREQ_FIXED) ? '=' : ':');
  921. char vbuf[16];
  922. /* Print the frequency/channel value */
  923. iw_print_freq_value(vbuf, sizeof(vbuf), freq);
  924. /* Check if channel only */
  925. if(freq < KILO)
  926. snprintf(buffer, buflen, "Channel%c%s", sep, vbuf);
  927. else
  928. {
  929. /* Frequency. Check if we have a channel as well */
  930. if(channel >= 0)
  931. snprintf(buffer, buflen, "Frequency%c%s (Channel %d)",
  932. sep, vbuf, channel);
  933. else
  934. snprintf(buffer, buflen, "Frequency%c%s", sep, vbuf);
  935. }
  936. }
  937. /*------------------------------------------------------------------*/
  938. /*
  939. * Convert a frequency to a channel (negative -> error)
  940. */
  941. int
  942. iw_freq_to_channel(double freq,
  943. const struct iw_range * range)
  944. {
  945. double ref_freq;
  946. int k;
  947. /* Check if it's a frequency or not already a channel */
  948. if(freq < KILO)
  949. return(-1);
  950. /* We compare the frequencies as double to ignore differences
  951. * in encoding. Slower, but safer... */
  952. for(k = 0; k < range->num_frequency; k++)
  953. {
  954. ref_freq = iw_freq2float(&(range->freq[k]));
  955. if(freq == ref_freq)
  956. return(range->freq[k].i);
  957. }
  958. /* Not found */
  959. return(-2);
  960. }
  961. /*------------------------------------------------------------------*/
  962. /*
  963. * Convert a channel to a frequency (negative -> error)
  964. * Return the channel on success
  965. */
  966. int
  967. iw_channel_to_freq(int channel,
  968. double * pfreq,
  969. const struct iw_range * range)
  970. {
  971. int has_freq = 0;
  972. int k;
  973. /* Check if the driver support only channels or if it has frequencies */
  974. for(k = 0; k < range->num_frequency; k++)
  975. {
  976. if((range->freq[k].e != 0) || (range->freq[k].m > (int) KILO))
  977. has_freq = 1;
  978. }
  979. if(!has_freq)
  980. return(-1);
  981. /* Find the correct frequency in the list */
  982. for(k = 0; k < range->num_frequency; k++)
  983. {
  984. if(range->freq[k].i == channel)
  985. {
  986. *pfreq = iw_freq2float(&(range->freq[k]));
  987. return(channel);
  988. }
  989. }
  990. /* Not found */
  991. return(-2);
  992. }
  993. /*********************** BITRATE SUBROUTINES ***********************/
  994. /*------------------------------------------------------------------*/
  995. /*
  996. * Output a bitrate with proper scaling
  997. */
  998. void
  999. iw_print_bitrate(char * buffer,
  1000. int buflen,
  1001. int bitrate)
  1002. {
  1003. double rate = bitrate;
  1004. char scale;
  1005. int divisor;
  1006. if(rate >= GIGA)
  1007. {
  1008. scale = 'G';
  1009. divisor = GIGA;
  1010. }
  1011. else
  1012. {
  1013. if(rate >= MEGA)
  1014. {
  1015. scale = 'M';
  1016. divisor = MEGA;
  1017. }
  1018. else
  1019. {
  1020. scale = 'k';
  1021. divisor = KILO;
  1022. }
  1023. }
  1024. snprintf(buffer, buflen, "%g %cb/s", rate / divisor, scale);
  1025. }
  1026. /************************ POWER SUBROUTINES *************************/
  1027. /*------------------------------------------------------------------*/
  1028. /*
  1029. * Convert a value in dBm to a value in milliWatt.
  1030. */
  1031. int
  1032. iw_dbm2mwatt(int in)
  1033. {
  1034. #ifdef WE_NOLIBM
  1035. /* Version without libm : slower */
  1036. int ip = in / 10;
  1037. int fp = in % 10;
  1038. int k;
  1039. double res = 1.0;
  1040. /* Split integral and floating part to avoid accumulating rounding errors */
  1041. for(k = 0; k < ip; k++)
  1042. res *= 10;
  1043. for(k = 0; k < fp; k++)
  1044. res *= LOG10_MAGIC;
  1045. return((int) res);
  1046. #else /* WE_NOLIBM */
  1047. /* Version with libm : faster */
  1048. return((int) (floor(pow(10.0, (((double) in) / 10.0)))));
  1049. #endif /* WE_NOLIBM */
  1050. }
  1051. /*------------------------------------------------------------------*/
  1052. /*
  1053. * Convert a value in milliWatt to a value in dBm.
  1054. */
  1055. int
  1056. iw_mwatt2dbm(int in)
  1057. {
  1058. #ifdef WE_NOLIBM
  1059. /* Version without libm : slower */
  1060. double fin = (double) in;
  1061. int res = 0;
  1062. /* Split integral and floating part to avoid accumulating rounding errors */
  1063. while(fin > 10.0)
  1064. {
  1065. res += 10;
  1066. fin /= 10.0;
  1067. }
  1068. while(fin > 1.000001) /* Eliminate rounding errors, take ceil */
  1069. {
  1070. res += 1;
  1071. fin /= LOG10_MAGIC;
  1072. }
  1073. return(res);
  1074. #else /* WE_NOLIBM */
  1075. /* Version with libm : faster */
  1076. return((int) (ceil(10.0 * log10((double) in))));
  1077. #endif /* WE_NOLIBM */
  1078. }
  1079. /*------------------------------------------------------------------*/
  1080. /*
  1081. * Output a txpower with proper conversion
  1082. */
  1083. void
  1084. iw_print_txpower(char * buffer,
  1085. int buflen,
  1086. struct iw_param * txpower)
  1087. {
  1088. int dbm;
  1089. /* Check if disabled */
  1090. if(txpower->disabled)
  1091. {
  1092. snprintf(buffer, buflen, "off");
  1093. }
  1094. else
  1095. {
  1096. /* Check for relative values */
  1097. if(txpower->flags & IW_TXPOW_RELATIVE)
  1098. {
  1099. snprintf(buffer, buflen, "%d", txpower->value);
  1100. }
  1101. else
  1102. {
  1103. /* Convert everything to dBm */
  1104. if(txpower->flags & IW_TXPOW_MWATT)
  1105. dbm = iw_mwatt2dbm(txpower->value);
  1106. else
  1107. dbm = txpower->value;
  1108. /* Display */
  1109. snprintf(buffer, buflen, "%d dBm", dbm);
  1110. }
  1111. }
  1112. }
  1113. /********************** STATISTICS SUBROUTINES **********************/
  1114. /*------------------------------------------------------------------*/
  1115. /*
  1116. * Read /proc/net/wireless to get the latest statistics
  1117. * Note : strtok not thread safe, not used in WE-12 and later.
  1118. */
  1119. int
  1120. iw_get_stats(int skfd,
  1121. const char * ifname,
  1122. iwstats * stats,
  1123. const iwrange * range,
  1124. int has_range)
  1125. {
  1126. /* Fortunately, we can always detect this condition properly */
  1127. if((has_range) && (range->we_version_compiled > 11))
  1128. {
  1129. struct iwreq wrq;
  1130. wrq.u.data.pointer = (caddr_t) stats;
  1131. wrq.u.data.length = sizeof(struct iw_statistics);
  1132. wrq.u.data.flags = 1; /* Clear updated flag */
  1133. strncpy(wrq.ifr_name, ifname, IFNAMSIZ);
  1134. if(iw_get_ext(skfd, ifname, SIOCGIWSTATS, &wrq) < 0)
  1135. return(-1);
  1136. /* Format has not changed since WE-12, no conversion */
  1137. return(0);
  1138. }
  1139. else
  1140. {
  1141. FILE * f = fopen(PROC_NET_WIRELESS, "r");
  1142. char buf[256];
  1143. char * bp;
  1144. int t;
  1145. if(f==NULL)
  1146. return -1;
  1147. /* Loop on all devices */
  1148. while(fgets(buf,255,f))
  1149. {
  1150. bp=buf;
  1151. while(*bp&&isspace(*bp))
  1152. bp++;
  1153. /* Is it the good device ? */
  1154. if(strncmp(bp,ifname,strlen(ifname))==0 && bp[strlen(ifname)]==':')
  1155. {
  1156. /* Skip ethX: */
  1157. bp=strchr(bp,':');
  1158. bp++;
  1159. /* -- status -- */
  1160. bp = strtok(bp, " ");
  1161. sscanf(bp, "%X", &t);
  1162. stats->status = (unsigned short) t;
  1163. /* -- link quality -- */
  1164. bp = strtok(NULL, " ");
  1165. if(strchr(bp,'.') != NULL)
  1166. stats->qual.updated |= 1;
  1167. sscanf(bp, "%d", &t);
  1168. stats->qual.qual = (unsigned char) t;
  1169. /* -- signal level -- */
  1170. bp = strtok(NULL, " ");
  1171. if(strchr(bp,'.') != NULL)
  1172. stats->qual.updated |= 2;
  1173. sscanf(bp, "%d", &t);
  1174. stats->qual.level = (unsigned char) t;
  1175. /* -- noise level -- */
  1176. bp = strtok(NULL, " ");
  1177. if(strchr(bp,'.') != NULL)
  1178. stats->qual.updated += 4;
  1179. sscanf(bp, "%d", &t);
  1180. stats->qual.noise = (unsigned char) t;
  1181. /* -- discarded packets -- */
  1182. bp = strtok(NULL, " ");
  1183. sscanf(bp, "%d", &stats->discard.nwid);
  1184. bp = strtok(NULL, " ");
  1185. sscanf(bp, "%d", &stats->discard.code);
  1186. bp = strtok(NULL, " ");
  1187. sscanf(bp, "%d", &stats->discard.misc);
  1188. fclose(f);
  1189. /* No conversion needed */
  1190. return 0;
  1191. }
  1192. }
  1193. fclose(f);
  1194. return -1;
  1195. }
  1196. }
  1197. /*------------------------------------------------------------------*/
  1198. /*
  1199. * Output the link statistics, taking care of formating
  1200. */
  1201. void
  1202. iw_print_stats(char * buffer,
  1203. int buflen,
  1204. const iwqual * qual,
  1205. const iwrange * range,
  1206. int has_range)
  1207. {
  1208. int len;
  1209. /* People are very often confused by the 8 bit arithmetic happening
  1210. * here.
  1211. * All the values here are encoded in a 8 bit integer. 8 bit integers
  1212. * are either unsigned [0 ; 255], signed [-128 ; +127] or
  1213. * negative [-255 ; 0].
  1214. * Further, on 8 bits, 0x100 == 256 == 0.
  1215. *
  1216. * Relative/percent values are always encoded unsigned, between 0 and 255.
  1217. * Absolute/dBm values are always encoded between -192 and 63.
  1218. * (Note that up to version 28 of Wireless Tools, dBm used to be
  1219. * encoded always negative, between -256 and -1).
  1220. *
  1221. * How do we separate relative from absolute values ?
  1222. * The old way is to use the range to do that. As of WE-19, we have
  1223. * an explicit IW_QUAL_DBM flag in updated...
  1224. * The range allow to specify the real min/max of the value. As the
  1225. * range struct only specify one bound of the value, we assume that
  1226. * the other bound is 0 (zero).
  1227. * For relative values, range is [0 ; range->max].
  1228. * For absolute values, range is [range->max ; 63].
  1229. *
  1230. * Let's take two example :
  1231. * 1) value is 75%. qual->value = 75 ; range->max_qual.value = 100
  1232. * 2) value is -54dBm. noise floor of the radio is -104dBm.
  1233. * qual->value = -54 = 202 ; range->max_qual.value = -104 = 152
  1234. *
  1235. * Jean II
  1236. */
  1237. /* Just do it...
  1238. * The old way to detect dBm require both the range and a non-null
  1239. * level (which confuse the test). The new way can deal with level of 0
  1240. * because it does an explicit test on the flag. */
  1241. if(has_range && ((qual->level != 0)
  1242. || (qual->updated & (IW_QUAL_DBM | IW_QUAL_RCPI))))
  1243. {
  1244. /* Deal with quality : always a relative value */
  1245. if(!(qual->updated & IW_QUAL_QUAL_INVALID))
  1246. {
  1247. len = snprintf(buffer, buflen, "Quality%c%d/%d ",
  1248. qual->updated & IW_QUAL_QUAL_UPDATED ? '=' : ':',
  1249. qual->qual, range->max_qual.qual);
  1250. buffer += len;
  1251. buflen -= len;
  1252. }
  1253. /* Check if the statistics are in RCPI (IEEE 802.11k) */
  1254. if(qual->updated & IW_QUAL_RCPI)
  1255. {
  1256. /* Deal with signal level in RCPI */
  1257. /* RCPI = int{(Power in dBm +110)*2} for 0dbm > Power > -110dBm */
  1258. if(!(qual->updated & IW_QUAL_LEVEL_INVALID))
  1259. {
  1260. double rcpilevel = (qual->level / 2.0) - 110.0;
  1261. len = snprintf(buffer, buflen, "Signal level%c%g dBm ",
  1262. qual->updated & IW_QUAL_LEVEL_UPDATED ? '=' : ':',
  1263. rcpilevel);
  1264. buffer += len;
  1265. buflen -= len;
  1266. }
  1267. /* Deal with noise level in dBm (absolute power measurement) */
  1268. if(!(qual->updated & IW_QUAL_NOISE_INVALID))
  1269. {
  1270. double rcpinoise = (qual->noise / 2.0) - 110.0;
  1271. len = snprintf(buffer, buflen, "Noise level%c%g dBm",
  1272. qual->updated & IW_QUAL_NOISE_UPDATED ? '=' : ':',
  1273. rcpinoise);
  1274. }
  1275. }
  1276. else
  1277. {
  1278. /* Check if the statistics are in dBm */
  1279. if((qual->updated & IW_QUAL_DBM)
  1280. || (qual->level > range->max_qual.level))
  1281. {
  1282. /* Deal with signal level in dBm (absolute power measurement) */
  1283. if(!(qual->updated & IW_QUAL_LEVEL_INVALID))
  1284. {
  1285. int dblevel = qual->level;
  1286. /* Implement a range for dBm [-192; 63] */
  1287. if(qual->level >= 64)
  1288. dblevel -= 0x100;
  1289. len = snprintf(buffer, buflen, "Signal level%c%d dBm ",
  1290. qual->updated & IW_QUAL_LEVEL_UPDATED ? '=' : ':',
  1291. dblevel);
  1292. buffer += len;
  1293. buflen -= len;
  1294. }
  1295. /* Deal with noise level in dBm (absolute power measurement) */
  1296. if(!(qual->updated & IW_QUAL_NOISE_INVALID))
  1297. {
  1298. int dbnoise = qual->noise;
  1299. /* Implement a range for dBm [-192; 63] */
  1300. if(qual->noise >= 64)
  1301. dbnoise -= 0x100;
  1302. len = snprintf(buffer, buflen, "Noise level%c%d dBm",
  1303. qual->updated & IW_QUAL_NOISE_UPDATED ? '=' : ':',
  1304. dbnoise);
  1305. }
  1306. }
  1307. else
  1308. {
  1309. /* Deal with signal level as relative value (0 -> max) */
  1310. if(!(qual->updated & IW_QUAL_LEVEL_INVALID))
  1311. {
  1312. len = snprintf(buffer, buflen, "Signal level%c%d/%d ",
  1313. qual->updated & IW_QUAL_LEVEL_UPDATED ? '=' : ':',
  1314. qual->level, range->max_qual.level);
  1315. buffer += len;
  1316. buflen -= len;
  1317. }
  1318. /* Deal with noise level as relative value (0 -> max) */
  1319. if(!(qual->updated & IW_QUAL_NOISE_INVALID))
  1320. {
  1321. len = snprintf(buffer, buflen, "Noise level%c%d/%d",
  1322. qual->updated & IW_QUAL_NOISE_UPDATED ? '=' : ':',
  1323. qual->noise, range->max_qual.noise);
  1324. }
  1325. }
  1326. }
  1327. }
  1328. else
  1329. {
  1330. /* We can't read the range, so we don't know... */
  1331. snprintf(buffer, buflen,
  1332. "Quality:%d Signal level:%d Noise level:%d",
  1333. qual->qual, qual->level, qual->noise);
  1334. }
  1335. }
  1336. /*********************** ENCODING SUBROUTINES ***********************/
  1337. /*------------------------------------------------------------------*/
  1338. /*
  1339. * Output the encoding key, with a nice formating
  1340. */
  1341. void
  1342. iw_print_key(char * buffer,
  1343. int buflen,
  1344. const unsigned char * key, /* Must be unsigned */
  1345. int key_size,
  1346. int key_flags)
  1347. {
  1348. int i;
  1349. /* Check buffer size -> 1 bytes => 2 digits + 1/2 separator */
  1350. if((key_size * 3) > buflen)
  1351. {
  1352. snprintf(buffer, buflen, "<too big>");
  1353. return;
  1354. }
  1355. /* Is the key present ??? */
  1356. if(key_flags & IW_ENCODE_NOKEY)
  1357. {
  1358. /* Nope : print on or dummy */
  1359. if(key_size <= 0)
  1360. strcpy(buffer, "on"); /* Size checked */
  1361. else
  1362. {
  1363. strcpy(buffer, "**"); /* Size checked */
  1364. buffer +=2;
  1365. for(i = 1; i < key_size; i++)
  1366. {
  1367. if((i & 0x1) == 0)
  1368. strcpy(buffer++, "-"); /* Size checked */
  1369. strcpy(buffer, "**"); /* Size checked */
  1370. buffer +=2;
  1371. }
  1372. }
  1373. }
  1374. else
  1375. {
  1376. /* Yes : print the key */
  1377. sprintf(buffer, "%.2X", key[0]); /* Size checked */
  1378. buffer +=2;
  1379. for(i = 1; i < key_size; i++)
  1380. {
  1381. if((i & 0x1) == 0)
  1382. strcpy(buffer++, "-"); /* Size checked */
  1383. sprintf(buffer, "%.2X", key[i]); /* Size checked */
  1384. buffer +=2;
  1385. }
  1386. }
  1387. }
  1388. /*------------------------------------------------------------------*/
  1389. /*
  1390. * Convert a passphrase into a key
  1391. * ### NOT IMPLEMENTED ###
  1392. * Return size of the key, or 0 (no key) or -1 (error)
  1393. */
  1394. static int
  1395. iw_pass_key(const char * input,
  1396. unsigned char * key)
  1397. {
  1398. input = input; key = key;
  1399. fprintf(stderr, "Error: Passphrase not implemented\n");
  1400. return(-1);
  1401. }
  1402. /*------------------------------------------------------------------*/
  1403. /*
  1404. * Parse a key from the command line.
  1405. * Return size of the key, or 0 (no key) or -1 (error)
  1406. * If the key is too long, it's simply truncated...
  1407. */
  1408. int
  1409. iw_in_key(const char * input,
  1410. unsigned char * key)
  1411. {
  1412. int keylen = 0;
  1413. /* Check the type of key */
  1414. if(!strncmp(input, "s:", 2))
  1415. {
  1416. /* First case : as an ASCII string (Lucent/Agere cards) */
  1417. keylen = strlen(input + 2); /* skip "s:" */
  1418. if(keylen > IW_ENCODING_TOKEN_MAX)
  1419. keylen = IW_ENCODING_TOKEN_MAX;
  1420. memcpy(key, input + 2, keylen);
  1421. }
  1422. else
  1423. if(!strncmp(input, "p:", 2))
  1424. {
  1425. /* Second case : as a passphrase (PrismII cards) */
  1426. return(iw_pass_key(input + 2, key)); /* skip "p:" */
  1427. }
  1428. else
  1429. {
  1430. const char * p;
  1431. int dlen; /* Digits sequence length */
  1432. unsigned char out[IW_ENCODING_TOKEN_MAX];
  1433. /* Third case : as hexadecimal digits */
  1434. p = input;
  1435. dlen = -1;
  1436. /* Loop until we run out of chars in input or overflow the output */
  1437. while(*p != '\0')
  1438. {
  1439. int temph;
  1440. int templ;
  1441. int count;
  1442. /* No more chars in this sequence */
  1443. if(dlen <= 0)
  1444. {
  1445. /* Skip separator */
  1446. if(dlen == 0)
  1447. p++;
  1448. /* Calculate num of char to next separator */
  1449. dlen = strcspn(p, "-:;.,");
  1450. }
  1451. /* Get each char separatly (and not by two) so that we don't
  1452. * get confused by 'enc' (=> '0E'+'0C') and similar */
  1453. count = sscanf(p, "%1X%1X", &temph, &templ);
  1454. if(count < 1)
  1455. return(-1); /* Error -> non-hex char */
  1456. /* Fixup odd strings such as '123' is '01'+'23' and not '12'+'03'*/
  1457. if(dlen % 2)
  1458. count = 1;
  1459. /* Put back two chars as one byte and output */
  1460. if(count == 2)
  1461. templ |= temph << 4;
  1462. else
  1463. templ = temph;
  1464. out[keylen++] = (unsigned char) (templ & 0xFF);
  1465. /* Check overflow in output */
  1466. if(keylen >= IW_ENCODING_TOKEN_MAX)
  1467. break;
  1468. /* Move on to next chars */
  1469. p += count;
  1470. dlen -= count;
  1471. }
  1472. /* We use a temporary output buffer 'out' so that if there is
  1473. * an error, we don't overwrite the original key buffer.
  1474. * Because of the way iwconfig loop on multiple key/enc arguments
  1475. * until it finds an error in here, this is necessary to avoid
  1476. * silently corrupting the encryption key... */
  1477. memcpy(key, out, keylen);
  1478. }
  1479. #ifdef DEBUG
  1480. {
  1481. char buf[IW_ENCODING_TOKEN_MAX * 3];
  1482. iw_print_key(buf, sizeof(buf), key, keylen, 0);
  1483. printf("Got key : %d [%s]\n", keylen, buf);
  1484. }
  1485. #endif
  1486. return(keylen);
  1487. }
  1488. /*------------------------------------------------------------------*/
  1489. /*
  1490. * Parse a key from the command line.
  1491. * Return size of the key, or 0 (no key) or -1 (error)
  1492. */
  1493. int
  1494. iw_in_key_full(int skfd,
  1495. const char * ifname,
  1496. const char * input,
  1497. unsigned char * key,
  1498. __u16 * flags)
  1499. {
  1500. int keylen = 0;
  1501. char * p;
  1502. if(!strncmp(input, "l:", 2))
  1503. {
  1504. struct iw_range range;
  1505. /* Extra case : as a login (user:passwd - Cisco LEAP) */
  1506. keylen = strlen(input + 2) + 1; /* skip "l:", add '\0' */
  1507. /* Most user/password is 8 char, so 18 char total, < 32 */
  1508. if(keylen > IW_ENCODING_TOKEN_MAX)
  1509. keylen = IW_ENCODING_TOKEN_MAX;
  1510. memcpy(key, input + 2, keylen);
  1511. /* Separate the two strings */
  1512. p = strchr((char *) key, ':');
  1513. if(p == NULL)
  1514. {
  1515. fprintf(stderr, "Error: Invalid login format\n");
  1516. return(-1);
  1517. }
  1518. *p = '\0';
  1519. /* Extract range info */
  1520. if(iw_get_range_info(skfd, ifname, &range) < 0)
  1521. /* Hum... Maybe we should return an error ??? */
  1522. memset(&range, 0, sizeof(range));
  1523. if(range.we_version_compiled > 15)
  1524. {
  1525. printf("flags = %X, index = %X\n",
  1526. *flags, range.encoding_login_index);
  1527. if((*flags & IW_ENCODE_INDEX) == 0)
  1528. {
  1529. /* Extract range info */
  1530. if(iw_get_range_info(skfd, ifname, &range) < 0)
  1531. memset(&range, 0, sizeof(range));
  1532. printf("flags = %X, index = %X\n", *flags, range.encoding_login_index);
  1533. /* Set the index the driver expects */
  1534. *flags |= range.encoding_login_index & IW_ENCODE_INDEX;
  1535. }
  1536. printf("flags = %X, index = %X\n", *flags, range.encoding_login_index);
  1537. }
  1538. }
  1539. else
  1540. /* Simpler routine above */
  1541. keylen = iw_in_key(input, key);
  1542. return(keylen);
  1543. }
  1544. /******************* POWER MANAGEMENT SUBROUTINES *******************/
  1545. /*------------------------------------------------------------------*/
  1546. /*
  1547. * Output a power management value with all attributes...
  1548. */
  1549. void
  1550. iw_print_pm_value(char * buffer,
  1551. int buflen,
  1552. int value,
  1553. int flags,
  1554. int we_version)
  1555. {
  1556. /* Check size */
  1557. if(buflen < 25)
  1558. {
  1559. snprintf(buffer, buflen, "<too big>");
  1560. return;
  1561. }
  1562. buflen -= 25;
  1563. /* Modifiers */
  1564. if(flags & IW_POWER_MIN)
  1565. {
  1566. strcpy(buffer, " min"); /* Size checked */
  1567. buffer += 4;
  1568. }
  1569. if(flags & IW_POWER_MAX)
  1570. {
  1571. strcpy(buffer, " max"); /* Size checked */
  1572. buffer += 4;
  1573. }
  1574. /* Type */
  1575. if(flags & IW_POWER_TIMEOUT)
  1576. {
  1577. strcpy(buffer, " timeout:"); /* Size checked */
  1578. buffer += 9;
  1579. }
  1580. else
  1581. {
  1582. if(flags & IW_POWER_SAVING)
  1583. {
  1584. strcpy(buffer, " saving:"); /* Size checked */
  1585. buffer += 8;
  1586. }
  1587. else
  1588. {
  1589. strcpy(buffer, " period:"); /* Size checked */
  1590. buffer += 8;
  1591. }
  1592. }
  1593. /* Display value without units */
  1594. if(flags & IW_POWER_RELATIVE)
  1595. {
  1596. if(we_version < 21)
  1597. value /= MEGA;
  1598. snprintf(buffer, buflen, "%d", value);
  1599. }
  1600. else
  1601. {
  1602. /* Display value with units */
  1603. if(value >= (int) MEGA)
  1604. snprintf(buffer, buflen, "%gs", ((double) value) / MEGA);
  1605. else
  1606. if(value >= (int) KILO)
  1607. snprintf(buffer, buflen, "%gms", ((double) value) / KILO);
  1608. else
  1609. snprintf(buffer, buflen, "%dus", value);
  1610. }
  1611. }
  1612. /*------------------------------------------------------------------*/
  1613. /*
  1614. * Output a power management mode
  1615. */
  1616. void
  1617. iw_print_pm_mode(char * buffer,
  1618. int buflen,
  1619. int flags)
  1620. {
  1621. /* Check size */
  1622. if(buflen < 28)
  1623. {
  1624. snprintf(buffer, buflen, "<too big>");
  1625. return;
  1626. }
  1627. /* Print the proper mode... */
  1628. switch(flags & IW_POWER_MODE)
  1629. {
  1630. case IW_POWER_UNICAST_R:
  1631. strcpy(buffer, "mode:Unicast only received"); /* Size checked */
  1632. break;
  1633. case IW_POWER_MULTICAST_R:
  1634. strcpy(buffer, "mode:Multicast only received"); /* Size checked */
  1635. break;
  1636. case IW_POWER_ALL_R:
  1637. strcpy(buffer, "mode:All packets received"); /* Size checked */
  1638. break;
  1639. case IW_POWER_FORCE_S:
  1640. strcpy(buffer, "mode:Force sending"); /* Size checked */
  1641. break;
  1642. case IW_POWER_REPEATER:
  1643. strcpy(buffer, "mode:Repeat multicasts"); /* Size checked */
  1644. break;
  1645. default:
  1646. strcpy(buffer, ""); /* Size checked */
  1647. break;
  1648. }
  1649. }
  1650. /***************** RETRY LIMIT/LIFETIME SUBROUTINES *****************/
  1651. /*------------------------------------------------------------------*/
  1652. /*
  1653. * Output a retry value with all attributes...
  1654. */
  1655. void
  1656. iw_print_retry_value(char * buffer,
  1657. int buflen,
  1658. int value,
  1659. int flags,
  1660. int we_version)
  1661. {
  1662. /* Check buffer size */
  1663. if(buflen < 20)
  1664. {
  1665. snprintf(buffer, buflen, "<too big>");
  1666. return;
  1667. }
  1668. buflen -= 20;
  1669. /* Modifiers */
  1670. if(flags & IW_RETRY_MIN)
  1671. {
  1672. strcpy(buffer, " min"); /* Size checked */
  1673. buffer += 4;
  1674. }
  1675. if(flags & IW_RETRY_MAX)
  1676. {
  1677. strcpy(buffer, " max"); /* Size checked */
  1678. buffer += 4;
  1679. }
  1680. if(flags & IW_RETRY_SHORT)
  1681. {
  1682. strcpy(buffer, " short"); /* Size checked */
  1683. buffer += 6;
  1684. }
  1685. if(flags & IW_RETRY_LONG)
  1686. {
  1687. strcpy(buffer, " long"); /* Size checked */
  1688. buffer += 6;
  1689. }
  1690. /* Type lifetime of limit */
  1691. if(flags & IW_RETRY_LIFETIME)
  1692. {
  1693. strcpy(buffer, " lifetime:"); /* Size checked */
  1694. buffer += 10;
  1695. /* Display value without units */
  1696. if(flags & IW_RETRY_RELATIVE)
  1697. {
  1698. if(we_version < 21)
  1699. value /= MEGA;
  1700. snprintf(buffer, buflen, "%d", value);
  1701. }
  1702. else
  1703. {
  1704. /* Display value with units */
  1705. if(value >= (int) MEGA)
  1706. snprintf(buffer, buflen, "%gs", ((double) value) / MEGA);
  1707. else
  1708. if(value >= (int) KILO)
  1709. snprintf(buffer, buflen, "%gms", ((double) value) / KILO);
  1710. else
  1711. snprintf(buffer, buflen, "%dus", value);
  1712. }
  1713. }
  1714. else
  1715. snprintf(buffer, buflen, " limit:%d", value);
  1716. }
  1717. /************************* TIME SUBROUTINES *************************/
  1718. /*------------------------------------------------------------------*/
  1719. /*
  1720. * Print timestamps
  1721. * Inspired from irdadump...
  1722. */
  1723. void
  1724. iw_print_timeval(char * buffer,
  1725. int buflen,
  1726. const struct timeval * timev,
  1727. const struct timezone * tz)
  1728. {
  1729. int s;
  1730. s = (timev->tv_sec - tz->tz_minuteswest * 60) % 86400;
  1731. snprintf(buffer, buflen, "%02d:%02d:%02d.%06u",
  1732. s / 3600, (s % 3600) / 60,
  1733. s % 60, (u_int32_t) timev->tv_usec);
  1734. }
  1735. /*********************** ADDRESS SUBROUTINES ************************/
  1736. /*
  1737. * This section is mostly a cut & past from net-tools-1.2.0
  1738. * (Well... This has evolved over the years)
  1739. * manage address display and input...
  1740. */
  1741. /*------------------------------------------------------------------*/
  1742. /*
  1743. * Check if interface support the right MAC address type...
  1744. */
  1745. int
  1746. iw_check_mac_addr_type(int skfd,
  1747. const char * ifname)
  1748. {
  1749. struct ifreq ifr;
  1750. /* Get the type of hardware address */
  1751. strncpy(ifr.ifr_name, ifname, IFNAMSIZ);
  1752. if((ioctl(skfd, SIOCGIFHWADDR, &ifr) < 0) ||
  1753. ((ifr.ifr_hwaddr.sa_family != ARPHRD_ETHER)
  1754. && (ifr.ifr_hwaddr.sa_family != ARPHRD_IEEE80211)))
  1755. {
  1756. /* Deep trouble... */
  1757. fprintf(stderr, "Interface %s doesn't support MAC addresses\n",
  1758. ifname);
  1759. return(-1);
  1760. }
  1761. #ifdef DEBUG
  1762. {
  1763. char buf[20];
  1764. printf("Hardware : %d - %s\n", ifr.ifr_hwaddr.sa_family,
  1765. iw_saether_ntop(&ifr.ifr_hwaddr, buf));
  1766. }
  1767. #endif
  1768. return(0);
  1769. }
  1770. /*------------------------------------------------------------------*/
  1771. /*
  1772. * Check if interface support the right interface address type...
  1773. */
  1774. int
  1775. iw_check_if_addr_type(int skfd,
  1776. const char * ifname)
  1777. {
  1778. struct ifreq ifr;
  1779. /* Get the type of interface address */
  1780. strncpy(ifr.ifr_name, ifname, IFNAMSIZ);
  1781. if((ioctl(skfd, SIOCGIFADDR, &ifr) < 0) ||
  1782. (ifr.ifr_addr.sa_family != AF_INET))
  1783. {
  1784. /* Deep trouble... */
  1785. fprintf(stderr, "Interface %s doesn't support IP addresses\n", ifname);
  1786. return(-1);
  1787. }
  1788. #ifdef DEBUG
  1789. printf("Interface : %d - 0x%lX\n", ifr.ifr_addr.sa_family,
  1790. *((unsigned long *) ifr.ifr_addr.sa_data));
  1791. #endif
  1792. return(0);
  1793. }
  1794. #if 0
  1795. /*------------------------------------------------------------------*/
  1796. /*
  1797. * Check if interface support the right address types...
  1798. */
  1799. int
  1800. iw_check_addr_type(int skfd,
  1801. char * ifname)
  1802. {
  1803. /* Check the interface address type */
  1804. if(iw_check_if_addr_type(skfd, ifname) < 0)
  1805. return(-1);
  1806. /* Check the interface address type */
  1807. if(iw_check_mac_addr_type(skfd, ifname) < 0)
  1808. return(-1);
  1809. return(0);
  1810. }
  1811. #endif
  1812. #if 0
  1813. /*------------------------------------------------------------------*/
  1814. /*
  1815. * Ask the kernel for the MAC address of an interface.
  1816. */
  1817. int
  1818. iw_get_mac_addr(int skfd,
  1819. const char * ifname,
  1820. struct ether_addr * eth,
  1821. unsigned short * ptype)
  1822. {
  1823. struct ifreq ifr;
  1824. int ret;
  1825. /* Prepare request */
  1826. bzero(&ifr, sizeof(struct ifreq));
  1827. strncpy(ifr.ifr_name, ifname, IFNAMSIZ);
  1828. /* Do it */
  1829. ret = ioctl(skfd, SIOCGIFHWADDR, &ifr);
  1830. memcpy(eth->ether_addr_octet, ifr.ifr_hwaddr.sa_data, 6);
  1831. *ptype = ifr.ifr_hwaddr.sa_family;
  1832. return(ret);
  1833. }
  1834. #endif
  1835. /*------------------------------------------------------------------*/
  1836. /*
  1837. * Display an arbitrary length MAC address in readable format.
  1838. */
  1839. char *
  1840. iw_mac_ntop(const unsigned char * mac,
  1841. int maclen,
  1842. char * buf,
  1843. int buflen)
  1844. {
  1845. int i;
  1846. /* Overflow check (don't forget '\0') */
  1847. if(buflen < (maclen * 3 - 1 + 1))
  1848. return(NULL);
  1849. /* First byte */
  1850. sprintf(buf, "%02X", mac[0]);
  1851. /* Other bytes */
  1852. for(i = 1; i < maclen; i++)
  1853. sprintf(buf + (i * 3) - 1, ":%02X", mac[i]);
  1854. return(buf);
  1855. }
  1856. /*------------------------------------------------------------------*/
  1857. /*
  1858. * Display an Ethernet address in readable format.
  1859. */
  1860. void
  1861. iw_ether_ntop(const struct ether_addr * eth,
  1862. char * buf)
  1863. {
  1864. sprintf(buf, "%02X:%02X:%02X:%02X:%02X:%02X",
  1865. eth->ether_addr_octet[0], eth->ether_addr_octet[1],
  1866. eth->ether_addr_octet[2], eth->ether_addr_octet[3],
  1867. eth->ether_addr_octet[4], eth->ether_addr_octet[5]);
  1868. }
  1869. /*------------------------------------------------------------------*/
  1870. /*
  1871. * Display an Wireless Access Point Socket Address in readable format.
  1872. * Note : 0x44 is an accident of history, that's what the Orinoco/PrismII
  1873. * chipset report, and the driver doesn't filter it.
  1874. */
  1875. char *
  1876. iw_sawap_ntop(const struct sockaddr * sap,
  1877. char * buf)
  1878. {
  1879. const struct ether_addr ether_zero = {{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }};
  1880. const struct ether_addr ether_bcast = {{ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }};
  1881. const struct ether_addr ether_hack = {{ 0x44, 0x44, 0x44, 0x44, 0x44, 0x44 }};
  1882. const struct ether_addr * ether_wap = (const struct ether_addr *) sap->sa_data;
  1883. if(!iw_ether_cmp(ether_wap, &ether_zero))
  1884. sprintf(buf, "Not-Associated");
  1885. else
  1886. if(!iw_ether_cmp(ether_wap, &ether_bcast))
  1887. sprintf(buf, "Invalid");
  1888. else
  1889. if(!iw_ether_cmp(ether_wap, &ether_hack))
  1890. sprintf(buf, "None");
  1891. else
  1892. iw_ether_ntop(ether_wap, buf);
  1893. return(buf);
  1894. }
  1895. /*------------------------------------------------------------------*/
  1896. /*
  1897. * Input an arbitrary length MAC address and convert to binary.
  1898. * Return address size.
  1899. */
  1900. int
  1901. iw_mac_aton(const char * orig,
  1902. unsigned char * mac,
  1903. int macmax)
  1904. {
  1905. const char * p = orig;
  1906. int maclen = 0;
  1907. /* Loop on all bytes of the string */
  1908. while(*p != '\0')
  1909. {
  1910. int temph;
  1911. int templ;
  1912. int count;
  1913. /* Extract one byte as two chars */
  1914. count = sscanf(p, "%1X%1X", &temph, &templ);
  1915. if(count != 2)
  1916. break; /* Error -> non-hex chars */
  1917. /* Output two chars as one byte */
  1918. templ |= temph << 4;
  1919. mac[maclen++] = (unsigned char) (templ & 0xFF);
  1920. /* Check end of string */
  1921. p += 2;
  1922. if(*p == '\0')
  1923. {
  1924. #ifdef DEBUG
  1925. char buf[20];
  1926. iw_ether_ntop((const struct ether_addr *) mac, buf);
  1927. fprintf(stderr, "iw_mac_aton(%s): %s\n", orig, buf);
  1928. #endif
  1929. return(maclen); /* Normal exit */
  1930. }
  1931. /* Check overflow */
  1932. if(maclen >= macmax)
  1933. {
  1934. #ifdef DEBUG
  1935. fprintf(stderr, "iw_mac_aton(%s): trailing junk!\n", orig);
  1936. #endif
  1937. errno = E2BIG;
  1938. return(0); /* Error -> overflow */
  1939. }
  1940. /* Check separator */
  1941. if(*p != ':')
  1942. break;
  1943. p++;
  1944. }
  1945. /* Error... */
  1946. #ifdef DEBUG
  1947. fprintf(stderr, "iw_mac_aton(%s): invalid ether address!\n", orig);
  1948. #endif
  1949. errno = EINVAL;
  1950. return(0);
  1951. }
  1952. /*------------------------------------------------------------------*/
  1953. /*
  1954. * Input an Ethernet address and convert to binary.
  1955. */
  1956. int
  1957. iw_ether_aton(const char *orig, struct ether_addr *eth)
  1958. {
  1959. int maclen;
  1960. maclen = iw_mac_aton(orig, (unsigned char *) eth, ETH_ALEN);
  1961. if((maclen > 0) && (maclen < ETH_ALEN))
  1962. {
  1963. errno = EINVAL;
  1964. maclen = 0;
  1965. }
  1966. return(maclen);
  1967. }
  1968. /*------------------------------------------------------------------*/
  1969. /*
  1970. * Input an Internet address and convert to binary.
  1971. */
  1972. int
  1973. iw_in_inet(char *name, struct sockaddr *sap)
  1974. {
  1975. struct hostent *hp;
  1976. struct netent *np;
  1977. struct sockaddr_in *sain = (struct sockaddr_in *) sap;
  1978. /* Grmpf. -FvK */
  1979. sain->sin_family = AF_INET;
  1980. sain->sin_port = 0;
  1981. /* Default is special, meaning 0.0.0.0. */
  1982. if (!strcmp(name, "default")) {
  1983. sain->sin_addr.s_addr = INADDR_ANY;
  1984. return(1);
  1985. }
  1986. /* Try the NETWORKS database to see if this is a known network. */
  1987. if ((np = getnetbyname(name)) != (struct netent *)NULL) {
  1988. sain->sin_addr.s_addr = htonl(np->n_net);
  1989. strcpy(name, np->n_name);
  1990. return(1);
  1991. }
  1992. /* Always use the resolver (DNS name + IP addresses) */
  1993. if ((hp = gethostbyname(name)) == (struct hostent *)NULL) {
  1994. errno = h_errno;
  1995. return(-1);
  1996. }
  1997. memcpy((char *) &sain->sin_addr, (char *) hp->h_addr_list[0], hp->h_length);
  1998. strcpy(name, hp->h_name);
  1999. return(0);
  2000. }
  2001. /*------------------------------------------------------------------*/
  2002. /*
  2003. * Input an address and convert to binary.
  2004. */
  2005. int
  2006. iw_in_addr(int skfd,
  2007. const char * ifname,
  2008. char * bufp,
  2009. struct sockaddr *sap)
  2010. {
  2011. /* Check if it is a hardware or IP address */
  2012. if(strchr(bufp, ':') == NULL)
  2013. {
  2014. struct sockaddr if_address;
  2015. struct arpreq arp_query;
  2016. /* Check if we have valid interface address type */
  2017. if(iw_check_if_addr_type(skfd, ifname) < 0)
  2018. {
  2019. fprintf(stderr, "%-8.16s Interface doesn't support IP addresses\n", ifname);
  2020. return(-1);
  2021. }
  2022. /* Read interface address */
  2023. if(iw_in_inet(bufp, &if_address) < 0)
  2024. {
  2025. fprintf(stderr, "Invalid interface address %s\n", bufp);
  2026. return(-1);
  2027. }
  2028. /* Translate IP addresses to MAC addresses */
  2029. memcpy((char *) &(arp_query.arp_pa),
  2030. (char *) &if_address,
  2031. sizeof(struct sockaddr));
  2032. arp_query.arp_ha.sa_family = 0;
  2033. arp_query.arp_flags = 0;
  2034. /* The following restrict the search to the interface only */
  2035. /* For old kernels which complain, just comment it... */
  2036. strncpy(arp_query.arp_dev, ifname, IFNAMSIZ);
  2037. if((ioctl(skfd, SIOCGARP, &arp_query) < 0) ||
  2038. !(arp_query.arp_flags & ATF_COM))
  2039. {
  2040. fprintf(stderr, "Arp failed for %s on %s... (%d)\nTry to ping the address before setting it.\n",
  2041. bufp, ifname, errno);
  2042. return(-1);
  2043. }
  2044. /* Store new MAC address */
  2045. memcpy((char *) sap,
  2046. (char *) &(arp_query.arp_ha),
  2047. sizeof(struct sockaddr));
  2048. #ifdef DEBUG
  2049. {
  2050. char buf[20];
  2051. printf("IP Address %s => Hw Address = %s\n",
  2052. bufp, iw_saether_ntop(sap, buf));
  2053. }
  2054. #endif
  2055. }
  2056. else /* If it's an hardware address */
  2057. {
  2058. /* Check if we have valid mac address type */
  2059. if(iw_check_mac_addr_type(skfd, ifname) < 0)
  2060. {
  2061. fprintf(stderr, "%-8.16s Interface doesn't support MAC addresses\n", ifname);
  2062. return(-1);
  2063. }
  2064. /* Get the hardware address */
  2065. if(iw_saether_aton(bufp, sap) == 0)
  2066. {
  2067. fprintf(stderr, "Invalid hardware address %s\n", bufp);
  2068. return(-1);
  2069. }
  2070. }
  2071. #ifdef DEBUG
  2072. {
  2073. char buf[20];
  2074. printf("Hw Address = %s\n", iw_saether_ntop(sap, buf));
  2075. }
  2076. #endif
  2077. return(0);
  2078. }
  2079. /************************* MISC SUBROUTINES **************************/
  2080. /* Size (in bytes) of various events */
  2081. static const int priv_type_size[] = {
  2082. 0, /* IW_PRIV_TYPE_NONE */
  2083. 1, /* IW_PRIV_TYPE_BYTE */
  2084. 1, /* IW_PRIV_TYPE_CHAR */
  2085. 0, /* Not defined */
  2086. sizeof(__u32), /* IW_PRIV_TYPE_INT */
  2087. sizeof(struct iw_freq), /* IW_PRIV_TYPE_FLOAT */
  2088. sizeof(struct sockaddr), /* IW_PRIV_TYPE_ADDR */
  2089. 0, /* Not defined */
  2090. };
  2091. /*------------------------------------------------------------------*/
  2092. /*
  2093. * Max size in bytes of an private argument.
  2094. */
  2095. int
  2096. iw_get_priv_size(int args)
  2097. {
  2098. int num = args & IW_PRIV_SIZE_MASK;
  2099. int type = (args & IW_PRIV_TYPE_MASK) >> 12;
  2100. return(num * priv_type_size[type]);
  2101. }
  2102. /************************ EVENT SUBROUTINES ************************/
  2103. /*
  2104. * The Wireless Extension API 14 and greater define Wireless Events,
  2105. * that are used for various events and scanning.
  2106. * Those functions help the decoding of events, so are needed only in
  2107. * this case.
  2108. */
  2109. /* -------------------------- CONSTANTS -------------------------- */
  2110. /* Type of headers we know about (basically union iwreq_data) */
  2111. #define IW_HEADER_TYPE_NULL 0 /* Not available */
  2112. #define IW_HEADER_TYPE_CHAR 2 /* char [IFNAMSIZ] */
  2113. #define IW_HEADER_TYPE_UINT 4 /* __u32 */
  2114. #define IW_HEADER_TYPE_FREQ 5 /* struct iw_freq */
  2115. #define IW_HEADER_TYPE_ADDR 6 /* struct sockaddr */
  2116. #define IW_HEADER_TYPE_POINT 8 /* struct iw_point */
  2117. #define IW_HEADER_TYPE_PARAM 9 /* struct iw_param */
  2118. #define IW_HEADER_TYPE_QUAL 10 /* struct iw_quality */
  2119. /* Handling flags */
  2120. /* Most are not implemented. I just use them as a reminder of some
  2121. * cool features we might need one day ;-) */
  2122. #define IW_DESCR_FLAG_NONE 0x0000 /* Obvious */
  2123. /* Wrapper level flags */
  2124. #define IW_DESCR_FLAG_DUMP 0x0001 /* Not part of the dump command */
  2125. #define IW_DESCR_FLAG_EVENT 0x0002 /* Generate an event on SET */
  2126. #define IW_DESCR_FLAG_RESTRICT 0x0004 /* GET : request is ROOT only */
  2127. /* SET : Omit payload from generated iwevent */
  2128. #define IW_DESCR_FLAG_NOMAX 0x0008 /* GET : no limit on request size */
  2129. /* Driver level flags */
  2130. #define IW_DESCR_FLAG_WAIT 0x0100 /* Wait for driver event */
  2131. /* ---------------------------- TYPES ---------------------------- */
  2132. /*
  2133. * Describe how a standard IOCTL looks like.
  2134. */
  2135. struct iw_ioctl_description
  2136. {
  2137. __u8 header_type; /* NULL, iw_point or other */
  2138. __u8 token_type; /* Future */
  2139. __u16 token_size; /* Granularity of payload */
  2140. __u16 min_tokens; /* Min acceptable token number */
  2141. __u16 max_tokens; /* Max acceptable token number */
  2142. __u32 flags; /* Special handling of the request */
  2143. };
  2144. /* -------------------------- VARIABLES -------------------------- */
  2145. /*
  2146. * Meta-data about all the standard Wireless Extension request we
  2147. * know about.
  2148. */
  2149. static const struct iw_ioctl_description standard_ioctl_descr[] = {
  2150. [SIOCSIWCOMMIT - SIOCIWFIRST] = {
  2151. .header_type = IW_HEADER_TYPE_NULL,
  2152. },
  2153. [SIOCGIWNAME - SIOCIWFIRST] = {
  2154. .header_type = IW_HEADER_TYPE_CHAR,
  2155. .flags = IW_DESCR_FLAG_DUMP,
  2156. },
  2157. [SIOCSIWNWID - SIOCIWFIRST] = {
  2158. .header_type = IW_HEADER_TYPE_PARAM,
  2159. .flags = IW_DESCR_FLAG_EVENT,
  2160. },
  2161. [SIOCGIWNWID - SIOCIWFIRST] = {
  2162. .header_type = IW_HEADER_TYPE_PARAM,
  2163. .flags = IW_DESCR_FLAG_DUMP,
  2164. },
  2165. [SIOCSIWFREQ - SIOCIWFIRST] = {
  2166. .header_type = IW_HEADER_TYPE_FREQ,
  2167. .flags = IW_DESCR_FLAG_EVENT,
  2168. },
  2169. [SIOCGIWFREQ - SIOCIWFIRST] = {
  2170. .header_type = IW_HEADER_TYPE_FREQ,
  2171. .flags = IW_DESCR_FLAG_DUMP,
  2172. },
  2173. [SIOCSIWMODE - SIOCIWFIRST] = {
  2174. .header_type = IW_HEADER_TYPE_UINT,
  2175. .flags = IW_DESCR_FLAG_EVENT,
  2176. },
  2177. [SIOCGIWMODE - SIOCIWFIRST] = {
  2178. .header_type = IW_HEADER_TYPE_UINT,
  2179. .flags = IW_DESCR_FLAG_DUMP,
  2180. },
  2181. [SIOCSIWSENS - SIOCIWFIRST] = {
  2182. .header_type = IW_HEADER_TYPE_PARAM,
  2183. },
  2184. [SIOCGIWSENS - SIOCIWFIRST] = {
  2185. .header_type = IW_HEADER_TYPE_PARAM,
  2186. },
  2187. [SIOCSIWRANGE - SIOCIWFIRST] = {
  2188. .header_type = IW_HEADER_TYPE_NULL,
  2189. },
  2190. [SIOCGIWRANGE - SIOCIWFIRST] = {
  2191. .header_type = IW_HEADER_TYPE_POINT,
  2192. .token_size = 1,
  2193. .max_tokens = sizeof(struct iw_range),
  2194. .flags = IW_DESCR_FLAG_DUMP,
  2195. },
  2196. [SIOCSIWPRIV - SIOCIWFIRST] = {
  2197. .header_type = IW_HEADER_TYPE_NULL,
  2198. },
  2199. [SIOCGIWPRIV - SIOCIWFIRST] = { /* (handled directly by us) */
  2200. .header_type = IW_HEADER_TYPE_NULL,
  2201. },
  2202. [SIOCSIWSTATS - SIOCIWFIRST] = {
  2203. .header_type = IW_HEADER_TYPE_NULL,
  2204. },
  2205. [SIOCGIWSTATS - SIOCIWFIRST] = { /* (handled directly by us) */
  2206. .header_type = IW_HEADER_TYPE_NULL,
  2207. .flags = IW_DESCR_FLAG_DUMP,
  2208. },
  2209. [SIOCSIWSPY - SIOCIWFIRST] = {
  2210. .header_type = IW_HEADER_TYPE_POINT,
  2211. .token_size = sizeof(struct sockaddr),
  2212. .max_tokens = IW_MAX_SPY,
  2213. },
  2214. [SIOCGIWSPY - SIOCIWFIRST] = {
  2215. .header_type = IW_HEADER_TYPE_POINT,
  2216. .token_size = sizeof(struct sockaddr) +
  2217. sizeof(struct iw_quality),
  2218. .max_tokens = IW_MAX_SPY,
  2219. },
  2220. [SIOCSIWTHRSPY - SIOCIWFIRST] = {
  2221. .header_type = IW_HEADER_TYPE_POINT,
  2222. .token_size = sizeof(struct iw_thrspy),
  2223. .min_tokens = 1,
  2224. .max_tokens = 1,
  2225. },
  2226. [SIOCGIWTHRSPY - SIOCIWFIRST] = {
  2227. .header_type = IW_HEADER_TYPE_POINT,
  2228. .token_size = sizeof(struct iw_thrspy),
  2229. .min_tokens = 1,
  2230. .max_tokens = 1,
  2231. },
  2232. [SIOCSIWAP - SIOCIWFIRST] = {
  2233. .header_type = IW_HEADER_TYPE_ADDR,
  2234. },
  2235. [SIOCGIWAP - SIOCIWFIRST] = {
  2236. .header_type = IW_HEADER_TYPE_ADDR,
  2237. .flags = IW_DESCR_FLAG_DUMP,
  2238. },
  2239. [SIOCSIWMLME - SIOCIWFIRST] = {
  2240. .header_type = IW_HEADER_TYPE_POINT,
  2241. .token_size = 1,
  2242. .min_tokens = sizeof(struct iw_mlme),
  2243. .max_tokens = sizeof(struct iw_mlme),
  2244. },
  2245. [SIOCGIWAPLIST - SIOCIWFIRST] = {
  2246. .header_type = IW_HEADER_TYPE_POINT,
  2247. .token_size = sizeof(struct sockaddr) +
  2248. sizeof(struct iw_quality),
  2249. .max_tokens = IW_MAX_AP,
  2250. .flags = IW_DESCR_FLAG_NOMAX,
  2251. },
  2252. [SIOCSIWSCAN - SIOCIWFIRST] = {
  2253. .header_type = IW_HEADER_TYPE_POINT,
  2254. .token_size = 1,
  2255. .min_tokens = 0,
  2256. .max_tokens = sizeof(struct iw_scan_req),
  2257. },
  2258. [SIOCGIWSCAN - SIOCIWFIRST] = {
  2259. .header_type = IW_HEADER_TYPE_POINT,
  2260. .token_size = 1,
  2261. .max_tokens = IW_SCAN_MAX_DATA,
  2262. .flags = IW_DESCR_FLAG_NOMAX,
  2263. },
  2264. [SIOCSIWESSID - SIOCIWFIRST] = {
  2265. .header_type = IW_HEADER_TYPE_POINT,
  2266. .token_size = 1,
  2267. .max_tokens = IW_ESSID_MAX_SIZE + 1,
  2268. .flags = IW_DESCR_FLAG_EVENT,
  2269. },
  2270. [SIOCGIWESSID - SIOCIWFIRST] = {
  2271. .header_type = IW_HEADER_TYPE_POINT,
  2272. .token_size = 1,
  2273. .max_tokens = IW_ESSID_MAX_SIZE + 1,
  2274. .flags = IW_DESCR_FLAG_DUMP,
  2275. },
  2276. [SIOCSIWNICKN - SIOCIWFIRST] = {
  2277. .header_type = IW_HEADER_TYPE_POINT,
  2278. .token_size = 1,
  2279. .max_tokens = IW_ESSID_MAX_SIZE + 1,
  2280. },
  2281. [SIOCGIWNICKN - SIOCIWFIRST] = {
  2282. .header_type = IW_HEADER_TYPE_POINT,
  2283. .token_size = 1,
  2284. .max_tokens = IW_ESSID_MAX_SIZE + 1,
  2285. },
  2286. [SIOCSIWRATE - SIOCIWFIRST] = {
  2287. .header_type = IW_HEADER_TYPE_PARAM,
  2288. },
  2289. [SIOCGIWRATE - SIOCIWFIRST] = {
  2290. .header_type = IW_HEADER_TYPE_PARAM,
  2291. },
  2292. [SIOCSIWRTS - SIOCIWFIRST] = {
  2293. .header_type = IW_HEADER_TYPE_PARAM,
  2294. },
  2295. [SIOCGIWRTS - SIOCIWFIRST] = {
  2296. .header_type = IW_HEADER_TYPE_PARAM,
  2297. },
  2298. [SIOCSIWFRAG - SIOCIWFIRST] = {
  2299. .header_type = IW_HEADER_TYPE_PARAM,
  2300. },
  2301. [SIOCGIWFRAG - SIOCIWFIRST] = {
  2302. .header_type = IW_HEADER_TYPE_PARAM,
  2303. },
  2304. [SIOCSIWTXPOW - SIOCIWFIRST] = {
  2305. .header_type = IW_HEADER_TYPE_PARAM,
  2306. },
  2307. [SIOCGIWTXPOW - SIOCIWFIRST] = {
  2308. .header_type = IW_HEADER_TYPE_PARAM,
  2309. },
  2310. [SIOCSIWRETRY - SIOCIWFIRST] = {
  2311. .header_type = IW_HEADER_TYPE_PARAM,
  2312. },
  2313. [SIOCGIWRETRY - SIOCIWFIRST] = {
  2314. .header_type = IW_HEADER_TYPE_PARAM,
  2315. },
  2316. [SIOCSIWENCODE - SIOCIWFIRST] = {
  2317. .header_type = IW_HEADER_TYPE_POINT,
  2318. .token_size = 1,
  2319. .max_tokens = IW_ENCODING_TOKEN_MAX,
  2320. .flags = IW_DESCR_FLAG_EVENT | IW_DESCR_FLAG_RESTRICT,
  2321. },
  2322. [SIOCGIWENCODE - SIOCIWFIRST] = {
  2323. .header_type = IW_HEADER_TYPE_POINT,
  2324. .token_size = 1,
  2325. .max_tokens = IW_ENCODING_TOKEN_MAX,
  2326. .flags = IW_DESCR_FLAG_DUMP | IW_DESCR_FLAG_RESTRICT,
  2327. },
  2328. [SIOCSIWPOWER - SIOCIWFIRST] = {
  2329. .header_type = IW_HEADER_TYPE_PARAM,
  2330. },
  2331. [SIOCGIWPOWER - SIOCIWFIRST] = {
  2332. .header_type = IW_HEADER_TYPE_PARAM,
  2333. },
  2334. [SIOCSIWMODUL - SIOCIWFIRST] = {
  2335. .header_type = IW_HEADER_TYPE_PARAM,
  2336. },
  2337. [SIOCGIWMODUL - SIOCIWFIRST] = {
  2338. .header_type = IW_HEADER_TYPE_PARAM,
  2339. },
  2340. [SIOCSIWGENIE - SIOCIWFIRST] = {
  2341. .header_type = IW_HEADER_TYPE_POINT,
  2342. .token_size = 1,
  2343. .max_tokens = IW_GENERIC_IE_MAX,
  2344. },
  2345. [SIOCGIWGENIE - SIOCIWFIRST] = {
  2346. .header_type = IW_HEADER_TYPE_POINT,
  2347. .token_size = 1,
  2348. .max_tokens = IW_GENERIC_IE_MAX,
  2349. },
  2350. [SIOCSIWAUTH - SIOCIWFIRST] = {
  2351. .header_type = IW_HEADER_TYPE_PARAM,
  2352. },
  2353. [SIOCGIWAUTH - SIOCIWFIRST] = {
  2354. .header_type = IW_HEADER_TYPE_PARAM,
  2355. },
  2356. [SIOCSIWENCODEEXT - SIOCIWFIRST] = {
  2357. .header_type = IW_HEADER_TYPE_POINT,
  2358. .token_size = 1,
  2359. .min_tokens = sizeof(struct iw_encode_ext),
  2360. .max_tokens = sizeof(struct iw_encode_ext) +
  2361. IW_ENCODING_TOKEN_MAX,
  2362. },
  2363. [SIOCGIWENCODEEXT - SIOCIWFIRST] = {
  2364. .header_type = IW_HEADER_TYPE_POINT,
  2365. .token_size = 1,
  2366. .min_tokens = sizeof(struct iw_encode_ext),
  2367. .max_tokens = sizeof(struct iw_encode_ext) +
  2368. IW_ENCODING_TOKEN_MAX,
  2369. },
  2370. [SIOCSIWPMKSA - SIOCIWFIRST] = {
  2371. .header_type = IW_HEADER_TYPE_POINT,
  2372. .token_size = 1,
  2373. .min_tokens = sizeof(struct iw_pmksa),
  2374. .max_tokens = sizeof(struct iw_pmksa),
  2375. },
  2376. };
  2377. static const unsigned int standard_ioctl_num = (sizeof(standard_ioctl_descr) /
  2378. sizeof(struct iw_ioctl_description));
  2379. /*
  2380. * Meta-data about all the additional standard Wireless Extension events
  2381. * we know about.
  2382. */
  2383. static const struct iw_ioctl_description standard_event_descr[] = {
  2384. [IWEVTXDROP - IWEVFIRST] = {
  2385. .header_type = IW_HEADER_TYPE_ADDR,
  2386. },
  2387. [IWEVQUAL - IWEVFIRST] = {
  2388. .header_type = IW_HEADER_TYPE_QUAL,
  2389. },
  2390. [IWEVCUSTOM - IWEVFIRST] = {
  2391. .header_type = IW_HEADER_TYPE_POINT,
  2392. .token_size = 1,
  2393. .max_tokens = IW_CUSTOM_MAX,
  2394. },
  2395. [IWEVREGISTERED - IWEVFIRST] = {
  2396. .header_type = IW_HEADER_TYPE_ADDR,
  2397. },
  2398. [IWEVEXPIRED - IWEVFIRST] = {
  2399. .header_type = IW_HEADER_TYPE_ADDR,
  2400. },
  2401. [IWEVGENIE - IWEVFIRST] = {
  2402. .header_type = IW_HEADER_TYPE_POINT,
  2403. .token_size = 1,
  2404. .max_tokens = IW_GENERIC_IE_MAX,
  2405. },
  2406. [IWEVMICHAELMICFAILURE - IWEVFIRST] = {
  2407. .header_type = IW_HEADER_TYPE_POINT,
  2408. .token_size = 1,
  2409. .max_tokens = sizeof(struct iw_michaelmicfailure),
  2410. },
  2411. [IWEVASSOCREQIE - IWEVFIRST] = {
  2412. .header_type = IW_HEADER_TYPE_POINT,
  2413. .token_size = 1,
  2414. .max_tokens = IW_GENERIC_IE_MAX,
  2415. },
  2416. [IWEVASSOCRESPIE - IWEVFIRST] = {
  2417. .header_type = IW_HEADER_TYPE_POINT,
  2418. .token_size = 1,
  2419. .max_tokens = IW_GENERIC_IE_MAX,
  2420. },
  2421. [IWEVPMKIDCAND - IWEVFIRST] = {
  2422. .header_type = IW_HEADER_TYPE_POINT,
  2423. .token_size = 1,
  2424. .max_tokens = sizeof(struct iw_pmkid_cand),
  2425. },
  2426. };
  2427. static const unsigned int standard_event_num = (sizeof(standard_event_descr) /
  2428. sizeof(struct iw_ioctl_description));
  2429. /* Size (in bytes) of various events */
  2430. static const int event_type_size[] = {
  2431. IW_EV_LCP_PK_LEN, /* IW_HEADER_TYPE_NULL */
  2432. 0,
  2433. IW_EV_CHAR_PK_LEN, /* IW_HEADER_TYPE_CHAR */
  2434. 0,
  2435. IW_EV_UINT_PK_LEN, /* IW_HEADER_TYPE_UINT */
  2436. IW_EV_FREQ_PK_LEN, /* IW_HEADER_TYPE_FREQ */
  2437. IW_EV_ADDR_PK_LEN, /* IW_HEADER_TYPE_ADDR */
  2438. 0,
  2439. IW_EV_POINT_PK_LEN, /* Without variable payload */
  2440. IW_EV_PARAM_PK_LEN, /* IW_HEADER_TYPE_PARAM */
  2441. IW_EV_QUAL_PK_LEN, /* IW_HEADER_TYPE_QUAL */
  2442. };
  2443. /*------------------------------------------------------------------*/
  2444. /*
  2445. * Initialise the struct stream_descr so that we can extract
  2446. * individual events from the event stream.
  2447. */
  2448. void
  2449. iw_init_event_stream(struct stream_descr * stream, /* Stream of events */
  2450. char * data,
  2451. int len)
  2452. {
  2453. /* Cleanup */
  2454. memset((char *) stream, '\0', sizeof(struct stream_descr));
  2455. /* Set things up */
  2456. stream->current = data;
  2457. stream->end = data + len;
  2458. }
  2459. /*------------------------------------------------------------------*/
  2460. /*
  2461. * Extract the next event from the event stream.
  2462. */
  2463. int
  2464. iw_extract_event_stream(struct stream_descr * stream, /* Stream of events */
  2465. struct iw_event * iwe, /* Extracted event */
  2466. int we_version)
  2467. {
  2468. const struct iw_ioctl_description * descr = NULL;
  2469. int event_type = 0;
  2470. unsigned int event_len = 1; /* Invalid */
  2471. char * pointer;
  2472. /* Don't "optimise" the following variable, it will crash */
  2473. unsigned cmd_index; /* *MUST* be unsigned */
  2474. /* Check for end of stream */
  2475. if((stream->current + IW_EV_LCP_PK_LEN) > stream->end)
  2476. return(0);
  2477. #ifdef DEBUG
  2478. printf("DBG - stream->current = %p, stream->value = %p, stream->end = %p\n",
  2479. stream->current, stream->value, stream->end);
  2480. #endif
  2481. /* Extract the event header (to get the event id).
  2482. * Note : the event may be unaligned, therefore copy... */
  2483. memcpy((char *) iwe, stream->current, IW_EV_LCP_PK_LEN);
  2484. #ifdef DEBUG
  2485. printf("DBG - iwe->cmd = 0x%X, iwe->len = %d\n",
  2486. iwe->cmd, iwe->len);
  2487. #endif
  2488. /* Check invalid events */
  2489. if(iwe->len <= IW_EV_LCP_PK_LEN)
  2490. return(-1);
  2491. /* Get the type and length of that event */
  2492. if(iwe->cmd <= SIOCIWLAST)
  2493. {
  2494. cmd_index = iwe->cmd - SIOCIWFIRST;
  2495. if(cmd_index < standard_ioctl_num)
  2496. descr = &(standard_ioctl_descr[cmd_index]);
  2497. }
  2498. else
  2499. {
  2500. cmd_index = iwe->cmd - IWEVFIRST;
  2501. if(cmd_index < standard_event_num)
  2502. descr = &(standard_event_descr[cmd_index]);
  2503. }
  2504. if(descr != NULL)
  2505. event_type = descr->header_type;
  2506. /* Unknown events -> event_type=0 => IW_EV_LCP_PK_LEN */
  2507. event_len = event_type_size[event_type];
  2508. /* Fixup for earlier version of WE */
  2509. if((we_version <= 18) && (event_type == IW_HEADER_TYPE_POINT))
  2510. event_len += IW_EV_POINT_OFF;
  2511. /* Check if we know about this event */
  2512. if(event_len <= IW_EV_LCP_PK_LEN)
  2513. {
  2514. /* Skip to next event */
  2515. stream->current += iwe->len;
  2516. return(2);
  2517. }
  2518. event_len -= IW_EV_LCP_PK_LEN;
  2519. /* Set pointer on data */
  2520. if(stream->value != NULL)
  2521. pointer = stream->value; /* Next value in event */
  2522. else
  2523. pointer = stream->current + IW_EV_LCP_PK_LEN; /* First value in event */
  2524. #ifdef DEBUG
  2525. printf("DBG - event_type = %d, event_len = %d, pointer = %p\n",
  2526. event_type, event_len, pointer);
  2527. #endif
  2528. /* Copy the rest of the event (at least, fixed part) */
  2529. if((pointer + event_len) > stream->end)
  2530. {
  2531. /* Go to next event */
  2532. stream->current += iwe->len;
  2533. return(-2);
  2534. }
  2535. /* Fixup for WE-19 and later : pointer no longer in the stream */
  2536. /* Beware of alignement. Dest has local alignement, not packed */
  2537. if((we_version > 18) && (event_type == IW_HEADER_TYPE_POINT))
  2538. memcpy((char *) iwe + IW_EV_LCP_LEN + IW_EV_POINT_OFF,
  2539. pointer, event_len);
  2540. else
  2541. memcpy((char *) iwe + IW_EV_LCP_LEN, pointer, event_len);
  2542. /* Skip event in the stream */
  2543. pointer += event_len;
  2544. /* Special processing for iw_point events */
  2545. if(event_type == IW_HEADER_TYPE_POINT)
  2546. {
  2547. /* Check the length of the payload */
  2548. unsigned int extra_len = iwe->len - (event_len + IW_EV_LCP_PK_LEN);
  2549. if(extra_len > 0)
  2550. {
  2551. /* Set pointer on variable part (warning : non aligned) */
  2552. iwe->u.data.pointer = pointer;
  2553. /* Check that we have a descriptor for the command */
  2554. if(descr == NULL)
  2555. /* Can't check payload -> unsafe... */
  2556. iwe->u.data.pointer = NULL; /* Discard paylod */
  2557. else
  2558. {
  2559. /* Those checks are actually pretty hard to trigger,
  2560. * because of the checks done in the kernel... */
  2561. unsigned int token_len = iwe->u.data.length * descr->token_size;
  2562. /* Ugly fixup for alignement issues.
  2563. * If the kernel is 64 bits and userspace 32 bits,
  2564. * we have an extra 4+4 bytes.
  2565. * Fixing that in the kernel would break 64 bits userspace. */
  2566. if((token_len != extra_len) && (extra_len >= 4))
  2567. {
  2568. __u16 alt_dlen = *((__u16 *) pointer);
  2569. unsigned int alt_token_len = alt_dlen * descr->token_size;
  2570. if((alt_token_len + 8) == extra_len)
  2571. {
  2572. #ifdef DEBUG
  2573. printf("DBG - alt_token_len = %d\n", alt_token_len);
  2574. #endif
  2575. /* Ok, let's redo everything */
  2576. pointer -= event_len;
  2577. pointer += 4;
  2578. /* Dest has local alignement, not packed */
  2579. memcpy((char *) iwe + IW_EV_LCP_LEN + IW_EV_POINT_OFF,
  2580. pointer, event_len);
  2581. pointer += event_len + 4;
  2582. iwe->u.data.pointer = pointer;
  2583. token_len = alt_token_len;
  2584. }
  2585. }
  2586. /* Discard bogus events which advertise more tokens than
  2587. * what they carry... */
  2588. if(token_len > extra_len)
  2589. iwe->u.data.pointer = NULL; /* Discard paylod */
  2590. /* Check that the advertised token size is not going to
  2591. * produce buffer overflow to our caller... */
  2592. if((iwe->u.data.length > descr->max_tokens)
  2593. && !(descr->flags & IW_DESCR_FLAG_NOMAX))
  2594. iwe->u.data.pointer = NULL; /* Discard paylod */
  2595. /* Same for underflows... */
  2596. if(iwe->u.data.length < descr->min_tokens)
  2597. iwe->u.data.pointer = NULL; /* Discard paylod */
  2598. #ifdef DEBUG
  2599. printf("DBG - extra_len = %d, token_len = %d, token = %d, max = %d, min = %d\n",
  2600. extra_len, token_len, iwe->u.data.length, descr->max_tokens, descr->min_tokens);
  2601. #endif
  2602. }
  2603. }
  2604. else
  2605. /* No data */
  2606. iwe->u.data.pointer = NULL;
  2607. /* Go to next event */
  2608. stream->current += iwe->len;
  2609. }
  2610. else
  2611. {
  2612. /* Ugly fixup for alignement issues.
  2613. * If the kernel is 64 bits and userspace 32 bits,
  2614. * we have an extra 4 bytes.
  2615. * Fixing that in the kernel would break 64 bits userspace. */
  2616. if((stream->value == NULL)
  2617. && ((((iwe->len - IW_EV_LCP_PK_LEN) % event_len) == 4)
  2618. || ((iwe->len == 12) && ((event_type == IW_HEADER_TYPE_UINT) ||
  2619. (event_type == IW_HEADER_TYPE_QUAL))) ))
  2620. {
  2621. #ifdef DEBUG
  2622. printf("DBG - alt iwe->len = %d\n", iwe->len - 4);
  2623. #endif
  2624. pointer -= event_len;
  2625. pointer += 4;
  2626. /* Beware of alignement. Dest has local alignement, not packed */
  2627. memcpy((char *) iwe + IW_EV_LCP_LEN, pointer, event_len);
  2628. pointer += event_len;
  2629. }
  2630. /* Is there more value in the event ? */
  2631. if((pointer + event_len) <= (stream->current + iwe->len))
  2632. /* Go to next value */
  2633. stream->value = pointer;
  2634. else
  2635. {
  2636. /* Go to next event */
  2637. stream->value = NULL;
  2638. stream->current += iwe->len;
  2639. }
  2640. }
  2641. return(1);
  2642. }
  2643. /*********************** SCANNING SUBROUTINES ***********************/
  2644. /*
  2645. * The Wireless Extension API 14 and greater define Wireless Scanning.
  2646. * The normal API is complex, this is an easy API that return
  2647. * a subset of the scanning results. This should be enough for most
  2648. * applications that want to use Scanning.
  2649. * If you want to have use the full/normal API, check iwlist.c...
  2650. *
  2651. * Precaution when using scanning :
  2652. * The scanning operation disable normal network traffic, and therefore
  2653. * you should not abuse of scan.
  2654. * The scan need to check the presence of network on other frequencies.
  2655. * While you are checking those other frequencies, you can *NOT* be on
  2656. * your normal frequency to listen to normal traffic in the cell.
  2657. * You need typically in the order of one second to actively probe all
  2658. * 802.11b channels (do the maths). Some cards may do that in background,
  2659. * to reply to scan commands faster, but they still have to do it.
  2660. * Leaving the cell for such an extended period of time is pretty bad.
  2661. * Any kind of streaming/low latency traffic will be impacted, and the
  2662. * user will perceive it (easily checked with telnet). People trying to
  2663. * send traffic to you will retry packets and waste bandwidth. Some
  2664. * applications may be sensitive to those packet losses in weird ways,
  2665. * and tracing those weird behavior back to scanning may take time.
  2666. * If you are in ad-hoc mode, if two nodes scan approx at the same
  2667. * time, they won't see each other, which may create associations issues.
  2668. * For those reasons, the scanning activity should be limited to
  2669. * what's really needed, and continuous scanning is a bad idea.
  2670. * Jean II
  2671. */
  2672. /*------------------------------------------------------------------*/
  2673. /*
  2674. * Process/store one element from the scanning results in wireless_scan
  2675. */
  2676. static inline struct wireless_scan *
  2677. iw_process_scanning_token(struct iw_event * event,
  2678. struct wireless_scan * wscan)
  2679. {
  2680. struct wireless_scan * oldwscan;
  2681. /* Now, let's decode the event */
  2682. switch(event->cmd)
  2683. {
  2684. case SIOCGIWAP:
  2685. /* New cell description. Allocate new cell descriptor, zero it. */
  2686. oldwscan = wscan;
  2687. wscan = (struct wireless_scan *) malloc(sizeof(struct wireless_scan));
  2688. if(wscan == NULL)
  2689. return(wscan);
  2690. /* Link at the end of the list */
  2691. if(oldwscan != NULL)
  2692. oldwscan->next = wscan;
  2693. /* Reset it */
  2694. bzero(wscan, sizeof(struct wireless_scan));
  2695. /* Save cell identifier */
  2696. wscan->has_ap_addr = 1;
  2697. memcpy(&(wscan->ap_addr), &(event->u.ap_addr), sizeof (sockaddr));
  2698. break;
  2699. case SIOCGIWNWID:
  2700. wscan->b.has_nwid = 1;
  2701. memcpy(&(wscan->b.nwid), &(event->u.nwid), sizeof(iwparam));
  2702. break;
  2703. case SIOCGIWFREQ:
  2704. wscan->b.has_freq = 1;
  2705. wscan->b.freq = iw_freq2float(&(event->u.freq));
  2706. wscan->b.freq_flags = event->u.freq.flags;
  2707. break;
  2708. case SIOCGIWMODE:
  2709. wscan->b.mode = event->u.mode;
  2710. if((wscan->b.mode < IW_NUM_OPER_MODE) && (wscan->b.mode >= 0))
  2711. wscan->b.has_mode = 1;
  2712. break;
  2713. case SIOCGIWESSID:
  2714. wscan->b.has_essid = 1;
  2715. wscan->b.essid_on = event->u.data.flags;
  2716. memset(wscan->b.essid, '\0', IW_ESSID_MAX_SIZE+1);
  2717. if((event->u.essid.pointer) && (event->u.essid.length))
  2718. memcpy(wscan->b.essid, event->u.essid.pointer, event->u.essid.length);
  2719. break;
  2720. case SIOCGIWENCODE:
  2721. wscan->b.has_key = 1;
  2722. wscan->b.key_size = event->u.data.length;
  2723. wscan->b.key_flags = event->u.data.flags;
  2724. if(event->u.data.pointer)
  2725. memcpy(wscan->b.key, event->u.essid.pointer, event->u.data.length);
  2726. else
  2727. wscan->b.key_flags |= IW_ENCODE_NOKEY;
  2728. break;
  2729. case IWEVQUAL:
  2730. /* We don't get complete stats, only qual */
  2731. wscan->has_stats = 1;
  2732. memcpy(&wscan->stats.qual, &event->u.qual, sizeof(struct iw_quality));
  2733. break;
  2734. case SIOCGIWRATE:
  2735. /* Scan may return a list of bitrates. As we have space for only
  2736. * a single bitrate, we only keep the largest one. */
  2737. if((!wscan->has_maxbitrate) ||
  2738. (event->u.bitrate.value > wscan->maxbitrate.value))
  2739. {
  2740. wscan->has_maxbitrate = 1;
  2741. memcpy(&(wscan->maxbitrate), &(event->u.bitrate), sizeof(iwparam));
  2742. }
  2743. case IWEVCUSTOM:
  2744. /* How can we deal with those sanely ? Jean II */
  2745. default:
  2746. break;
  2747. } /* switch(event->cmd) */
  2748. return(wscan);
  2749. }
  2750. /*------------------------------------------------------------------*/
  2751. /*
  2752. * Initiate the scan procedure, and process results.
  2753. * This is a non-blocking procedure and it will return each time
  2754. * it would block, returning the amount of time the caller should wait
  2755. * before calling again.
  2756. * Return -1 for error, delay to wait for (in ms), or 0 for success.
  2757. * Error code is in errno
  2758. */
  2759. int
  2760. iw_process_scan(int skfd,
  2761. char * ifname,
  2762. int we_version,
  2763. wireless_scan_head * context)
  2764. {
  2765. struct iwreq wrq;
  2766. unsigned char * buffer = NULL; /* Results */
  2767. int buflen = IW_SCAN_MAX_DATA; /* Min for compat WE<17 */
  2768. unsigned char * newbuf;
  2769. /* Don't waste too much time on interfaces (150 * 100 = 15s) */
  2770. context->retry++;
  2771. if(context->retry > 150)
  2772. {
  2773. errno = ETIME;
  2774. return(-1);
  2775. }
  2776. /* If we have not yet initiated scanning on the interface */
  2777. if(context->retry == 1)
  2778. {
  2779. /* Initiate Scan */
  2780. wrq.u.data.pointer = NULL; /* Later */
  2781. wrq.u.data.flags = 0;
  2782. wrq.u.data.length = 0;
  2783. /* Remember that as non-root, we will get an EPERM here */
  2784. if((iw_set_ext(skfd, ifname, SIOCSIWSCAN, &wrq) < 0)
  2785. && (errno != EPERM))
  2786. return(-1);
  2787. /* Success : now, just wait for event or results */
  2788. return(250); /* Wait 250 ms */
  2789. }
  2790. realloc:
  2791. /* (Re)allocate the buffer - realloc(NULL, len) == malloc(len) */
  2792. newbuf = realloc(buffer, buflen);
  2793. if(newbuf == NULL)
  2794. {
  2795. /* man says : If realloc() fails the original block is left untouched */
  2796. if(buffer)
  2797. free(buffer);
  2798. errno = ENOMEM;
  2799. return(-1);
  2800. }
  2801. buffer = newbuf;
  2802. /* Try to read the results */
  2803. wrq.u.data.pointer = buffer;
  2804. wrq.u.data.flags = 0;
  2805. wrq.u.data.length = buflen;
  2806. if(iw_get_ext(skfd, ifname, SIOCGIWSCAN, &wrq) < 0)
  2807. {
  2808. /* Check if buffer was too small (WE-17 only) */
  2809. if((errno == E2BIG) && (we_version > 16))
  2810. {
  2811. /* Some driver may return very large scan results, either
  2812. * because there are many cells, or because they have many
  2813. * large elements in cells (like IWEVCUSTOM). Most will
  2814. * only need the regular sized buffer. We now use a dynamic
  2815. * allocation of the buffer to satisfy everybody. Of course,
  2816. * as we don't know in advance the size of the array, we try
  2817. * various increasing sizes. Jean II */
  2818. /* Check if the driver gave us any hints. */
  2819. if(wrq.u.data.length > buflen)
  2820. buflen = wrq.u.data.length;
  2821. else
  2822. buflen *= 2;
  2823. /* Try again */
  2824. goto realloc;
  2825. }
  2826. /* Check if results not available yet */
  2827. if(errno == EAGAIN)
  2828. {
  2829. free(buffer);
  2830. /* Wait for only 100ms from now on */
  2831. return(100); /* Wait 100 ms */
  2832. }
  2833. free(buffer);
  2834. /* Bad error, please don't come back... */
  2835. return(-1);
  2836. }
  2837. /* We have the results, process them */
  2838. if(wrq.u.data.length)
  2839. {
  2840. struct iw_event iwe;
  2841. struct stream_descr stream;
  2842. struct wireless_scan * wscan = NULL;
  2843. int ret;
  2844. #ifdef DEBUG
  2845. /* Debugging code. In theory useless, because it's debugged ;-) */
  2846. int i;
  2847. printf("Scan result [%02X", buffer[0]);
  2848. for(i = 1; i < wrq.u.data.length; i++)
  2849. printf(":%02X", buffer[i]);
  2850. printf("]\n");
  2851. #endif
  2852. /* Init */
  2853. iw_init_event_stream(&stream, (char *) buffer, wrq.u.data.length);
  2854. /* This is dangerous, we may leak user data... */
  2855. context->result = NULL;
  2856. /* Look every token */
  2857. do
  2858. {
  2859. /* Extract an event and print it */
  2860. ret = iw_extract_event_stream(&stream, &iwe, we_version);
  2861. if(ret > 0)
  2862. {
  2863. /* Convert to wireless_scan struct */
  2864. wscan = iw_process_scanning_token(&iwe, wscan);
  2865. /* Check problems */
  2866. if(wscan == NULL)
  2867. {
  2868. free(buffer);
  2869. errno = ENOMEM;
  2870. return(-1);
  2871. }
  2872. /* Save head of list */
  2873. if(context->result == NULL)
  2874. context->result = wscan;
  2875. }
  2876. }
  2877. while(ret > 0);
  2878. }
  2879. /* Done with this interface - return success */
  2880. free(buffer);
  2881. return(0);
  2882. }
  2883. /*------------------------------------------------------------------*/
  2884. /*
  2885. * Perform a wireless scan on the specified interface.
  2886. * This is a blocking procedure and it will when the scan is completed
  2887. * or when an error occur.
  2888. *
  2889. * The scan results are given in a linked list of wireless_scan objects.
  2890. * The caller *must* free the result himself (by walking the list).
  2891. * If there is an error, -1 is returned and the error code is available
  2892. * in errno.
  2893. *
  2894. * The parameter we_version can be extracted from the range structure
  2895. * (range.we_version_compiled - see iw_get_range_info()), or using
  2896. * iw_get_kernel_we_version(). For performance reason, you should
  2897. * cache this parameter when possible rather than querying it every time.
  2898. *
  2899. * Return -1 for error and 0 for success.
  2900. */
  2901. int
  2902. iw_scan(int skfd,
  2903. char * ifname,
  2904. int we_version,
  2905. wireless_scan_head * context)
  2906. {
  2907. int delay; /* in ms */
  2908. /* Clean up context. Potential memory leak if(context.result != NULL) */
  2909. context->result = NULL;
  2910. context->retry = 0;
  2911. /* Wait until we get results or error */
  2912. while(1)
  2913. {
  2914. /* Try to get scan results */
  2915. delay = iw_process_scan(skfd, ifname, we_version, context);
  2916. /* Check termination */
  2917. if(delay <= 0)
  2918. break;
  2919. /* Wait a bit */
  2920. usleep(delay * 1000);
  2921. }
  2922. /* End - return -1 or 0 */
  2923. return(delay);
  2924. }