iwinfo 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200
  1. #!/usr/bin/ucode
  2. 'use strict';
  3. import { find_phy } from 'wifi.utils';
  4. import * as uci from 'uci';
  5. import * as iwinfo from 'iwinfo';
  6. function normalize_ssid(ssid) {
  7. if (!ssid)
  8. return 'unknown';
  9. return '"' + replace(ssid, /[[:cntrl:]]/g,
  10. function(c) { return '\\x' + hexenc(c); }) + '"'
  11. }
  12. function print_assoclist(stations) {
  13. for (let mac, station in stations) {
  14. printf(`${station.mac} ${station.signal} dBm / ${station.noise} dBm (SNR ${station.snr}) ${station.inactive_time} ms ago\n`);
  15. for (let k in [ 'rx', 'tx' ]) {
  16. let bitrate = station[k];
  17. let flags = join(', ', bitrate.flags);
  18. printf(`\t${uc(k)}: ${bitrate.bitrate == 'unknown' ? 'unknown' : bitrate.bitrate + ' MBit/s'}`);
  19. if (length(bitrate.flags))
  20. printf(', %s', flags);
  21. printf('%10d Pkts.\n', bitrate.packets);
  22. }
  23. let expected_throughput = station.expected_throughput;
  24. printf(`\texpected throughput: ${expected_throughput == 'unknown' ? 'unknown' : expected_throughput + ' MBit/s'}\n\n`);
  25. }
  26. }
  27. function print_countrylist(list) {
  28. for (let k, v in list.countries)
  29. printf(`${k == list.active ? '*' : ' '} ${k} "${v}"\n`);
  30. }
  31. function print_freqlist(channels) {
  32. for (let channel in channels) {
  33. printf(`${channel.active ? '*' : ' '} ${channel.freq} GHz (Band: ${channel.band} GHz, Channel ${channel.channel})`);
  34. if (length(channel.flags))
  35. printf(` [${join(', ', channel.flags)}]`);
  36. printf('\n');
  37. }
  38. }
  39. function print_htmodelist(htmode) {
  40. printf('%s\n', join(' ', htmode));
  41. }
  42. function print_info(list) {
  43. let padding = ' ';
  44. for (let bss in list) {
  45. printf(`${bss.iface} ESSID: ${normalize_ssid(bss.ssid)}\n`);
  46. printf(`${padding}Access Point: ${bss.mac}\n`);
  47. printf(`${padding}Mode: ${bss.mode} Channel: ${bss.channel} (${bss.freq} GHz) HT Mode: ${bss.htmode}\n`);
  48. printf(`${padding}Center Channel 1: ${bss.center_freq1} 2: ${bss.center_freq2}\n`);
  49. printf(`${padding}Tx-Power: ${bss.txpower} dBm Link Quality: ${bss.quality}/70\n`);
  50. printf(`${padding}Signal: ${bss.signal} dBm Noise: ${bss.noise} dBm\n`);
  51. printf(`${padding}Bit Rate: ${bss.bitrate == 'unknown' ? 'unknown' : bss.bitrate + ' MBit/s'}\n`);
  52. printf(`${padding}Encryption: ${bss.encryption}\n`);
  53. printf(`${padding}Type: nl80211 HW Mode(s): 802.11${bss.hwmode}\n`);
  54. printf(`${padding}Hardware: ${bss.hw_type} [${bss.hw_id}]\n`);
  55. printf(`${padding}TX power offset: ${bss.power_offset}\n`);
  56. printf(`${padding}Channel offset: ${bss.channel_offset}\n`);
  57. printf(`${padding}Supports VAPs: ${bss.vaps} PHY name: ${bss.phy}\n`);
  58. if (bss.owe_transition_ifname)
  59. printf(`${padding}OWE partner: ${bss.owe_transition_ifname}\n`);
  60. printf('\n');
  61. }
  62. return 0;
  63. }
  64. function print_scan(cells) {
  65. let idx = 1;
  66. for (let cell in cells) {
  67. printf('Cell %02d - Address: %s\n', idx++, cell.bssid);
  68. printf('\t ESSID: %s\n', normalize_ssid(cell.ssid));
  69. printf('\t Mode: %s Frequency: %s GHz Band: %s GHz Channel: %d\n', cell.mode, cell.frequency, cell.band, cell.channel);
  70. printf('\t Signal: %d dBm Quality: %2d/70\n', cell.dbm, cell.quality);
  71. if (!cell.crypto || !length(cell.crypto.key_mgmt))
  72. printf('\t Encryption: NONE\n');
  73. else
  74. printf('\t Encryption: %s (%s)\n', join(' / ', cell.crypto.key_mgmt), join(' / ', cell.crypto.pair));
  75. if (cell.ht) {
  76. printf('\t HT Operation:\n');
  77. printf('\t\tPrimary Channel: %d\n', cell.ht.primary_channel);
  78. printf('\t\tSecondary Channel Offset: %s\n', cell.ht.secondary_chan_off);
  79. printf('\t\tChannel Width: %s\n', cell.ht.chan_width);
  80. }
  81. if (cell.vht) {
  82. printf('\t VHT Operation:\n');
  83. printf('\t\tCenter Frequency 1: %d\n', cell.vht.center_chan_1);
  84. printf('\t\tCenter Frequency 2: %s\n', cell.vht.center_chan_2);
  85. printf('\t\tChannel Width: %s\n', cell.vht.chan_width);
  86. }
  87. if (cell.he) {
  88. printf('\t HE Operation:\n');
  89. printf('\t\tCenter Frequency 1: %d\n', cell.he.center_chan_1);
  90. printf('\t\tCenter Frequency 2: %s\n', cell.he.center_chan_2);
  91. printf('\t\tChannel Width: %s\n', cell.he.chan_width);
  92. }
  93. if (cell.eht) {
  94. printf('\t EHT Operation:\n');
  95. printf('\t\tCenter Frequency 1: %d\n', cell.eht.center_chan_1);
  96. printf('\t\tCenter Frequency 2: %s\n', cell.eht.center_chan_2);
  97. printf('\t\tChannel Width: %s\n', cell.eht.chan_width);
  98. }
  99. printf('\n');
  100. }
  101. }
  102. function print_txpowerlist(list) {
  103. for (let power in list)
  104. printf('%s %2d dbm (%4d mW)\n', power.active ? '*' : ' ', power.dbm, power.mw);
  105. }
  106. let pretty = true;
  107. if (ARGV[0] == '-j') {
  108. pretty = false;
  109. shift(ARGV);
  110. }
  111. if (!length(ARGV)) {
  112. let info = iwinfo.info();
  113. if (pretty)
  114. print_info(info);
  115. else
  116. printf('%.J\n', info);
  117. return 0;
  118. }
  119. const commands = {
  120. assoclist: [ iwinfo.assoclist, print_assoclist ],
  121. countrylist: [ iwinfo.countrylist, print_countrylist ],
  122. freqlist: [ iwinfo.freqlist, print_freqlist ],
  123. htmodelist: [ iwinfo.htmodelist, print_htmodelist ],
  124. info: [ iwinfo.info, print_info ],
  125. scan: [ iwinfo.scan, print_scan ],
  126. txpowerlist: [ iwinfo.txpowerlist, print_txpowerlist ],
  127. };
  128. if (ARGV[0] == 'nl80211' && ARGV[1] == 'phyname') {
  129. let sec_name = ARGV[2];
  130. let sec = uci.cursor(null, null, null, { strict: false }).get_all('wireless', sec_name);
  131. if (!sec || sec['.type'] != 'wifi-device') {
  132. warn(`Config section ${sec_name} not found\n`);
  133. return 1;
  134. }
  135. let name = find_phy(sec);
  136. if (!name) {
  137. warn('Phy not found\n');
  138. return 1;
  139. }
  140. print(name + '\n');
  141. return 0;
  142. }
  143. if (length(ARGV) == 2 && iwinfo.ifaces[ARGV[0]])
  144. for (let cmd, cb in commands)
  145. if (substr(cmd, 0, length(ARGV[1])) == ARGV[1]) {
  146. let ret = cb[0](ARGV[0]);
  147. if (pretty)
  148. cb[1](ret);
  149. else
  150. printf('%.J\n', ret);
  151. return 0;
  152. }
  153. switch(ARGV[0]) {
  154. case 'phy':
  155. printf('%.J\n', iwinfo.phys);
  156. return 0;
  157. case 'iface':
  158. printf('%.J\n', iwinfo.ifaces);
  159. return 0;
  160. }
  161. warn('Usage:\n' +
  162. '\tiwinfo <device> info\n' +
  163. '\tiwinfo <device> scan\n' +
  164. '\tiwinfo <device> txpowerlist\n' +
  165. '\tiwinfo <device> freqlist\n' +
  166. '\tiwinfo <device> assoclist\n' +
  167. '\tiwinfo <device> countrylist\n' +
  168. '\tiwinfo <device> htmodelist\n' +
  169. '\tiwinfo nl80211 phyname <section>\n');
  170. return 1;