• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* src/p80211/p80211knetdev.c
2 *
3 * Linux Kernel net device interface
4 *
5 * Copyright (C) 1999 AbsoluteValue Systems, Inc.  All Rights Reserved.
6 * --------------------------------------------------------------------
7 *
8 * linux-wlan
9 *
10 *   The contents of this file are subject to the Mozilla Public
11 *   License Version 1.1 (the "License"); you may not use this file
12 *   except in compliance with the License. You may obtain a copy of
13 *   the License at http://www.mozilla.org/MPL/
14 *
15 *   Software distributed under the License is distributed on an "AS
16 *   IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
17 *   implied. See the License for the specific language governing
18 *   rights and limitations under the License.
19 *
20 *   Alternatively, the contents of this file may be used under the
21 *   terms of the GNU Public License version 2 (the "GPL"), in which
22 *   case the provisions of the GPL are applicable instead of the
23 *   above.  If you wish to allow the use of your version of this file
24 *   only under the terms of the GPL and not to allow others to use
25 *   your version of this file under the MPL, indicate your decision
26 *   by deleting the provisions above and replace them with the notice
27 *   and other provisions required by the GPL.  If you do not delete
28 *   the provisions above, a recipient may use your version of this
29 *   file under either the MPL or the GPL.
30 *
31 * --------------------------------------------------------------------
32 *
33 * Inquiries regarding the linux-wlan Open Source project can be
34 * made directly to:
35 *
36 * AbsoluteValue Systems Inc.
37 * info@linux-wlan.com
38 * http://www.linux-wlan.com
39 *
40 * --------------------------------------------------------------------
41 *
42 * Portions of the development of this software were funded by
43 * Intersil Corporation as part of PRISM(R) chipset product development.
44 *
45 * --------------------------------------------------------------------
46 *
47 * The functions required for a Linux network device are defined here.
48 *
49 * --------------------------------------------------------------------
50 */
51 
52 
53 /*================================================================*/
54 /* System Includes */
55 
56 
57 #include <linux/version.h>
58 
59 #include <linux/module.h>
60 #include <linux/kernel.h>
61 #include <linux/sched.h>
62 #include <linux/types.h>
63 #include <linux/skbuff.h>
64 #include <linux/slab.h>
65 #include <linux/proc_fs.h>
66 #include <linux/interrupt.h>
67 #include <linux/netdevice.h>
68 #include <linux/kmod.h>
69 #include <linux/if_arp.h>
70 #include <linux/wireless.h>
71 #include <linux/sockios.h>
72 #include <linux/etherdevice.h>
73 
74 #include <asm/bitops.h>
75 #include <asm/uaccess.h>
76 #include <asm/byteorder.h>
77 
78 #ifdef SIOCETHTOOL
79 #include <linux/ethtool.h>
80 #endif
81 
82 #include <net/iw_handler.h>
83 #include <net/net_namespace.h>
84 
85 /*================================================================*/
86 /* Project Includes */
87 
88 #include "wlan_compat.h"
89 #include "p80211types.h"
90 #include "p80211hdr.h"
91 #include "p80211conv.h"
92 #include "p80211mgmt.h"
93 #include "p80211msg.h"
94 #include "p80211netdev.h"
95 #include "p80211ioctl.h"
96 #include "p80211req.h"
97 #include "p80211metastruct.h"
98 #include "p80211metadef.h"
99 
100 /*================================================================*/
101 /* Local Constants */
102 
103 /*================================================================*/
104 /* Local Macros */
105 
106 
107 /*================================================================*/
108 /* Local Types */
109 
110 /*================================================================*/
111 /* Local Function Declarations */
112 
113 /* Support functions */
114 static void p80211netdev_rx_bh(unsigned long arg);
115 
116 /* netdevice method functions */
117 static int p80211knetdev_init( netdevice_t *netdev);
118 static struct net_device_stats* p80211knetdev_get_stats(netdevice_t *netdev);
119 static int p80211knetdev_open( netdevice_t *netdev);
120 static int p80211knetdev_stop( netdevice_t *netdev );
121 static int p80211knetdev_hard_start_xmit( struct sk_buff *skb, netdevice_t *netdev);
122 static void p80211knetdev_set_multicast_list(netdevice_t *dev);
123 static int p80211knetdev_do_ioctl(netdevice_t *dev, struct ifreq *ifr, int cmd);
124 static int p80211knetdev_set_mac_address(netdevice_t *dev, void *addr);
125 static void p80211knetdev_tx_timeout(netdevice_t *netdev);
126 static int p80211_rx_typedrop( wlandevice_t *wlandev, u16 fc);
127 
128 int wlan_watchdog = 5000;
129 module_param(wlan_watchdog, int, 0644);
130 MODULE_PARM_DESC(wlan_watchdog, "transmit timeout in milliseconds");
131 
132 int wlan_wext_write = 1;
133 module_param(wlan_wext_write, int, 0644);
134 MODULE_PARM_DESC(wlan_wext_write, "enable write wireless extensions");
135 
136 #ifdef WLAN_INCLUDE_DEBUG
137 int wlan_debug=0;
138 module_param(wlan_debug, int, 0644);
139 MODULE_PARM_DESC(wlan_debug, "p80211 debug level");
140 #endif
141 
142 /*================================================================*/
143 /* Function Definitions */
144 
145 /*----------------------------------------------------------------
146 * p80211knetdev_init
147 *
148 * Init method for a Linux netdevice.  Called in response to
149 * register_netdev.
150 *
151 * Arguments:
152 *	none
153 *
154 * Returns:
155 *	nothing
156 ----------------------------------------------------------------*/
p80211knetdev_init(netdevice_t * netdev)157 static int p80211knetdev_init( netdevice_t *netdev)
158 {
159 	DBFENTER;
160 	/* Called in response to register_netdev */
161 	/* This is usually the probe function, but the probe has */
162 	/* already been done by the MSD and the create_kdev */
163 	/* function.  All we do here is return success */
164 	DBFEXIT;
165 	return 0;
166 }
167 
168 
169 /*----------------------------------------------------------------
170 * p80211knetdev_get_stats
171 *
172 * Statistics retrieval for linux netdevices.  Here we're reporting
173 * the Linux i/f level statistics.  Hence, for the primary numbers,
174 * we don't want to report the numbers from the MIB.  Eventually,
175 * it might be useful to collect some of the error counters though.
176 *
177 * Arguments:
178 *	netdev		Linux netdevice
179 *
180 * Returns:
181 *	the address of the statistics structure
182 ----------------------------------------------------------------*/
183 static struct net_device_stats*
p80211knetdev_get_stats(netdevice_t * netdev)184 p80211knetdev_get_stats(netdevice_t *netdev)
185 {
186 	wlandevice_t	*wlandev = netdev->ml_priv;
187 	DBFENTER;
188 
189 	/* TODO: review the MIB stats for items that correspond to
190 		linux stats */
191 
192 	DBFEXIT;
193 	return &(wlandev->linux_stats);
194 }
195 
196 
197 /*----------------------------------------------------------------
198 * p80211knetdev_open
199 *
200 * Linux netdevice open method.  Following a successful call here,
201 * the device is supposed to be ready for tx and rx.  In our
202 * situation that may not be entirely true due to the state of the
203 * MAC below.
204 *
205 * Arguments:
206 *	netdev		Linux network device structure
207 *
208 * Returns:
209 *	zero on success, non-zero otherwise
210 ----------------------------------------------------------------*/
p80211knetdev_open(netdevice_t * netdev)211 static int p80211knetdev_open( netdevice_t *netdev )
212 {
213 	int 		result = 0; /* success */
214 	wlandevice_t	*wlandev = netdev->ml_priv;
215 
216 	DBFENTER;
217 
218 	/* Check to make sure the MSD is running */
219 	if ( wlandev->msdstate != WLAN_MSD_RUNNING ) {
220 		return -ENODEV;
221 	}
222 
223 	/* Tell the MSD to open */
224 	if ( wlandev->open != NULL) {
225 		result = wlandev->open(wlandev);
226 		if ( result == 0 ) {
227 			netif_start_queue(wlandev->netdev);
228 			wlandev->state = WLAN_DEVICE_OPEN;
229 		}
230 	} else {
231 		result = -EAGAIN;
232 	}
233 
234 	DBFEXIT;
235 	return result;
236 }
237 
238 
239 /*----------------------------------------------------------------
240 * p80211knetdev_stop
241 *
242 * Linux netdevice stop (close) method.  Following this call,
243 * no frames should go up or down through this interface.
244 *
245 * Arguments:
246 *	netdev		Linux network device structure
247 *
248 * Returns:
249 *	zero on success, non-zero otherwise
250 ----------------------------------------------------------------*/
p80211knetdev_stop(netdevice_t * netdev)251 static int p80211knetdev_stop( netdevice_t *netdev )
252 {
253 	int		result = 0;
254 	wlandevice_t	*wlandev = netdev->ml_priv;
255 
256 	DBFENTER;
257 
258 	if ( wlandev->close != NULL ) {
259 		result = wlandev->close(wlandev);
260 	}
261 
262 	netif_stop_queue(wlandev->netdev);
263 	wlandev->state = WLAN_DEVICE_CLOSED;
264 
265 	DBFEXIT;
266 	return result;
267 }
268 
269 /*----------------------------------------------------------------
270 * p80211netdev_rx
271 *
272 * Frame receive function called by the mac specific driver.
273 *
274 * Arguments:
275 *	wlandev		WLAN network device structure
276 *	skb		skbuff containing a full 802.11 frame.
277 * Returns:
278 *	nothing
279 * Side effects:
280 *
281 ----------------------------------------------------------------*/
282 void
p80211netdev_rx(wlandevice_t * wlandev,struct sk_buff * skb)283 p80211netdev_rx(wlandevice_t *wlandev, struct sk_buff *skb )
284 {
285 	DBFENTER;
286 
287 	/* Enqueue for post-irq processing */
288 	skb_queue_tail(&wlandev->nsd_rxq, skb);
289 
290 	tasklet_schedule(&wlandev->rx_bh);
291 
292         DBFEXIT;
293 	return;
294 }
295 
296 /*----------------------------------------------------------------
297 * p80211netdev_rx_bh
298 *
299 * Deferred processing of all received frames.
300 *
301 * Arguments:
302 *	wlandev		WLAN network device structure
303 *	skb		skbuff containing a full 802.11 frame.
304 * Returns:
305 *	nothing
306 * Side effects:
307 *
308 ----------------------------------------------------------------*/
p80211netdev_rx_bh(unsigned long arg)309 static void p80211netdev_rx_bh(unsigned long arg)
310 {
311 	wlandevice_t *wlandev = (wlandevice_t *) arg;
312 	struct sk_buff *skb = NULL;
313 	netdevice_t     *dev = wlandev->netdev;
314 	p80211_hdr_a3_t *hdr;
315 	u16 fc;
316 
317         DBFENTER;
318 
319 	/* Let's empty our our queue */
320 	while ( (skb = skb_dequeue(&wlandev->nsd_rxq)) ) {
321 		if (wlandev->state == WLAN_DEVICE_OPEN) {
322 
323 			if (dev->type != ARPHRD_ETHER) {
324 				/* RAW frame; we shouldn't convert it */
325 				// XXX Append the Prism Header here instead.
326 
327 				/* set up various data fields */
328 				skb->dev = dev;
329 				skb_reset_mac_header(skb);
330 				skb->ip_summed = CHECKSUM_NONE;
331 				skb->pkt_type = PACKET_OTHERHOST;
332 				skb->protocol = htons(ETH_P_80211_RAW);
333 				dev->last_rx = jiffies;
334 
335 				wlandev->linux_stats.rx_packets++;
336 				wlandev->linux_stats.rx_bytes += skb->len;
337 				netif_rx_ni(skb);
338 				continue;
339 			} else {
340 				hdr = (p80211_hdr_a3_t *)skb->data;
341 				fc = ieee2host16(hdr->fc);
342 				if (p80211_rx_typedrop(wlandev, fc)) {
343 					dev_kfree_skb(skb);
344 					continue;
345 				}
346 
347 				/* perform mcast filtering */
348 				if (wlandev->netdev->flags & IFF_ALLMULTI) {
349 					/* allow my local address through */
350 					if (memcmp(hdr->a1, wlandev->netdev->dev_addr, WLAN_ADDR_LEN) != 0) {
351 						/* but reject anything else that isn't multicast */
352 						if (!(hdr->a1[0] & 0x01)) {
353 							dev_kfree_skb(skb);
354 							continue;
355 						}
356 					}
357 				}
358 
359 				if ( skb_p80211_to_ether(wlandev, wlandev->ethconv, skb) == 0 ) {
360 					skb->dev->last_rx = jiffies;
361 					wlandev->linux_stats.rx_packets++;
362 					wlandev->linux_stats.rx_bytes += skb->len;
363 					netif_rx_ni(skb);
364 					continue;
365 				}
366 				WLAN_LOG_DEBUG(1, "p80211_to_ether failed.\n");
367 			}
368 		}
369 		dev_kfree_skb(skb);
370 	}
371 
372         DBFEXIT;
373 }
374 
375 
376 /*----------------------------------------------------------------
377 * p80211knetdev_hard_start_xmit
378 *
379 * Linux netdevice method for transmitting a frame.
380 *
381 * Arguments:
382 *	skb	Linux sk_buff containing the frame.
383 *	netdev	Linux netdevice.
384 *
385 * Side effects:
386 *	If the lower layers report that buffers are full. netdev->tbusy
387 *	will be set to prevent higher layers from sending more traffic.
388 *
389 *	Note: If this function returns non-zero, higher layers retain
390 *	      ownership of the skb.
391 *
392 * Returns:
393 *	zero on success, non-zero on failure.
394 ----------------------------------------------------------------*/
p80211knetdev_hard_start_xmit(struct sk_buff * skb,netdevice_t * netdev)395 static int p80211knetdev_hard_start_xmit( struct sk_buff *skb, netdevice_t *netdev)
396 {
397 	int		result = 0;
398 	int		txresult = -1;
399 	wlandevice_t	*wlandev = netdev->ml_priv;
400 	p80211_hdr_t    p80211_hdr;
401 	p80211_metawep_t p80211_wep;
402 
403 	DBFENTER;
404 
405 	if (skb == NULL) {
406 		return 0;
407 	}
408 
409         if (wlandev->state != WLAN_DEVICE_OPEN) {
410 		result = 1;
411 		goto failed;
412 	}
413 
414 	memset(&p80211_hdr, 0, sizeof(p80211_hdr_t));
415 	memset(&p80211_wep, 0, sizeof(p80211_metawep_t));
416 
417 	if ( netif_queue_stopped(netdev) ) {
418 		WLAN_LOG_DEBUG(1, "called when queue stopped.\n");
419 		result = 1;
420 		goto failed;
421 	}
422 
423 	netif_stop_queue(netdev);
424 
425 	/* Check to see that a valid mode is set */
426 	switch( wlandev->macmode ) {
427 	case WLAN_MACMODE_IBSS_STA:
428 	case WLAN_MACMODE_ESS_STA:
429 	case WLAN_MACMODE_ESS_AP:
430 		break;
431 	default:
432 		/* Mode isn't set yet, just drop the frame
433 		 * and return success .
434 		 * TODO: we need a saner way to handle this
435 		 */
436 		if(skb->protocol != ETH_P_80211_RAW) {
437 			netif_start_queue(wlandev->netdev);
438 			WLAN_LOG_NOTICE(
439 				"Tx attempt prior to association, frame dropped.\n");
440 			wlandev->linux_stats.tx_dropped++;
441 			result = 0;
442 			goto failed;
443 		}
444 		break;
445 	}
446 
447 	/* Check for raw transmits */
448 	if(skb->protocol == ETH_P_80211_RAW) {
449 		if (!capable(CAP_NET_ADMIN)) {
450 			result = 1;
451 			goto failed;
452 		}
453 		/* move the header over */
454 		memcpy(&p80211_hdr, skb->data, sizeof(p80211_hdr_t));
455 		skb_pull(skb, sizeof(p80211_hdr_t));
456 	} else {
457 		if ( skb_ether_to_p80211(wlandev, wlandev->ethconv, skb, &p80211_hdr, &p80211_wep) != 0 ) {
458 			/* convert failed */
459 			WLAN_LOG_DEBUG(1, "ether_to_80211(%d) failed.\n",
460 					wlandev->ethconv);
461 			result = 1;
462 			goto failed;
463 		}
464 	}
465 	if ( wlandev->txframe == NULL ) {
466 		result = 1;
467 		goto failed;
468 	}
469 
470 	netdev->trans_start = jiffies;
471 
472 	wlandev->linux_stats.tx_packets++;
473 	/* count only the packet payload */
474 	wlandev->linux_stats.tx_bytes += skb->len;
475 
476 	txresult = wlandev->txframe(wlandev, skb, &p80211_hdr, &p80211_wep);
477 
478 	if ( txresult == 0) {
479 		/* success and more buf */
480 		/* avail, re: hw_txdata */
481 		netif_wake_queue(wlandev->netdev);
482 		result = 0;
483 	} else if ( txresult == 1 ) {
484 		/* success, no more avail */
485 		WLAN_LOG_DEBUG(3, "txframe success, no more bufs\n");
486 		/* netdev->tbusy = 1;  don't set here, irqhdlr */
487 		/*   may have already cleared it */
488 		result = 0;
489 	} else if ( txresult == 2 ) {
490 		/* alloc failure, drop frame */
491 		WLAN_LOG_DEBUG(3, "txframe returned alloc_fail\n");
492 		result = 1;
493 	} else {
494 		/* buffer full or queue busy, drop frame. */
495 		WLAN_LOG_DEBUG(3, "txframe returned full or busy\n");
496 		result = 1;
497 	}
498 
499  failed:
500 	/* Free up the WEP buffer if it's not the same as the skb */
501 	if ((p80211_wep.data) && (p80211_wep.data != skb->data))
502 		kfree(p80211_wep.data);
503 
504 	/* we always free the skb here, never in a lower level. */
505 	if (!result)
506 		dev_kfree_skb(skb);
507 
508 	DBFEXIT;
509 	return result;
510 }
511 
512 
513 /*----------------------------------------------------------------
514 * p80211knetdev_set_multicast_list
515 *
516 * Called from higher lavers whenever there's a need to set/clear
517 * promiscuous mode or rewrite the multicast list.
518 *
519 * Arguments:
520 *	none
521 *
522 * Returns:
523 *	nothing
524 ----------------------------------------------------------------*/
p80211knetdev_set_multicast_list(netdevice_t * dev)525 static void p80211knetdev_set_multicast_list(netdevice_t *dev)
526 {
527 	wlandevice_t	*wlandev = dev->ml_priv;
528 
529 	DBFENTER;
530 
531 	/* TODO:  real multicast support as well */
532 
533 	if (wlandev->set_multicast_list)
534 		wlandev->set_multicast_list(wlandev, dev);
535 
536 	DBFEXIT;
537 }
538 
539 #ifdef SIOCETHTOOL
540 
p80211netdev_ethtool(wlandevice_t * wlandev,void __user * useraddr)541 static int p80211netdev_ethtool(wlandevice_t *wlandev, void __user *useraddr)
542 {
543 	u32 ethcmd;
544 	struct ethtool_drvinfo info;
545 	struct ethtool_value edata;
546 
547 	memset(&info, 0, sizeof(info));
548 	memset(&edata, 0, sizeof(edata));
549 
550 	if (copy_from_user(&ethcmd, useraddr, sizeof(ethcmd)))
551 		return -EFAULT;
552 
553 	switch (ethcmd) {
554 	case ETHTOOL_GDRVINFO:
555 		info.cmd = ethcmd;
556 		snprintf(info.driver, sizeof(info.driver), "p80211_%s",
557 			 wlandev->nsdname);
558 		snprintf(info.version, sizeof(info.version), "%s",
559 			 WLAN_RELEASE);
560 
561 		// info.fw_version
562 		// info.bus_info
563 
564 		if (copy_to_user(useraddr, &info, sizeof(info)))
565 			return -EFAULT;
566 		return 0;
567 #ifdef ETHTOOL_GLINK
568 	case ETHTOOL_GLINK:
569 		edata.cmd = ethcmd;
570 
571 		if (wlandev->linkstatus &&
572 		    (wlandev->macmode != WLAN_MACMODE_NONE)) {
573 			edata.data = 1;
574 		} else {
575 			edata.data = 0;
576 		}
577 
578 		if (copy_to_user(useraddr, &edata, sizeof(edata)))
579                         return -EFAULT;
580 		return 0;
581 	}
582 #endif
583 
584 	return -EOPNOTSUPP;
585 }
586 
587 #endif
588 
589 /*----------------------------------------------------------------
590 * p80211knetdev_do_ioctl
591 *
592 * Handle an ioctl call on one of our devices.  Everything Linux
593 * ioctl specific is done here.  Then we pass the contents of the
594 * ifr->data to the request message handler.
595 *
596 * Arguments:
597 *	dev	Linux kernel netdevice
598 *	ifr	Our private ioctl request structure, typed for the
599 *		generic struct ifreq so we can use ptr to func
600 *		w/o cast.
601 *
602 * Returns:
603 *	zero on success, a negative errno on failure.  Possible values:
604 *		-ENETDOWN Device isn't up.
605 *		-EBUSY	cmd already in progress
606 *		-ETIME	p80211 cmd timed out (MSD may have its own timers)
607 *		-EFAULT memory fault copying msg from user buffer
608 *		-ENOMEM unable to allocate kernel msg buffer
609 *		-ENOSYS	bad magic, it the cmd really for us?
610 *		-EintR	sleeping on cmd, awakened by signal, cmd cancelled.
611 *
612 * Call Context:
613 *	Process thread (ioctl caller).  TODO: SMP support may require
614 *	locks.
615 ----------------------------------------------------------------*/
p80211knetdev_do_ioctl(netdevice_t * dev,struct ifreq * ifr,int cmd)616 static int p80211knetdev_do_ioctl(netdevice_t *dev, struct ifreq *ifr, int cmd)
617 {
618 	int			result = 0;
619 	p80211ioctl_req_t	*req = (p80211ioctl_req_t*)ifr;
620 	wlandevice_t		*wlandev = dev->ml_priv;
621 	u8			*msgbuf;
622 	DBFENTER;
623 
624 	WLAN_LOG_DEBUG(2, "rx'd ioctl, cmd=%d, len=%d\n", cmd, req->len);
625 
626 #ifdef SIOCETHTOOL
627 	if (cmd == SIOCETHTOOL) {
628 		result = p80211netdev_ethtool(wlandev, (void __user *) ifr->ifr_data);
629 		goto bail;
630 	}
631 #endif
632 
633 	/* Test the magic, assume ifr is good if it's there */
634 	if ( req->magic != P80211_IOCTL_MAGIC ) {
635 		result = -ENOSYS;
636 		goto bail;
637 	}
638 
639 	if ( cmd == P80211_IFTEST ) {
640 		result = 0;
641 		goto bail;
642 	} else if ( cmd != P80211_IFREQ ) {
643 		result = -ENOSYS;
644 		goto bail;
645 	}
646 
647 	/* Allocate a buf of size req->len */
648 	if ((msgbuf = kmalloc( req->len, GFP_KERNEL))) {
649 		if ( copy_from_user( msgbuf, (void __user *) req->data, req->len) ) {
650 			result = -EFAULT;
651 		} else {
652 			result = p80211req_dorequest( wlandev, msgbuf);
653 		}
654 
655 		if ( result == 0 ) {
656 			if ( copy_to_user( (void __user *) req->data, msgbuf, req->len)) {
657 				result = -EFAULT;
658 			}
659 		}
660 		kfree(msgbuf);
661 	} else {
662 		result = -ENOMEM;
663 	}
664 bail:
665 	DBFEXIT;
666 
667 	return result; /* If allocate,copyfrom or copyto fails, return errno */
668 }
669 
670 /*----------------------------------------------------------------
671 * p80211knetdev_set_mac_address
672 *
673 * Handles the ioctl for changing the MACAddress of a netdevice
674 *
675 * references: linux/netdevice.h and drivers/net/net_init.c
676 *
677 * NOTE: [MSM] We only prevent address changes when the netdev is
678 * up.  We don't control anything based on dot11 state.  If the
679 * address is changed on a STA that's currently associated, you
680 * will probably lose the ability to send and receive data frames.
681 * Just be aware.  Therefore, this should usually only be done
682 * prior to scan/join/auth/assoc.
683 *
684 * Arguments:
685 *	dev	netdevice struct
686 *	addr	the new MACAddress (a struct)
687 *
688 * Returns:
689 *	zero on success, a negative errno on failure.  Possible values:
690 *		-EBUSY	device is bussy (cmd not possible)
691 *		-and errors returned by: p80211req_dorequest(..)
692 *
693 * by: Collin R. Mulliner <collin@mulliner.org>
694 ----------------------------------------------------------------*/
p80211knetdev_set_mac_address(netdevice_t * dev,void * addr)695 static int p80211knetdev_set_mac_address(netdevice_t *dev, void *addr)
696 {
697 	struct sockaddr			*new_addr = addr;
698 	p80211msg_dot11req_mibset_t	dot11req;
699 	p80211item_unk392_t		*mibattr;
700 	p80211item_pstr6_t		*macaddr;
701 	p80211item_uint32_t		*resultcode;
702 	int result = 0;
703 
704 	DBFENTER;
705 	/* If we're running, we don't allow MAC address changes */
706 	if (netif_running(dev)) {
707 		return -EBUSY;
708 	}
709 
710 	/* Set up some convenience pointers. */
711 	mibattr = &dot11req.mibattribute;
712 	macaddr = (p80211item_pstr6_t*)&mibattr->data;
713 	resultcode = &dot11req.resultcode;
714 
715 	/* Set up a dot11req_mibset */
716 	memset(&dot11req, 0, sizeof(p80211msg_dot11req_mibset_t));
717 	dot11req.msgcode = DIDmsg_dot11req_mibset;
718 	dot11req.msglen = sizeof(p80211msg_dot11req_mibset_t);
719 	memcpy(dot11req.devname,
720 		((wlandevice_t *)dev->ml_priv)->name,
721 		WLAN_DEVNAMELEN_MAX - 1);
722 
723 	/* Set up the mibattribute argument */
724 	mibattr->did = DIDmsg_dot11req_mibset_mibattribute;
725 	mibattr->status = P80211ENUM_msgitem_status_data_ok;
726 	mibattr->len = sizeof(mibattr->data);
727 
728 	macaddr->did = DIDmib_dot11mac_dot11OperationTable_dot11MACAddress;
729 	macaddr->status = P80211ENUM_msgitem_status_data_ok;
730 	macaddr->len = sizeof(macaddr->data);
731 	macaddr->data.len = WLAN_ADDR_LEN;
732 	memcpy(&macaddr->data.data, new_addr->sa_data, WLAN_ADDR_LEN);
733 
734 	/* Set up the resultcode argument */
735 	resultcode->did = DIDmsg_dot11req_mibset_resultcode;
736 	resultcode->status = P80211ENUM_msgitem_status_no_value;
737 	resultcode->len = sizeof(resultcode->data);
738 	resultcode->data = 0;
739 
740 	/* now fire the request */
741 	result = p80211req_dorequest(dev->ml_priv, (u8 *)&dot11req);
742 
743 	/* If the request wasn't successful, report an error and don't
744 	 * change the netdev address
745 	 */
746 	if ( result != 0 || resultcode->data != P80211ENUM_resultcode_success) {
747 		WLAN_LOG_ERROR(
748 		"Low-level driver failed dot11req_mibset(dot11MACAddress).\n");
749 		result = -EADDRNOTAVAIL;
750 	} else {
751 		/* everything's ok, change the addr in netdev */
752 		memcpy(dev->dev_addr, new_addr->sa_data, dev->addr_len);
753 	}
754 
755 	DBFEXIT;
756 	return result;
757 }
758 
wlan_change_mtu(netdevice_t * dev,int new_mtu)759 static int wlan_change_mtu(netdevice_t *dev, int new_mtu)
760 {
761 	DBFENTER;
762 	// 2312 is max 802.11 payload, 20 is overhead, (ether + llc +snap)
763 	// and another 8 for wep.
764         if ( (new_mtu < 68) || (new_mtu > (2312 - 20 - 8)))
765                 return -EINVAL;
766 
767         dev->mtu = new_mtu;
768 
769 	DBFEXIT;
770 
771         return 0;
772 }
773 
774 
775 
776 /*----------------------------------------------------------------
777 * wlan_setup
778 *
779 * Roughly matches the functionality of ether_setup.  Here
780 * we set up any members of the wlandevice structure that are common
781 * to all devices.  Additionally, we allocate a linux 'struct device'
782 * and perform the same setup as ether_setup.
783 *
784 * Note: It's important that the caller have setup the wlandev->name
785 *	ptr prior to calling this function.
786 *
787 * Arguments:
788 *	wlandev		ptr to the wlandev structure for the
789 *			interface.
790 * Returns:
791 *	zero on success, non-zero otherwise.
792 * Call Context:
793 *	Should be process thread.  We'll assume it might be
794 *	interrupt though.  When we add support for statically
795 *	compiled drivers, this function will be called in the
796 *	context of the kernel startup code.
797 ----------------------------------------------------------------*/
wlan_setup(wlandevice_t * wlandev)798 int wlan_setup(wlandevice_t *wlandev)
799 {
800 	int		result = 0;
801 	netdevice_t	*dev;
802 
803 	DBFENTER;
804 
805 	/* Set up the wlandev */
806 	wlandev->state = WLAN_DEVICE_CLOSED;
807 	wlandev->ethconv = WLAN_ETHCONV_8021h;
808 	wlandev->macmode = WLAN_MACMODE_NONE;
809 
810 	/* Set up the rx queue */
811 	skb_queue_head_init(&wlandev->nsd_rxq);
812 	tasklet_init(&wlandev->rx_bh,
813 		     p80211netdev_rx_bh,
814 		     (unsigned long)wlandev);
815 
816 	/* Allocate and initialize the struct device */
817 	dev = alloc_netdev(0,"wlan%d",ether_setup);
818 	if ( dev == NULL ) {
819 		WLAN_LOG_ERROR("Failed to alloc netdev.\n");
820 		result = 1;
821 	} else {
822 		wlandev->netdev = dev;
823 		dev->ml_priv = wlandev;
824 		dev->hard_start_xmit =	p80211knetdev_hard_start_xmit;
825 		dev->get_stats =	p80211knetdev_get_stats;
826 #ifdef HAVE_PRIVATE_IOCTL
827 		dev->do_ioctl = 	p80211knetdev_do_ioctl;
828 #endif
829 #ifdef HAVE_MULTICAST
830 		dev->set_multicast_list = p80211knetdev_set_multicast_list;
831 #endif
832 		dev->init =		p80211knetdev_init;
833 		dev->open =		p80211knetdev_open;
834 		dev->stop =		p80211knetdev_stop;
835 
836 #if (WIRELESS_EXT < 21)
837 		dev->get_wireless_stats = p80211wext_get_wireless_stats;
838 #endif
839 		dev->wireless_handlers = &p80211wext_handler_def;
840 
841 		netif_stop_queue(dev);
842 #ifdef HAVE_CHANGE_MTU
843 		dev->change_mtu = wlan_change_mtu;
844 #endif
845 #ifdef HAVE_SET_MAC_ADDR
846 		dev->set_mac_address =	p80211knetdev_set_mac_address;
847 #endif
848 #ifdef HAVE_TX_TIMEOUT
849 		dev->tx_timeout      =  &p80211knetdev_tx_timeout;
850 		dev->watchdog_timeo  =  (wlan_watchdog * HZ) / 1000;
851 #endif
852 		netif_carrier_off(dev);
853 	}
854 
855 	DBFEXIT;
856 	return result;
857 }
858 
859 /*----------------------------------------------------------------
860 * wlan_unsetup
861 *
862 * This function is paired with the wlan_setup routine.  It should
863 * be called after unregister_wlandev.  Basically, all it does is
864 * free the 'struct device' that's associated with the wlandev.
865 * We do it here because the 'struct device' isn't allocated
866 * explicitly in the driver code, it's done in wlan_setup.  To
867 * do the free in the driver might seem like 'magic'.
868 *
869 * Arguments:
870 *	wlandev		ptr to the wlandev structure for the
871 *			interface.
872 * Returns:
873 *	zero on success, non-zero otherwise.
874 * Call Context:
875 *	Should be process thread.  We'll assume it might be
876 *	interrupt though.  When we add support for statically
877 *	compiled drivers, this function will be called in the
878 *	context of the kernel startup code.
879 ----------------------------------------------------------------*/
wlan_unsetup(wlandevice_t * wlandev)880 int wlan_unsetup(wlandevice_t *wlandev)
881 {
882 	int		result = 0;
883 
884 	DBFENTER;
885 
886 	tasklet_kill(&wlandev->rx_bh);
887 
888 	if (wlandev->netdev == NULL ) {
889 		WLAN_LOG_ERROR("called without wlandev->netdev set.\n");
890 		result = 1;
891 	} else {
892 		free_netdev(wlandev->netdev);
893 		wlandev->netdev = NULL;
894 	}
895 
896 	DBFEXIT;
897 	return 0;
898 }
899 
900 
901 
902 /*----------------------------------------------------------------
903 * register_wlandev
904 *
905 * Roughly matches the functionality of register_netdev.  This function
906 * is called after the driver has successfully probed and set up the
907 * resources for the device.  It's now ready to become a named device
908 * in the Linux system.
909 *
910 * First we allocate a name for the device (if not already set), then
911 * we call the Linux function register_netdevice.
912 *
913 * Arguments:
914 *	wlandev		ptr to the wlandev structure for the
915 *			interface.
916 * Returns:
917 *	zero on success, non-zero otherwise.
918 * Call Context:
919 *	Can be either interrupt or not.
920 ----------------------------------------------------------------*/
register_wlandev(wlandevice_t * wlandev)921 int register_wlandev(wlandevice_t *wlandev)
922 {
923 	int		i = 0;
924 
925 	DBFENTER;
926 
927 	i = register_netdev(wlandev->netdev);
928 	if (i)
929 		return i;
930 
931 	DBFEXIT;
932 	return 0;
933 }
934 
935 
936 /*----------------------------------------------------------------
937 * unregister_wlandev
938 *
939 * Roughly matches the functionality of unregister_netdev.  This
940 * function is called to remove a named device from the system.
941 *
942 * First we tell linux that the device should no longer exist.
943 * Then we remove it from the list of known wlan devices.
944 *
945 * Arguments:
946 *	wlandev		ptr to the wlandev structure for the
947 *			interface.
948 * Returns:
949 *	zero on success, non-zero otherwise.
950 * Call Context:
951 *	Can be either interrupt or not.
952 ----------------------------------------------------------------*/
unregister_wlandev(wlandevice_t * wlandev)953 int unregister_wlandev(wlandevice_t *wlandev)
954 {
955 	struct sk_buff *skb;
956 
957 	DBFENTER;
958 
959 	unregister_netdev(wlandev->netdev);
960 
961 	/* Now to clean out the rx queue */
962 	while ( (skb = skb_dequeue(&wlandev->nsd_rxq)) ) {
963 		dev_kfree_skb(skb);
964 	}
965 
966 	DBFEXIT;
967 	return 0;
968 }
969 
970 
971 /*----------------------------------------------------------------
972 * p80211netdev_hwremoved
973 *
974 * Hardware removed notification. This function should be called
975 * immediately after an MSD has detected that the underlying hardware
976 * has been yanked out from under us.  The primary things we need
977 * to do are:
978 *   - Mark the wlandev
979 *   - Prevent any further traffic from the knetdev i/f
980 *   - Prevent any further requests from mgmt i/f
981 *   - If there are any waitq'd mgmt requests or mgmt-frame exchanges,
982 *     shut them down.
983 *   - Call the MSD hwremoved function.
984 *
985 * The remainder of the cleanup will be handled by unregister().
986 * Our primary goal here is to prevent as much tickling of the MSD
987 * as possible since the MSD is already in a 'wounded' state.
988 *
989 * TODO: As new features are added, this function should be
990 *       updated.
991 *
992 * Arguments:
993 *	wlandev		WLAN network device structure
994 * Returns:
995 *	nothing
996 * Side effects:
997 *
998 * Call context:
999 *	Usually interrupt.
1000 ----------------------------------------------------------------*/
p80211netdev_hwremoved(wlandevice_t * wlandev)1001 void p80211netdev_hwremoved(wlandevice_t *wlandev)
1002 {
1003 	DBFENTER;
1004 	wlandev->hwremoved = 1;
1005 	if ( wlandev->state == WLAN_DEVICE_OPEN) {
1006 		netif_stop_queue(wlandev->netdev);
1007 	}
1008 
1009 	netif_device_detach(wlandev->netdev);
1010 
1011 	DBFEXIT;
1012 }
1013 
1014 
1015 /*----------------------------------------------------------------
1016 * p80211_rx_typedrop
1017 *
1018 * Classifies the frame, increments the appropriate counter, and
1019 * returns 0|1|2 indicating whether the driver should handle, ignore, or
1020 * drop the frame
1021 *
1022 * Arguments:
1023 *	wlandev		wlan device structure
1024 *	fc		frame control field
1025 *
1026 * Returns:
1027 *	zero if the frame should be handled by the driver,
1028 *       one if the frame should be ignored
1029 *       anything else means we drop it.
1030 *
1031 * Side effects:
1032 *
1033 * Call context:
1034 *	interrupt
1035 ----------------------------------------------------------------*/
p80211_rx_typedrop(wlandevice_t * wlandev,u16 fc)1036 static int p80211_rx_typedrop( wlandevice_t *wlandev, u16 fc)
1037 {
1038 	u16	ftype;
1039 	u16	fstype;
1040 	int	drop = 0;
1041 	/* Classify frame, increment counter */
1042 	ftype = WLAN_GET_FC_FTYPE(fc);
1043 	fstype = WLAN_GET_FC_FSTYPE(fc);
1044 #if 0
1045 	WLAN_LOG_DEBUG(4,
1046 		"rx_typedrop : ftype=%d fstype=%d.\n", ftype, fstype);
1047 #endif
1048 	switch ( ftype ) {
1049 	case WLAN_FTYPE_MGMT:
1050 		if ((wlandev->netdev->flags & IFF_PROMISC) ||
1051 			(wlandev->netdev->flags & IFF_ALLMULTI)) {
1052 			drop = 1;
1053 			break;
1054 		}
1055 		WLAN_LOG_DEBUG(3, "rx'd mgmt:\n");
1056 		wlandev->rx.mgmt++;
1057 		switch( fstype ) {
1058 		case WLAN_FSTYPE_ASSOCREQ:
1059 			/* printk("assocreq"); */
1060 			wlandev->rx.assocreq++;
1061 			break;
1062 		case WLAN_FSTYPE_ASSOCRESP:
1063 			/* printk("assocresp"); */
1064 			wlandev->rx.assocresp++;
1065 			break;
1066 		case WLAN_FSTYPE_REASSOCREQ:
1067 			/* printk("reassocreq"); */
1068 			wlandev->rx.reassocreq++;
1069 			break;
1070 		case WLAN_FSTYPE_REASSOCRESP:
1071 			/* printk("reassocresp"); */
1072 			wlandev->rx.reassocresp++;
1073 			break;
1074 		case WLAN_FSTYPE_PROBEREQ:
1075 			/* printk("probereq"); */
1076 			wlandev->rx.probereq++;
1077 			break;
1078 		case WLAN_FSTYPE_PROBERESP:
1079 			/* printk("proberesp"); */
1080 			wlandev->rx.proberesp++;
1081 			break;
1082 		case WLAN_FSTYPE_BEACON:
1083 			/* printk("beacon"); */
1084 			wlandev->rx.beacon++;
1085 			break;
1086 		case WLAN_FSTYPE_ATIM:
1087 			/* printk("atim"); */
1088 			wlandev->rx.atim++;
1089 			break;
1090 		case WLAN_FSTYPE_DISASSOC:
1091 			/* printk("disassoc"); */
1092 			wlandev->rx.disassoc++;
1093 			break;
1094 		case WLAN_FSTYPE_AUTHEN:
1095 			/* printk("authen"); */
1096 			wlandev->rx.authen++;
1097 			break;
1098 		case WLAN_FSTYPE_DEAUTHEN:
1099 			/* printk("deauthen"); */
1100 			wlandev->rx.deauthen++;
1101 			break;
1102 		default:
1103 			/* printk("unknown"); */
1104 			wlandev->rx.mgmt_unknown++;
1105 			break;
1106 		}
1107 		/* printk("\n"); */
1108 		drop = 2;
1109 		break;
1110 
1111 	case WLAN_FTYPE_CTL:
1112 		if ((wlandev->netdev->flags & IFF_PROMISC) ||
1113 			(wlandev->netdev->flags & IFF_ALLMULTI)) {
1114 			drop = 1;
1115 			break;
1116 		}
1117 		WLAN_LOG_DEBUG(3, "rx'd ctl:\n");
1118 		wlandev->rx.ctl++;
1119 		switch( fstype ) {
1120 		case WLAN_FSTYPE_PSPOLL:
1121 			/* printk("pspoll"); */
1122 			wlandev->rx.pspoll++;
1123 			break;
1124 		case WLAN_FSTYPE_RTS:
1125 			/* printk("rts"); */
1126 			wlandev->rx.rts++;
1127 			break;
1128 		case WLAN_FSTYPE_CTS:
1129 			/* printk("cts"); */
1130 			wlandev->rx.cts++;
1131 			break;
1132 		case WLAN_FSTYPE_ACK:
1133 			/* printk("ack"); */
1134 			wlandev->rx.ack++;
1135 			break;
1136 		case WLAN_FSTYPE_CFEND:
1137 			/* printk("cfend"); */
1138 			wlandev->rx.cfend++;
1139 			break;
1140 		case WLAN_FSTYPE_CFENDCFACK:
1141 			/* printk("cfendcfack"); */
1142 			wlandev->rx.cfendcfack++;
1143 			break;
1144 		default:
1145 			/* printk("unknown"); */
1146 			wlandev->rx.ctl_unknown++;
1147 			break;
1148 		}
1149 		/* printk("\n"); */
1150 		drop = 2;
1151 		break;
1152 
1153 	case WLAN_FTYPE_DATA:
1154 		wlandev->rx.data++;
1155 		switch( fstype ) {
1156 		case WLAN_FSTYPE_DATAONLY:
1157 			wlandev->rx.dataonly++;
1158 			break;
1159 		case WLAN_FSTYPE_DATA_CFACK:
1160 			wlandev->rx.data_cfack++;
1161 			break;
1162 		case WLAN_FSTYPE_DATA_CFPOLL:
1163 			wlandev->rx.data_cfpoll++;
1164 			break;
1165 		case WLAN_FSTYPE_DATA_CFACK_CFPOLL:
1166 			wlandev->rx.data__cfack_cfpoll++;
1167 			break;
1168 		case WLAN_FSTYPE_NULL:
1169 			WLAN_LOG_DEBUG(3, "rx'd data:null\n");
1170 			wlandev->rx.null++;
1171 			break;
1172 		case WLAN_FSTYPE_CFACK:
1173 			WLAN_LOG_DEBUG(3, "rx'd data:cfack\n");
1174 			wlandev->rx.cfack++;
1175 			break;
1176 		case WLAN_FSTYPE_CFPOLL:
1177 			WLAN_LOG_DEBUG(3, "rx'd data:cfpoll\n");
1178 			wlandev->rx.cfpoll++;
1179 			break;
1180 		case WLAN_FSTYPE_CFACK_CFPOLL:
1181 			WLAN_LOG_DEBUG(3, "rx'd data:cfack_cfpoll\n");
1182 			wlandev->rx.cfack_cfpoll++;
1183 			break;
1184 		default:
1185 			/* printk("unknown"); */
1186 			wlandev->rx.data_unknown++;
1187 			break;
1188 		}
1189 
1190 		break;
1191 	}
1192 	return drop;
1193 }
1194 
p80211knetdev_tx_timeout(netdevice_t * netdev)1195 static void p80211knetdev_tx_timeout( netdevice_t *netdev)
1196 {
1197 	wlandevice_t	*wlandev = netdev->ml_priv;
1198 	DBFENTER;
1199 
1200 	if (wlandev->tx_timeout) {
1201 		wlandev->tx_timeout(wlandev);
1202 	} else {
1203 		WLAN_LOG_WARNING("Implement tx_timeout for %s\n",
1204 				 wlandev->nsdname);
1205 		netif_wake_queue(wlandev->netdev);
1206 	}
1207 
1208 	DBFEXIT;
1209 }
1210