00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015 #ifndef EXPORT_SYMTAB
00016 #define EXPORT_SYMTAB
00017 #endif
00018
00019 #include <linux/config.h>
00020 #include <linux/version.h>
00021 #include <linux/module.h>
00022 #include <linux/init.h>
00023 #include <linux/slab.h>
00024 #include <linux/proc_fs.h>
00025 #include <linux/if_arp.h>
00026 #include <linux/delay.h>
00027 #include <linux/random.h>
00028 #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,44))
00029 #include <linux/tqueue.h>
00030 #else
00031 #include <linux/workqueue.h>
00032 #endif
00033 #include <linux/kmod.h>
00034 #include <linux/rtnetlink.h>
00035 #include "hostap_wext.h"
00036 #include <asm/uaccess.h>
00037
00038 #include "hostap_wlan.h"
00039 #include "hostap_80211.h"
00040 #include "hostap_ap.h"
00041 #include "hostap.h"
00042 #include "hostap_crypt.h"
00043
00044 MODULE_AUTHOR("Jouni Malinen");
00045 MODULE_DESCRIPTION("Host AP common routines");
00046 MODULE_LICENSE("GPL");
00047
00048 #ifndef HOSTAP_CRYPT_MODULE
00049
00050 #include "hostap_crypt.c"
00051 #else
00052 #define hostap_crypto_init()
00053 #define hostap_crypto_deinit()
00054 #endif
00055
00056 #define TX_TIMEOUT (2 * HZ)
00057
00058 #define PRISM2_MAX_FRAME_SIZE 2304
00059 #define PRISM2_MIN_MTU 256
00060
00061 #define PRISM2_MAX_MTU (PRISM2_MAX_FRAME_SIZE - (6 + 8 ))
00062
00063
00064
00065 static int prism2_wds_add(local_info_t *local, u8 *remote_addr,
00066 int rtnl_locked);
00067 static int prism2_wds_del(local_info_t *local, u8 *remote_addr,
00068 int rtnl_locked, int do_not_remove);
00069
00070
00071 #ifdef WIRELESS_EXT
00072 static int prism2_ap_get_sta_qual(local_info_t *local, struct sockaddr addr[],
00073 struct iw_quality qual[], int buf_size,
00074 int aplist);
00075 #if WIRELESS_EXT > 13
00076 static int prism2_ap_translate_scan(struct net_device *dev, char *buffer);
00077 #endif
00078 #endif
00079 static int prism2_hostapd(struct ap_data *ap,
00080 struct prism2_hostapd_param *param);
00081 static void * ap_crypt_get_ptrs(struct ap_data *ap, u8 *addr, int permanent,
00082 struct prism2_crypt_data ***crypt);
00083 static void ap_control_kickall(struct ap_data *ap);
00084 #ifndef PRISM2_NO_KERNEL_IEEE80211_MGMT
00085 static int ap_control_add_mac(struct mac_restrictions *mac_restrictions,
00086 u8 *mac);
00087 static int ap_control_del_mac(struct mac_restrictions *mac_restrictions,
00088 u8 *mac);
00089 static void ap_control_flush_macs(struct mac_restrictions *mac_restrictions);
00090 static int ap_control_kick_mac(struct ap_data *ap, struct net_device *dev,
00091 u8 *mac);
00092 #endif
00093
00094
00095 #ifdef WIRELESS_EXT
00096 static const long freq_list[] = { 2412, 2417, 2422, 2427, 2432, 2437, 2442,
00097 2447, 2452, 2457, 2462, 2467, 2472, 2484 };
00098 #define FREQ_COUNT (sizeof(freq_list) / sizeof(freq_list[0]))
00099 #endif
00100
00101
00102
00103
00104 static unsigned char rfc1042_header[] =
00105 { 0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00 };
00106
00107 static unsigned char bridge_tunnel_header[] =
00108 { 0xaa, 0xaa, 0x03, 0x00, 0x00, 0xf8 };
00109
00110
00111
00112
00113 #include "hostap_ap.c"
00114 #include "hostap_info.c"
00115 #include "hostap_ioctl.c"
00116 #include "hostap_proc.c"
00117 #include "hostap_80211_rx.c"
00118
00119
00120 struct net_device * hostap_add_interface(struct local_info *local,
00121 int type, int rtnl_locked,
00122 const char *name)
00123 {
00124 struct net_device *dev, *mdev;
00125 struct hostap_interface *iface;
00126 int ret;
00127
00128 dev = alloc_etherdev(sizeof(struct hostap_interface));
00129 if (dev == NULL)
00130 return NULL;
00131
00132 iface = dev->priv;
00133 iface->dev = dev;
00134 iface->local = local;
00135 iface->type = type;
00136 #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0))
00137 dev->name = iface->name;
00138 #endif
00139 list_add(&iface->list, &local->hostap_interfaces);
00140
00141 mdev = local->dev;
00142 memcpy(dev->dev_addr, mdev->dev_addr, ETH_ALEN);
00143 dev->base_addr = mdev->base_addr;
00144 dev->irq = mdev->irq;
00145 dev->mem_start = mdev->mem_start;
00146 dev->mem_end = mdev->mem_end;
00147
00148 hostap_setup_dev(dev, local, 0);
00149 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0))
00150 dev->destructor = free_netdev;
00151 #elif (LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0))
00152
00153
00154
00155
00156 dev->features |= NETIF_F_DYNALLOC;
00157 #endif
00158
00159 sprintf(dev->name, "%s%s", mdev->name, name);
00160 if (!rtnl_locked)
00161 rtnl_lock();
00162
00163 ret = 0;
00164 if (strchr(dev->name, '%'))
00165 ret = dev_alloc_name(dev, dev->name);
00166
00167 if (ret >= 0)
00168 ret = register_netdevice(dev);
00169
00170 if (!rtnl_locked)
00171 rtnl_unlock();
00172
00173 if (ret < 0) {
00174 printk(KERN_WARNING "%s: failed to add new netdevice!\n",
00175 dev->name);
00176 free_netdev(dev);
00177 return NULL;
00178 }
00179
00180 printk(KERN_DEBUG "%s: registered netdevice %s\n",
00181 mdev->name, dev->name);
00182
00183 return dev;
00184 }
00185
00186
00187 void hostap_remove_interface(struct net_device *dev, int rtnl_locked,
00188 int remove_from_list)
00189 {
00190 if (!dev)
00191 return;
00192
00193 if (remove_from_list) {
00194 struct hostap_interface *iface;
00195 iface = dev->priv;
00196 list_del(&iface->list);
00197 }
00198 if (rtnl_locked)
00199 unregister_netdevice(dev);
00200 else
00201 unregister_netdev(dev);
00202
00203
00204
00205 #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0))
00206
00207
00208 free_netdev(dev);
00209 #endif
00210 }
00211
00212
00213 static inline int prism2_wds_special_addr(u8 *addr)
00214 {
00215 if (addr[0] || addr[1] || addr[2] || addr[3] || addr[4] || addr[5])
00216 return 0;
00217
00218 return 1;
00219 }
00220
00221
00222 static int prism2_wds_add(local_info_t *local, u8 *remote_addr,
00223 int rtnl_locked)
00224 {
00225 struct net_device *dev;
00226 struct list_head *ptr;
00227 struct hostap_interface *iface, *empty, *match;
00228 unsigned long flags;
00229
00230 empty = match = NULL;
00231 read_lock_irqsave(&local->iface_lock, flags);
00232 list_for_each(ptr, &local->hostap_interfaces) {
00233 iface = list_entry(ptr, struct hostap_interface, list);
00234 if (iface->type != HOSTAP_INTERFACE_WDS)
00235 continue;
00236
00237 if (prism2_wds_special_addr(iface->u.wds.remote_addr))
00238 empty = iface;
00239 else if (memcmp(iface->u.wds.remote_addr, remote_addr,
00240 ETH_ALEN) == 0) {
00241 match = iface;
00242 break;
00243 }
00244 }
00245 if (!match && empty) {
00246
00247 memcpy(empty->u.wds.remote_addr, remote_addr, ETH_ALEN);
00248 }
00249
00250 if (!match && empty) {
00251 read_unlock_irqrestore(&local->iface_lock, flags);
00252 printk(KERN_DEBUG "%s: using pre-allocated WDS netdevice %s\n",
00253 local->dev->name, empty->dev->name);
00254 return 0;
00255 }
00256 read_unlock_irqrestore(&local->iface_lock, flags);
00257
00258 if (!prism2_wds_special_addr(remote_addr)) {
00259 if (match)
00260 return -EEXIST;
00261 hostap_add_sta(local->ap, remote_addr);
00262 }
00263
00264 if (local->wds_connections >= local->wds_max_connections)
00265 return -ENOBUFS;
00266
00267
00268 if (strlen(local->dev->name) > IFNAMSIZ - 5) {
00269 printk(KERN_DEBUG "'%s' too long base device name\n",
00270 local->dev->name);
00271 return -EINVAL;
00272 }
00273
00274 dev = hostap_add_interface(local, HOSTAP_INTERFACE_WDS, rtnl_locked,
00275 "wds%d");
00276 if (dev == NULL)
00277 return -ENOMEM;
00278
00279 iface = dev->priv;
00280 memcpy(iface->u.wds.remote_addr, remote_addr, ETH_ALEN);
00281
00282 local->wds_connections++;
00283
00284 return 0;
00285 }
00286
00287
00288 static int prism2_wds_del(local_info_t *local, u8 *remote_addr,
00289 int rtnl_locked, int do_not_remove)
00290 {
00291 unsigned long flags;
00292 struct list_head *ptr;
00293 struct hostap_interface *iface, *selected = NULL;
00294
00295 write_lock_irqsave(&local->iface_lock, flags);
00296 list_for_each(ptr, &local->hostap_interfaces) {
00297 iface = list_entry(ptr, struct hostap_interface, list);
00298 if (iface->type != HOSTAP_INTERFACE_WDS)
00299 continue;
00300
00301 if (memcmp(iface->u.wds.remote_addr, remote_addr,
00302 ETH_ALEN) == 0) {
00303 selected = iface;
00304 break;
00305 }
00306 }
00307 if (selected && !do_not_remove)
00308 list_del(&selected->list);
00309 write_unlock_irqrestore(&local->iface_lock, flags);
00310
00311 if (selected) {
00312 if (do_not_remove)
00313 memset(selected->u.wds.remote_addr, 0, ETH_ALEN);
00314 else {
00315 hostap_remove_interface(selected->dev, rtnl_locked, 0);
00316 local->wds_connections--;
00317 }
00318 }
00319
00320 return selected ? 0 : -ENODEV;
00321 }
00322
00323
00324 u16 hostap_tx_callback_register(local_info_t *local,
00325 void (*func)(struct sk_buff *, int ok, void *),
00326 void *data)
00327 {
00328 unsigned long flags;
00329 struct hostap_tx_callback_info *entry;
00330
00331 entry = (struct hostap_tx_callback_info *) kmalloc(sizeof(*entry),
00332 GFP_ATOMIC);
00333 if (entry == NULL)
00334 return 0;
00335
00336 entry->func = func;
00337 entry->data = data;
00338
00339 spin_lock_irqsave(&local->lock, flags);
00340 entry->idx = local->tx_callback ? local->tx_callback->idx + 1 : 1;
00341 entry->next = local->tx_callback;
00342 local->tx_callback = entry;
00343 spin_unlock_irqrestore(&local->lock, flags);
00344
00345 return entry->idx;
00346 }
00347
00348
00349 int hostap_tx_callback_unregister(local_info_t *local, u16 idx)
00350 {
00351 unsigned long flags;
00352 struct hostap_tx_callback_info *cb, *prev = NULL;
00353
00354 spin_lock_irqsave(&local->lock, flags);
00355 cb = local->tx_callback;
00356 while (cb != NULL && cb->idx != idx) {
00357 prev = cb;
00358 cb = cb->next;
00359 }
00360 if (cb) {
00361 if (prev == NULL)
00362 local->tx_callback = cb->next;
00363 else
00364 prev->next = cb->next;
00365 kfree(cb);
00366 }
00367 spin_unlock_irqrestore(&local->lock, flags);
00368
00369 return cb ? 0 : -1;
00370 }
00371
00372
00373
00374 int hostap_set_word(struct net_device *dev, int rid, u16 val)
00375 {
00376 struct hostap_interface *iface = dev->priv;
00377 u16 tmp = cpu_to_le16(val);
00378 return iface->local->func->set_rid(dev, rid, &tmp, 2);
00379 }
00380
00381
00382 int hostap_set_string(struct net_device *dev, int rid, const char *val)
00383 {
00384 struct hostap_interface *iface = dev->priv;
00385 char buf[MAX_SSID_LEN + 2];
00386 int len;
00387
00388 len = strlen(val);
00389 if (len > MAX_SSID_LEN)
00390 return -1;
00391 memset(buf, 0, sizeof(buf));
00392 buf[0] = len;
00393 memcpy(buf + 2, val, len);
00394
00395 return iface->local->func->set_rid(dev, rid, &buf, MAX_SSID_LEN + 2);
00396 }
00397
00398
00399 u16 hostap_get_porttype(local_info_t *local)
00400 {
00401 if (local->iw_mode == IW_MODE_ADHOC && local->pseudo_adhoc)
00402 return HFA384X_PORTTYPE_PSEUDO_IBSS;
00403 if (local->iw_mode == IW_MODE_ADHOC)
00404 return HFA384X_PORTTYPE_IBSS;
00405 if (local->iw_mode == IW_MODE_INFRA)
00406 return HFA384X_PORTTYPE_BSS;
00407 if (local->iw_mode == IW_MODE_REPEAT)
00408 return HFA384X_PORTTYPE_WDS;
00409 if (local->iw_mode == IW_MODE_MONITOR)
00410 return HFA384X_PORTTYPE_PSEUDO_IBSS;
00411 return HFA384X_PORTTYPE_HOSTAP;
00412 }
00413
00414
00415 int hostap_set_encryption(local_info_t *local)
00416 {
00417 u16 val;
00418 int i, keylen, len, idx;
00419 char keybuf[WEP_KEY_LEN + 1];
00420 enum { NONE, WEP, OTHER } encrypt_type;
00421
00422 if (local->crypt == NULL || local->crypt->ops == NULL)
00423 encrypt_type = NONE;
00424 else if (strcmp(local->crypt->ops->name, "WEP") == 0)
00425 encrypt_type = WEP;
00426 else
00427 encrypt_type = OTHER;
00428
00429 if (local->func->get_rid(local->dev, HFA384X_RID_CNFWEPFLAGS, &val, 2,
00430 1) < 0) {
00431 printk(KERN_DEBUG "Could not read current WEP flags.\n");
00432 goto fail;
00433 }
00434 le16_to_cpus(&val);
00435
00436 if (encrypt_type != NONE)
00437 val |= HFA384X_WEPFLAGS_PRIVACYINVOKED;
00438 else
00439 val &= ~HFA384X_WEPFLAGS_PRIVACYINVOKED;
00440
00441 if (local->open_wep || encrypt_type == NONE ||
00442 (local->ieee_802_1x && local->host_decrypt))
00443 val &= ~HFA384X_WEPFLAGS_EXCLUDEUNENCRYPTED;
00444 else
00445 val |= HFA384X_WEPFLAGS_EXCLUDEUNENCRYPTED;
00446
00447 if (encrypt_type != NONE &&
00448 (encrypt_type == OTHER || local->host_encrypt))
00449 val |= HFA384X_WEPFLAGS_HOSTENCRYPT;
00450 else
00451 val &= ~HFA384X_WEPFLAGS_HOSTENCRYPT;
00452 if (encrypt_type != NONE &&
00453 (encrypt_type == OTHER || local->host_decrypt))
00454 val |= HFA384X_WEPFLAGS_HOSTDECRYPT;
00455 else
00456 val &= ~HFA384X_WEPFLAGS_HOSTDECRYPT;
00457
00458 if (hostap_set_word(local->dev, HFA384X_RID_CNFWEPFLAGS, val)) {
00459 printk(KERN_DEBUG "Could not write new WEP flags (0x%x)\n",
00460 val);
00461 goto fail;
00462 }
00463
00464 if (encrypt_type != WEP)
00465 return 0;
00466
00467
00468
00469 keylen = 6;
00470 idx = local->crypt->ops->get_key_idx(local->crypt->priv);
00471 len = local->crypt->ops->get_key(idx, keybuf, sizeof(keybuf),
00472 local->crypt->priv);
00473 if (idx >= 0 && idx < WEP_KEYS && len > 5)
00474 keylen = WEP_KEY_LEN + 1;
00475
00476 for (i = 0; i < WEP_KEYS; i++) {
00477 memset(keybuf, 0, sizeof(keybuf));
00478 (void) local->crypt->ops->get_key(i, keybuf, sizeof(keybuf),
00479 local->crypt->priv);
00480 if (local->func->set_rid(local->dev,
00481 HFA384X_RID_CNFDEFAULTKEY0 + i,
00482 keybuf, keylen)) {
00483 printk(KERN_DEBUG "Could not set key %d (len=%d)\n",
00484 i, keylen);
00485 goto fail;
00486 }
00487 }
00488 if (hostap_set_word(local->dev, HFA384X_RID_CNFWEPDEFAULTKEYID, idx)) {
00489 printk(KERN_DEBUG "Could not set default keyid %d\n", idx);
00490 goto fail;
00491 }
00492
00493 return 0;
00494
00495 fail:
00496 printk(KERN_DEBUG "%s: encryption setup failed\n", local->dev->name);
00497 return -1;
00498 }
00499
00500
00501 int hostap_set_antsel(local_info_t *local)
00502 {
00503 u16 val;
00504 int ret = 0;
00505
00506 if (local->antsel_tx != HOSTAP_ANTSEL_DO_NOT_TOUCH &&
00507 local->func->cmd(local->dev, HFA384X_CMDCODE_READMIF,
00508 HFA386X_CR_TX_CONFIGURE,
00509 NULL, &val) == 0) {
00510 val &= ~(BIT(2) | BIT(1));
00511 switch (local->antsel_tx) {
00512 case HOSTAP_ANTSEL_DIVERSITY:
00513 val |= BIT(1);
00514 break;
00515 case HOSTAP_ANTSEL_LOW:
00516 break;
00517 case HOSTAP_ANTSEL_HIGH:
00518 val |= BIT(2);
00519 break;
00520 }
00521
00522 if (local->func->cmd(local->dev, HFA384X_CMDCODE_WRITEMIF,
00523 HFA386X_CR_TX_CONFIGURE, &val, NULL)) {
00524 printk(KERN_INFO "%s: setting TX AntSel failed\n",
00525 local->dev->name);
00526 ret = -1;
00527 }
00528 }
00529
00530 if (local->antsel_rx != HOSTAP_ANTSEL_DO_NOT_TOUCH &&
00531 local->func->cmd(local->dev, HFA384X_CMDCODE_READMIF,
00532 HFA386X_CR_RX_CONFIGURE,
00533 NULL, &val) == 0) {
00534 val &= ~(BIT(1) | BIT(0));
00535 switch (local->antsel_rx) {
00536 case HOSTAP_ANTSEL_DIVERSITY:
00537 break;
00538 case HOSTAP_ANTSEL_LOW:
00539 val |= BIT(0);
00540 break;
00541 case HOSTAP_ANTSEL_HIGH:
00542 val |= BIT(0) | BIT(1);
00543 break;
00544 }
00545
00546 if (local->func->cmd(local->dev, HFA384X_CMDCODE_WRITEMIF,
00547 HFA386X_CR_RX_CONFIGURE, &val, NULL)) {
00548 printk(KERN_INFO "%s: setting RX AntSel failed\n",
00549 local->dev->name);
00550 ret = -1;
00551 }
00552 }
00553
00554 return ret;
00555 }
00556
00557
00558 int hostap_set_roaming(local_info_t *local)
00559 {
00560 u16 val;
00561
00562 switch (local->host_roaming) {
00563 case 1:
00564 val = HFA384X_ROAMING_HOST;
00565 break;
00566 case 2:
00567 val = HFA384X_ROAMING_DISABLED;
00568 break;
00569 case 0:
00570 default:
00571 val = HFA384X_ROAMING_FIRMWARE;
00572 break;
00573 }
00574
00575 return hostap_set_word(local->dev, HFA384X_RID_CNFROAMINGMODE, val);
00576 }
00577
00578
00579 int hostap_set_auth_algs(local_info_t *local)
00580 {
00581 int val = local->auth_algs;
00582
00583
00584
00585
00586
00587 if (local->sta_fw_ver < PRISM2_FW_VER(0,7,0) &&
00588 val != PRISM2_AUTH_OPEN && val != PRISM2_AUTH_SHARED_KEY)
00589 val = PRISM2_AUTH_OPEN;
00590
00591 if (hostap_set_word(local->dev, HFA384X_RID_CNFAUTHENTICATION, val)) {
00592 printk(KERN_INFO "%s: cnfAuthentication setting to 0x%x "
00593 "failed\n", local->dev->name, local->auth_algs);
00594 return -EINVAL;
00595 }
00596
00597 return 0;
00598 }
00599
00600
00601 void hostap_dump_rx_header(const char *name, const struct hfa384x_rx_frame *rx)
00602 {
00603 u16 status, fc;
00604
00605 status = __le16_to_cpu(rx->status);
00606
00607 printk(KERN_DEBUG "%s: RX status=0x%04x (port=%d, type=%d, "
00608 "fcserr=%d) silence=%d signal=%d rate=%d rxflow=%d; "
00609 "jiffies=%ld\n",
00610 name, status, (status >> 8) & 0x07, status >> 13, status & 1,
00611 rx->silence, rx->signal, rx->rate, rx->rxflow, jiffies);
00612
00613 fc = __le16_to_cpu(rx->frame_control);
00614 printk(KERN_DEBUG " FC=0x%04x (type=%d:%d) dur=0x%04x seq=0x%04x "
00615 "data_len=%d%s%s\n",
00616 fc, WLAN_FC_GET_TYPE(fc), WLAN_FC_GET_STYPE(fc),
00617 __le16_to_cpu(rx->duration_id), __le16_to_cpu(rx->seq_ctrl),
00618 __le16_to_cpu(rx->data_len),
00619 fc & WLAN_FC_TODS ? " [ToDS]" : "",
00620 fc & WLAN_FC_FROMDS ? " [FromDS]" : "");
00621
00622 printk(KERN_DEBUG " A1=" MACSTR " A2=" MACSTR " A3=" MACSTR " A4="
00623 MACSTR "\n",
00624 MAC2STR(rx->addr1), MAC2STR(rx->addr2), MAC2STR(rx->addr3),
00625 MAC2STR(rx->addr4));
00626
00627 printk(KERN_DEBUG " dst=" MACSTR " src=" MACSTR " len=%d\n",
00628 MAC2STR(rx->dst_addr), MAC2STR(rx->src_addr),
00629 __be16_to_cpu(rx->len));
00630 }
00631
00632
00633 void hostap_dump_tx_header(const char *name, const struct hfa384x_tx_frame *tx)
00634 {
00635 u16 fc;
00636
00637 printk(KERN_DEBUG "%s: TX status=0x%04x retry_count=%d tx_rate=%d "
00638 "tx_control=0x%04x; jiffies=%ld\n",
00639 name, __le16_to_cpu(tx->status), tx->retry_count, tx->tx_rate,
00640 __le16_to_cpu(tx->tx_control), jiffies);
00641
00642 fc = __le16_to_cpu(tx->frame_control);
00643 printk(KERN_DEBUG " FC=0x%04x (type=%d:%d) dur=0x%04x seq=0x%04x "
00644 "data_len=%d%s%s\n",
00645 fc, WLAN_FC_GET_TYPE(fc), WLAN_FC_GET_STYPE(fc),
00646 __le16_to_cpu(tx->duration_id), __le16_to_cpu(tx->seq_ctrl),
00647 __le16_to_cpu(tx->data_len),
00648 fc & WLAN_FC_TODS ? " [ToDS]" : "",
00649 fc & WLAN_FC_FROMDS ? " [FromDS]" : "");
00650
00651 printk(KERN_DEBUG " A1=" MACSTR " A2=" MACSTR " A3=" MACSTR " A4="
00652 MACSTR "\n",
00653 MAC2STR(tx->addr1), MAC2STR(tx->addr2), MAC2STR(tx->addr3),
00654 MAC2STR(tx->addr4));
00655
00656 printk(KERN_DEBUG " dst=" MACSTR " src=" MACSTR " len=%d\n",
00657 MAC2STR(tx->dst_addr), MAC2STR(tx->src_addr),
00658 __be16_to_cpu(tx->len));
00659 }
00660
00661
00662
00663
00664
00665 void hostap_netif_wake_queues(struct net_device *dev)
00666 {
00667 struct hostap_interface *iface = dev->priv;
00668 local_info_t *local = iface->local;
00669 struct list_head *ptr;
00670 unsigned long flags;
00671
00672 read_lock_irqsave(&local->iface_lock, flags);
00673 list_for_each(ptr, &local->hostap_interfaces) {
00674 iface = list_entry(ptr, struct hostap_interface, list);
00675 netif_wake_queue(iface->dev);
00676 }
00677 read_unlock_irqrestore(&local->iface_lock, flags);
00678 }
00679
00680
00681
00682 void hostap_netif_stop_queues(struct net_device *dev)
00683 {
00684 struct hostap_interface *iface = dev->priv;
00685 local_info_t *local = iface->local;
00686 struct list_head *ptr;
00687 unsigned long flags;
00688
00689 read_lock_irqsave(&local->iface_lock, flags);
00690 list_for_each(ptr, &local->hostap_interfaces) {
00691 iface = list_entry(ptr, struct hostap_interface, list);
00692 netif_stop_queue(iface->dev);
00693 }
00694 read_unlock_irqrestore(&local->iface_lock, flags);
00695 }
00696
00697
00698 int hostap_80211_header_parse(struct sk_buff *skb, unsigned char *haddr)
00699 {
00700 memcpy(haddr, skb->mac.raw + 10, ETH_ALEN);
00701 return ETH_ALEN;
00702 }
00703
00704
00705 int hostap_80211_prism_header_parse(struct sk_buff *skb, unsigned char *haddr)
00706 {
00707 if (*(u32 *)skb->mac.raw == LWNG_CAP_DID_BASE) {
00708 memcpy(haddr, skb->mac.raw +
00709 sizeof(struct linux_wlan_ng_prism_hdr) + 10,
00710 ETH_ALEN);
00711 } else {
00712 memcpy(haddr, skb->mac.raw +
00713 sizeof(struct linux_wlan_ng_cap_hdr) + 10,
00714 ETH_ALEN);
00715 }
00716 return ETH_ALEN;
00717 }
00718
00719
00720 int hostap_80211_get_hdrlen(u16 fc)
00721 {
00722 int hdrlen = 24;
00723
00724 switch (WLAN_FC_GET_TYPE(fc)) {
00725 case WLAN_FC_TYPE_DATA:
00726 if ((fc & WLAN_FC_FROMDS) && (fc & WLAN_FC_TODS))
00727 hdrlen = 30;
00728 break;
00729 case WLAN_FC_TYPE_CTRL:
00730 switch (WLAN_FC_GET_STYPE(fc)) {
00731 case WLAN_FC_STYPE_CTS:
00732 case WLAN_FC_STYPE_ACK:
00733 hdrlen = 10;
00734 break;
00735 default:
00736 hdrlen = 16;
00737 break;
00738 }
00739 break;
00740 }
00741
00742 return hdrlen;
00743 }
00744
00745
00746 struct net_device_stats *hostap_get_stats(struct net_device *dev)
00747 {
00748 struct hostap_interface *iface = dev->priv;
00749 return &iface->stats;
00750 }
00751
00752
00753 static int prism2_close(struct net_device *dev)
00754 {
00755 struct hostap_interface *iface = dev->priv;
00756 local_info_t *local = iface->local;
00757
00758 PDEBUG(DEBUG_FLOW, "%s: prism2_close\n", dev->name);
00759
00760 #ifndef PRISM2_NO_KERNEL_IEEE80211_MGMT
00761 if (!local->hostapd && dev == local->dev &&
00762 (!local->func->card_present || local->func->card_present(local)) &&
00763 local->hw_ready && local->ap && local->iw_mode == IW_MODE_MASTER)
00764 hostap_deauth_all_stas(dev, local->ap, 1);
00765 #endif
00766
00767 if (local->func->dev_close && local->func->dev_close(local))
00768 return 0;
00769
00770 if (local->disable_on_close) {
00771 local->func->hw_shutdown(dev, HOSTAP_HW_ENABLE_CMDCOMPL);
00772 }
00773
00774 if (netif_running(dev)) {
00775 netif_stop_queue(dev);
00776 netif_device_detach(dev);
00777 }
00778
00779 flush_scheduled_work();
00780
00781 #ifdef NEW_MODULE_CODE
00782 module_put(local->hw_module);
00783 #elif MODULE
00784 __MOD_DEC_USE_COUNT(local->hw_module);
00785 #endif
00786
00787 return 0;
00788 }
00789
00790
00791 static int prism2_open(struct net_device *dev)
00792 {
00793 struct hostap_interface *iface = dev->priv;
00794 local_info_t *local = iface->local;
00795
00796 PDEBUG(DEBUG_FLOW, "%s: prism2_open\n", dev->name);
00797
00798 if (local->func->dev_open && local->func->dev_open(local))
00799 return 1;
00800
00801 #ifdef NEW_MODULE_CODE
00802 if (!try_module_get(local->hw_module))
00803 return -ENODEV;
00804 #elif MODULE
00805 __MOD_INC_USE_COUNT(local->hw_module);
00806 #endif
00807
00808 if (!local->dev_enabled && local->func->hw_enable(dev, 1)) {
00809 printk(KERN_WARNING "%s: could not enable MAC port\n",
00810 dev->name);
00811 prism2_close(dev);
00812 return 1;
00813 }
00814 if (!local->dev_enabled)
00815 prism2_callback(local, PRISM2_CALLBACK_ENABLE);
00816 local->dev_enabled = 1;
00817
00818 netif_device_attach(dev);
00819 netif_start_queue(dev);
00820
00821 return 0;
00822 }
00823
00824
00825 #ifdef HAVE_SET_MAC_ADDR
00826 static int prism2_set_mac_address(struct net_device *dev, void *p)
00827 {
00828 struct hostap_interface *iface = dev->priv;
00829 local_info_t *local = iface->local;
00830 struct list_head *ptr;
00831 struct sockaddr *addr = p;
00832 unsigned long flags;
00833
00834 if (local->func->set_rid(dev, HFA384X_RID_CNFOWNMACADDR, addr->sa_data,
00835 ETH_ALEN) < 0 || local->func->reset_port(dev))
00836 return -EINVAL;
00837
00838 read_lock_irqsave(&local->iface_lock, flags);
00839 list_for_each(ptr, &local->hostap_interfaces) {
00840 iface = list_entry(ptr, struct hostap_interface, list);
00841 memcpy(iface->dev->dev_addr, addr->sa_data, ETH_ALEN);
00842 }
00843 read_unlock_irqrestore(&local->iface_lock, flags);
00844
00845 return 0;
00846 }
00847 #endif
00848
00849
00850
00851
00852 void hostap_set_multicast_list_queue(void *data)
00853 {
00854 struct net_device *dev = (struct net_device *) data;
00855 struct hostap_interface *iface = dev->priv;
00856 local_info_t *local = iface->local;
00857
00858 if (hostap_set_word(dev, HFA384X_RID_PROMISCUOUSMODE,
00859 local->is_promisc)) {
00860 printk(KERN_INFO "%s: %sabling promiscuous mode failed\n",
00861 dev->name, local->is_promisc ? "en" : "dis");
00862 }
00863
00864 #ifndef NEW_MODULE_CODE
00865 MOD_DEC_USE_COUNT;
00866 #endif
00867 }
00868
00869
00870 static void hostap_set_multicast_list(struct net_device *dev)
00871 {
00872 #if 0
00873
00874
00875
00876
00877 struct hostap_interface *iface = dev->priv;
00878 local_info_t *local = iface->local;
00879
00880 if ((dev->flags & IFF_ALLMULTI) || (dev->flags & IFF_PROMISC)) {
00881 local->is_promisc = 1;
00882 } else {
00883 local->is_promisc = 0;
00884 }
00885
00886 PRISM2_SCHEDULE_TASK(&local->set_multicast_list_queue);
00887 #endif
00888 }
00889
00890
00891 static int prism2_change_mtu(struct net_device *dev, int new_mtu)
00892 {
00893 if (new_mtu < PRISM2_MIN_MTU || new_mtu > PRISM2_MAX_MTU)
00894 return -EINVAL;
00895
00896 dev->mtu = new_mtu;
00897 return 0;
00898 }
00899
00900
00901 #ifdef HAVE_TX_TIMEOUT
00902 static void prism2_tx_timeout(struct net_device *dev)
00903 {
00904 struct hostap_interface *iface = dev->priv;
00905 local_info_t *local = iface->local;
00906 struct hfa384x_regs regs;
00907
00908 printk(KERN_WARNING "%s Tx timed out! Resetting card\n", dev->name);
00909 hostap_netif_stop_queues(dev);
00910
00911 local->func->read_regs(dev, ®s);
00912 printk(KERN_DEBUG "%s: CMD=%04x EVSTAT=%04x "
00913 "OFFSET0=%04x OFFSET1=%04x SWSUPPORT0=%04x\n",
00914 dev->name, regs.cmd, regs.evstat, regs.offset0, regs.offset1,
00915 regs.swsupport0);
00916
00917 local->func->schedule_reset(local);
00918 }
00919 #endif
00920
00921
00922 void hostap_setup_dev(struct net_device *dev, local_info_t *local,
00923 int main_dev)
00924 {
00925 ether_setup(dev);
00926
00927
00928 dev->get_stats = hostap_get_stats;
00929 #ifdef WIRELESS_EXT
00930 dev->get_wireless_stats = main_dev ? hostap_get_wireless_stats : NULL;
00931 #if WIRELESS_EXT > 12
00932 dev->wireless_handlers =
00933 (struct iw_handler_def *) &hostap_iw_handler_def;
00934 #endif
00935 #ifdef HAVE_PRIVATE_IOCTL
00936 dev->do_ioctl = main_dev ? hostap_ioctl : NULL;
00937 #endif
00938 #endif
00939 dev->open = prism2_open;
00940 dev->stop = prism2_close;
00941 if (local->func)
00942 dev->hard_start_xmit = local->func->tx;
00943 else
00944 printk(KERN_WARNING "hostap_setup_dev: local->func == NULL\n");
00945 #ifdef HAVE_SET_MAC_ADDR
00946 dev->set_mac_address = prism2_set_mac_address;
00947 #endif
00948 #ifdef HAVE_MULTICAST
00949 dev->set_multicast_list = hostap_set_multicast_list;
00950 #endif
00951 #ifdef HAVE_CHANGE_MTU
00952 dev->change_mtu = prism2_change_mtu;
00953 #endif
00954 #ifdef HAVE_TX_TIMEOUT
00955 dev->tx_timeout = prism2_tx_timeout;
00956 dev->watchdog_timeo = TX_TIMEOUT;
00957 #endif
00958
00959 dev->mtu = local->mtu;
00960
00961 netif_stop_queue(dev);
00962 }
00963
00964
00965 static int hostap_enable_hostapd(local_info_t *local, int rtnl_locked)
00966 {
00967 struct net_device *dev = local->dev;
00968
00969 if (local->apdev)
00970 return -EEXIST;
00971
00972 printk(KERN_DEBUG "%s: enabling hostapd mode\n", dev->name);
00973
00974 local->apdev = hostap_add_interface(local, HOSTAP_INTERFACE_AP,
00975 rtnl_locked, "ap");
00976 if (local->apdev == NULL)
00977 return -ENOMEM;
00978
00979 local->apdev->hard_start_xmit = local->func->tx_80211;
00980 local->apdev->type = ARPHRD_IEEE80211_PRISM;
00981 local->apdev->hard_header_parse = hostap_80211_header_parse;
00982
00983 local->stadev = hostap_add_interface(local, HOSTAP_INTERFACE_STA,
00984 rtnl_locked, "sta");
00985 if (local->stadev == NULL)
00986 return -ENOMEM;
00987
00988 return 0;
00989 }
00990
00991
00992 static int hostap_disable_hostapd(local_info_t *local, int rtnl_locked)
00993 {
00994 struct net_device *dev = local->dev;
00995
00996 printk(KERN_DEBUG "%s: disabling hostapd mode\n", dev->name);
00997
00998 hostap_remove_interface(local->apdev, rtnl_locked, 1);
00999 local->apdev = NULL;
01000
01001 hostap_remove_interface(local->stadev, rtnl_locked, 1);
01002 local->stadev = NULL;
01003
01004 return 0;
01005 }
01006
01007
01008 int hostap_set_hostapd(local_info_t *local, int val, int rtnl_locked)
01009 {
01010 if (val < 0 || val > 1)
01011 return -EINVAL;
01012
01013 if (local->hostapd == val)
01014 return 0;
01015
01016 local->hostapd = val;
01017
01018 if (val)
01019 return hostap_enable_hostapd(local, rtnl_locked);
01020 else
01021 return hostap_disable_hostapd(local, rtnl_locked);
01022 }
01023
01024
01025 struct proc_dir_entry *hostap_proc;
01026
01027 static int __init hostap_init(void)
01028 {
01029 hostap_crypto_init();
01030
01031 if (proc_net != NULL) {
01032 hostap_proc = proc_mkdir("hostap", proc_net);
01033 if (!hostap_proc)
01034 printk(KERN_WARNING "Failed to mkdir "
01035 "/proc/net/hostap\n");
01036 } else
01037 hostap_proc = NULL;
01038
01039 return 0;
01040 }
01041
01042
01043 static void __exit hostap_exit(void)
01044 {
01045 if (hostap_proc != NULL) {
01046 hostap_proc = NULL;
01047 remove_proc_entry("hostap", proc_net);
01048 }
01049
01050 hostap_crypto_deinit();
01051 }
01052
01053
01054 EXPORT_SYMBOL(hostap_set_word);
01055 EXPORT_SYMBOL(hostap_set_string);
01056 EXPORT_SYMBOL(hostap_get_porttype);
01057 EXPORT_SYMBOL(hostap_set_encryption);
01058 EXPORT_SYMBOL(hostap_set_antsel);
01059 EXPORT_SYMBOL(hostap_set_roaming);
01060 EXPORT_SYMBOL(hostap_set_auth_algs);
01061 EXPORT_SYMBOL(hostap_dump_rx_header);
01062 EXPORT_SYMBOL(hostap_dump_tx_header);
01063 EXPORT_SYMBOL(hostap_netif_wake_queues);
01064 EXPORT_SYMBOL(hostap_netif_stop_queues);
01065 EXPORT_SYMBOL(hostap_80211_header_parse);
01066 EXPORT_SYMBOL(hostap_80211_prism_header_parse);
01067 EXPORT_SYMBOL(hostap_80211_get_hdrlen);
01068 EXPORT_SYMBOL(hostap_get_stats);
01069 EXPORT_SYMBOL(hostap_setup_dev);
01070 EXPORT_SYMBOL(hostap_proc);
01071 EXPORT_SYMBOL(hostap_set_multicast_list_queue);
01072 EXPORT_SYMBOL(hostap_set_hostapd);
01073 EXPORT_SYMBOL(hostap_add_interface);
01074 EXPORT_SYMBOL(hostap_remove_interface);
01075
01076 module_init(hostap_init);
01077 module_exit(hostap_exit);