00001
00017 #include "includes.h"
00018
00019 #include "hostapd.h"
00020 #include "hw_features.h"
00021 #include "driver.h"
00022 #include "config.h"
00023 #include "ieee802_11.h"
00024 #include "eloop.h"
00025
00026
00027 void hostapd_free_hw_features(struct hostapd_hw_modes *hw_features,
00028 size_t num_hw_features)
00029 {
00030 size_t i;
00031
00032 if (hw_features == NULL)
00033 return;
00034
00035 for (i = 0; i < num_hw_features; i++) {
00036 free(hw_features[i].channels);
00037 free(hw_features[i].rates);
00038 }
00039
00040 free(hw_features);
00041 }
00042
00043
00044 int hostapd_get_hw_features(struct hostapd_iface *iface)
00045 {
00046 struct hostapd_data *hapd = iface->bss[0];
00047 int ret = 0, i, j;
00048 u16 num_modes, flags;
00049 struct hostapd_hw_modes *modes;
00050
00051 modes = hostapd_get_hw_feature_data(hapd, &num_modes, &flags);
00052 if (modes == NULL) {
00053 hostapd_logger(hapd, NULL, HOSTAPD_MODULE_IEEE80211,
00054 HOSTAPD_LEVEL_DEBUG,
00055 "Fetching hardware channel/rate support not "
00056 "supported.");
00057 return -1;
00058 }
00059
00060 iface->hw_flags = flags;
00061
00062 hostapd_free_hw_features(iface->hw_features, iface->num_hw_features);
00063 iface->hw_features = modes;
00064 iface->num_hw_features = num_modes;
00065
00066 for (i = 0; i < num_modes; i++) {
00067 struct hostapd_hw_modes *feature = &modes[i];
00068
00069
00070 for (j = 0; j < feature->num_channels; j++) {
00071
00072 unsigned char power_level = 0;
00073 unsigned char antenna_max = 0;
00074
00075 if ((feature->mode == HOSTAPD_MODE_IEEE80211G ||
00076 feature->mode == HOSTAPD_MODE_IEEE80211B) &&
00077 feature->channels[j].chan >= 1 &&
00078 feature->channels[j].chan <= 11) {
00079 power_level = 20;
00080 feature->channels[j].flag |=
00081 HOSTAPD_CHAN_W_SCAN;
00082 } else
00083 feature->channels[j].flag &=
00084 ~HOSTAPD_CHAN_W_SCAN;
00085
00086 hostapd_set_channel_flag(hapd, feature->mode,
00087 feature->channels[j].chan,
00088 feature->channels[j].flag,
00089 power_level,
00090 antenna_max);
00091 }
00092 }
00093
00094 return ret;
00095 }
00096
00097
00098 static int hostapd_prepare_rates(struct hostapd_data *hapd,
00099 struct hostapd_hw_modes *mode)
00100 {
00101 int i, num_basic_rates = 0;
00102 int basic_rates_a[] = { 60, 120, 240, -1 };
00103 int basic_rates_b[] = { 10, 20, -1 };
00104 int basic_rates_g[] = { 10, 20, 55, 110, -1 };
00105 int *basic_rates;
00106
00107 if (hapd->iconf->basic_rates)
00108 basic_rates = hapd->iconf->basic_rates;
00109 else switch (mode->mode) {
00110 case HOSTAPD_MODE_IEEE80211A:
00111 basic_rates = basic_rates_a;
00112 break;
00113 case HOSTAPD_MODE_IEEE80211B:
00114 basic_rates = basic_rates_b;
00115 break;
00116 case HOSTAPD_MODE_IEEE80211G:
00117 basic_rates = basic_rates_g;
00118 break;
00119 default:
00120 return -1;
00121 }
00122
00123 if (hostapd_set_rate_sets(hapd, hapd->iconf->supported_rates,
00124 basic_rates, mode->mode)) {
00125 printf("Failed to update rate sets in kernel module\n");
00126 }
00127
00128 free(hapd->iface->current_rates);
00129 hapd->iface->num_rates = 0;
00130
00131 hapd->iface->current_rates =
00132 malloc(mode->num_rates * sizeof(struct hostapd_rate_data));
00133 if (!hapd->iface->current_rates) {
00134 printf("Failed to allocate memory for rate table.\n");
00135 return -1;
00136 }
00137
00138 for (i = 0; i < mode->num_rates; i++) {
00139 struct hostapd_rate_data *rate;
00140
00141 if (hapd->iconf->supported_rates &&
00142 !hostapd_rate_found(hapd->iconf->supported_rates,
00143 mode->rates[i].rate))
00144 continue;
00145
00146 rate = &hapd->iface->current_rates[hapd->iface->num_rates];
00147 memcpy(rate, &mode->rates[i],
00148 sizeof(struct hostapd_rate_data));
00149 if (hostapd_rate_found(basic_rates, rate->rate)) {
00150 rate->flags |= HOSTAPD_RATE_BASIC;
00151 num_basic_rates++;
00152 } else
00153 rate->flags &= ~HOSTAPD_RATE_BASIC;
00154 HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL,
00155 "RATE[%d] rate=%d flags=0x%x\n",
00156 hapd->iface->num_rates, rate->rate, rate->flags);
00157 hapd->iface->num_rates++;
00158 }
00159
00160 if (hapd->iface->num_rates == 0 || num_basic_rates == 0) {
00161 printf("No rates remaining in supported/basic rate sets "
00162 "(%d,%d).\n", hapd->iface->num_rates, num_basic_rates);
00163 return -1;
00164 }
00165
00166 return 0;
00167 }
00168
00169
00170 static void select_hw_mode_start(void *eloop_data, void *user_ctx);
00171 static void select_hw_mode2_handler(void *eloop_data, void *user_ctx);
00172
00180 static int select_hw_mode_finalize(struct hostapd_iface *iface, int status)
00181 {
00182 hostapd_iface_cb cb;
00183
00184 if (!iface->hw_mode_sel_cb)
00185 return -1;
00186
00187 eloop_cancel_timeout(select_hw_mode_start, iface, NULL);
00188 eloop_cancel_timeout(select_hw_mode2_handler, iface, NULL);
00189
00190 cb = iface->hw_mode_sel_cb;
00191
00192 iface->hw_mode_sel_cb = NULL;
00193
00194 cb(iface, status);
00195
00196 return 0;
00197 }
00198
00199
00208 static void select_hw_mode2(struct hostapd_iface *iface, int status)
00209 {
00210 int ret = status;
00211 if (ret)
00212 goto fail;
00213
00214 if (iface->current_mode == NULL) {
00215 hostapd_logger(iface->bss[0], NULL, HOSTAPD_MODULE_IEEE80211,
00216 HOSTAPD_LEVEL_WARNING,
00217 "Hardware does not support configured channel");
00218 ret = -1;
00219 goto fail;
00220 }
00221
00222 if (hostapd_prepare_rates(iface->bss[0], iface->current_mode)) {
00223 printf("Failed to prepare rates table.\n");
00224 hostapd_logger(iface->bss[0], NULL, HOSTAPD_MODULE_IEEE80211,
00225 HOSTAPD_LEVEL_WARNING,
00226 "Failed to prepare rates table.");
00227 ret = -1;
00228 goto fail;
00229 }
00230
00231 ret = hostapd_passive_scan(iface->bss[0], 0,
00232 iface->conf->passive_scan_mode,
00233 iface->conf->passive_scan_interval,
00234 iface->conf->passive_scan_listen,
00235 NULL, NULL);
00236 if (ret) {
00237 printf("Could not set passive scanning: %s\n", strerror(ret));
00238 ret = 0;
00239 }
00240
00241 fail:
00242 select_hw_mode_finalize(iface, ret);
00243 }
00244
00245
00252 static void select_hw_mode2_handler(void *eloop_data, void *user_ctx)
00253 {
00254 struct hostapd_iface *iface = eloop_data;
00255
00256 select_hw_mode2(iface, 0);
00257 }
00258
00259
00270 static int select_hw_mode1(struct hostapd_iface *iface)
00271 {
00272 int i, j, ok;
00273
00274 if (iface->num_hw_features < 1)
00275 return -1;
00276
00277 iface->current_mode = NULL;
00278 for (i = 0; i < iface->num_hw_features; i++) {
00279 struct hostapd_hw_modes *mode = &iface->hw_features[i];
00280 if (mode->mode == (int) iface->conf->hw_mode) {
00281 iface->current_mode = mode;
00282 break;
00283 }
00284 }
00285
00286 if (iface->current_mode == NULL) {
00287 printf("Hardware does not support configured mode\n");
00288 hostapd_logger(iface->bss[0], NULL, HOSTAPD_MODULE_IEEE80211,
00289 HOSTAPD_LEVEL_WARNING,
00290 "Hardware does not support configured mode "
00291 "(%d)", (int) iface->conf->hw_mode);
00292 return -1;
00293 }
00294
00295 ok = 0;
00296 for (j = 0; j < iface->current_mode->num_channels; j++) {
00297 struct hostapd_channel_data *chan =
00298 &iface->current_mode->channels[j];
00299 if ((chan->flag & HOSTAPD_CHAN_W_SCAN) &&
00300 (chan->chan == iface->conf->channel)) {
00301 ok = 1;
00302 break;
00303 }
00304 }
00305 if (ok == 0 && iface->conf->channel != 0) {
00306 hostapd_logger(iface->bss[0], NULL,
00307 HOSTAPD_MODULE_IEEE80211,
00308 HOSTAPD_LEVEL_WARNING,
00309 "Configured channel (%d) not found from the "
00310 "channel list of current mode (%d) %s",
00311 iface->conf->channel,
00312 iface->current_mode->mode,
00313 hostapd_hw_mode_txt(iface->current_mode->mode));
00314 iface->current_mode = NULL;
00315 }
00316
00317
00318
00319
00320
00321 eloop_register_timeout(0, 0, select_hw_mode2_handler, iface, NULL);
00322 return 0;
00323 }
00324
00325
00335 static void select_hw_mode_start(void *eloop_data, void *user_ctx)
00336 {
00337 struct hostapd_iface *iface = (struct hostapd_iface *)eloop_data;
00338
00339 int ret;
00340
00341 ret = select_hw_mode1(iface);
00342 if (ret)
00343 select_hw_mode_finalize(iface, ret);
00344 }
00345
00346
00358 int hostapd_select_hw_mode_start(struct hostapd_iface *iface,
00359 hostapd_iface_cb cb)
00360 {
00361 if (iface->hw_mode_sel_cb) {
00362 wpa_printf(MSG_DEBUG,
00363 "%s: Hardware mode select already in progress.",
00364 iface->bss[0]->conf->iface);
00365 return -1;
00366 }
00367
00368 iface->hw_mode_sel_cb = cb;
00369
00370 eloop_register_timeout(0, 0, select_hw_mode_start, iface, NULL);
00371
00372 return 0;
00373 }
00374
00375
00383 int hostapd_select_hw_mode_stop(struct hostapd_iface *iface)
00384 {
00385 return select_hw_mode_finalize(iface, -1);
00386 }
00387
00388
00389 const char * hostapd_hw_mode_txt(int mode)
00390 {
00391 switch (mode) {
00392 case HOSTAPD_MODE_IEEE80211A:
00393 return "IEEE 802.11a";
00394 case HOSTAPD_MODE_IEEE80211B:
00395 return "IEEE 802.11b";
00396 case HOSTAPD_MODE_IEEE80211G:
00397 return "IEEE 802.11g";
00398 default:
00399 return "UNKNOWN";
00400 }
00401 }
00402
00403
00404 int hostapd_hw_get_freq(struct hostapd_data *hapd, int chan)
00405 {
00406 int i;
00407
00408 if (!hapd->iface->current_mode)
00409 return 0;
00410
00411 for (i = 0; i < hapd->iface->current_mode->num_channels; i++) {
00412 struct hostapd_channel_data *ch =
00413 &hapd->iface->current_mode->channels[i];
00414 if (ch->chan == chan)
00415 return ch->freq;
00416 }
00417
00418 return 0;
00419 }
00420
00421
00422 int hostapd_hw_get_channel(struct hostapd_data *hapd, int freq)
00423 {
00424 int i;
00425
00426 if (!hapd->iface->current_mode)
00427 return 0;
00428
00429 for (i = 0; i < hapd->iface->current_mode->num_channels; i++) {
00430 struct hostapd_channel_data *ch =
00431 &hapd->iface->current_mode->channels[i];
00432 if (ch->freq == freq)
00433 return ch->chan;
00434 }
00435
00436 return 0;
00437 }
00438