00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 FILE_LICENCE ( GPL2_OR_LATER );
00020
00021 #include <stdio.h>
00022 #include <console.h>
00023 #include <string.h>
00024 #include <errno.h>
00025 #include <gpxe/net80211.h>
00026 #include <gpxe/ethernet.h>
00027 #include <usr/ifmgmt.h>
00028 #include <usr/iwmgmt.h>
00029 #include <gpxe/errortab.h>
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042 void iwstat ( struct net80211_device *dev ) {
00043
00044 ifstat ( dev->netdev );
00045
00046 printf ( " [802.11 ");
00047 if ( dev->state & NET80211_ASSOCIATED ) {
00048 printf ( "SSID '%s', ", dev->essid );
00049 } else {
00050 printf ( "not associated, " );
00051 }
00052 if ( dev->channel < dev->nr_channels && dev->rate < dev->nr_rates ) {
00053 printf ( "Ch:%d Sig:%d", dev->channels[dev->channel].channel_nr,
00054 dev->last_signal );
00055 switch ( dev->hw->signal_type ) {
00056 case NET80211_SIGNAL_NONE:
00057 printf ( "?" );
00058 break;
00059 case NET80211_SIGNAL_ARBITRARY:
00060 printf ( "/%d", dev->hw->signal_max );
00061 break;
00062 case NET80211_SIGNAL_DB:
00063 printf ( "/%d dB", dev->hw->signal_max );
00064 break;
00065 case NET80211_SIGNAL_DBM:
00066 printf ( " dBm" );
00067 break;
00068 }
00069 printf ( ", Qual:%d%% Rate:%d Mbps]\n",
00070 ( dev->rx_beacon_interval == 0 ? 0 :
00071 100 * dev->tx_beacon_interval /
00072 dev->rx_beacon_interval ),
00073 dev->rates[dev->rate] / 10 );
00074 } else {
00075 printf ( "antenna off]\n" );
00076 }
00077
00078 if ( dev->state & NET80211_WORKING ) {
00079 printf ( " [associating" );
00080 if ( dev->associating )
00081 printf ( " to '%s'", dev->associating->essid );
00082 printf ( "...]\n" );
00083 }
00084 }
00085
00086
00087 static const char *crypto_types[] = {
00088 [NET80211_CRYPT_NONE] = "Open",
00089 [NET80211_CRYPT_WEP] = "WEP ",
00090 [NET80211_CRYPT_TKIP] = "WPA ",
00091 [NET80211_CRYPT_CCMP] = "WPA2",
00092 [NET80211_CRYPT_UNKNOWN] = "UNK ",
00093 };
00094
00095
00096 #define NR_CRYPTO_TYPES ( sizeof ( crypto_types ) / sizeof ( crypto_types[0] ) )
00097
00098
00099 static const char *auth_types[] = {
00100 [NET80211_SECPROT_NONE] = "",
00101 [NET80211_SECPROT_PSK] = "PSK",
00102 [NET80211_SECPROT_EAP] = "802.1X",
00103 [NET80211_SECPROT_UNKNOWN] = "UNK",
00104 };
00105
00106
00107 #define NR_AUTH_TYPES ( sizeof ( auth_types ) / sizeof ( auth_types[0] ) )
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121 int iwlist ( struct net80211_device *dev ) {
00122 struct net80211_probe_ctx *ctx;
00123 struct list_head *networks;
00124 struct net80211_wlan *wlan;
00125 char ssid_buf[22];
00126 int rc;
00127 unsigned i;
00128 int was_opened = netdev_is_open ( dev->netdev );
00129 int was_channel = dev->channels[dev->channel].channel_nr;
00130
00131 if ( ! was_opened ) {
00132 dev->state |= NET80211_NO_ASSOC;
00133 rc = netdev_open ( dev->netdev );
00134 if ( rc < 0 )
00135 goto err;
00136 }
00137
00138 if ( dev->state & NET80211_WORKING ) {
00139 rc = -EINVAL;
00140 goto err_close_netdev;
00141 }
00142
00143 if ( ! was_opened ) {
00144 rc = net80211_prepare_probe ( dev, dev->hw->bands, 0 );
00145 if ( rc < 0 )
00146 goto err_close_netdev;
00147 }
00148
00149 ctx = net80211_probe_start ( dev, "", 0 );
00150 if ( ! ctx ) {
00151 rc = -ENOMEM;
00152 goto err_close_netdev;
00153 }
00154
00155 while ( ! ( rc = net80211_probe_step ( ctx ) ) ) {
00156 step();
00157 }
00158
00159 networks = net80211_probe_finish_all ( ctx );
00160
00161 if ( list_empty ( networks ) ) {
00162 goto err_free_networks;
00163 }
00164
00165 rc = 0;
00166
00167 printf ( "Networks on %s:\n\n", dev->netdev->name );
00168
00169
00170
00171
00172
00173
00174
00175
00176
00177
00178
00179
00180 printf ( "[Sig] SSID BSSID Ch Crypt/Auth\n"
00181 "-------------------------------------------------------------\n" );
00182
00183 list_for_each_entry ( wlan, networks, list ) {
00184
00185
00186
00187
00188 snprintf ( ssid_buf, sizeof ( ssid_buf ), "%s", wlan->essid );
00189 for ( i = strlen ( ssid_buf ); i < sizeof ( ssid_buf ) - 1;
00190 i++ )
00191 ssid_buf[i] = ' ';
00192 if ( ssid_buf[sizeof ( ssid_buf ) - 2] != ' ' )
00193 ssid_buf[sizeof ( ssid_buf ) - 2] = '>';
00194 ssid_buf[sizeof ( ssid_buf ) - 1] = 0;
00195
00196
00197 if ( wlan->crypto >= NR_CRYPTO_TYPES ||
00198 wlan->handshaking >= NR_AUTH_TYPES )
00199 continue;
00200
00201 printf ( "[%3d] %s %s %2d %s %s\n",
00202 wlan->signal < 0 ? 100 + wlan->signal : wlan->signal,
00203 ssid_buf, eth_ntoa ( wlan->bssid ), wlan->channel,
00204 crypto_types[wlan->crypto],
00205 auth_types[wlan->handshaking] );
00206 }
00207 printf ( "\n" );
00208
00209 err_free_networks:
00210 net80211_free_wlanlist ( networks );
00211
00212 err_close_netdev:
00213 if ( ! was_opened ) {
00214 dev->state &= ~NET80211_NO_ASSOC;
00215 netdev_close ( dev->netdev );
00216 } else {
00217 net80211_change_channel ( dev, was_channel );
00218 }
00219
00220 if ( ! rc )
00221 return 0;
00222
00223 err:
00224 printf ( "Scanning for networks on %s: %s\n",
00225 dev->netdev->name, strerror ( rc ) );
00226 return rc;
00227 }
00228
00229
00230
00231 #undef ERRFILE
00232 #define ERRFILE ERRFILE_net80211
00233
00234
00235 struct errortab common_wireless_errors[] __errortab = {
00236 { EINVAL | EUNIQ_06, "Packet decryption error" },
00237 { ECONNRESET | EUNIQ_01, "Unspecified reason" },
00238 { ECONNRESET | EUNIQ_04, "Disassociated due to inactivity" },
00239 { ECONNRESET | EUNIQ_0F, "4-Way Handshake timeout" },
00240 { ECONNRESET | EUNIQ_17, "IEEE 802.1X authentication failed" },
00241 { ECONNREFUSED | EUNIQ_01, "Unspecified failure" },
00242 { ECONNREFUSED | EUNIQ_0C, "Association denied" },
00243 { ECONNREFUSED | EUNIQ_0D, "Authentication method not supported" },
00244 };