File: /usr/src/linux/net/irda/irlan/irlan_eth.c

1     /*********************************************************************
2      *                
3      * Filename:      irlan_eth.c
4      * Version:       
5      * Description:   
6      * Status:        Experimental.
7      * Author:        Dag Brattli <dagb@cs.uit.no>
8      * Created at:    Thu Oct 15 08:37:58 1998
9      * Modified at:   Tue Mar 21 09:06:41 2000
10      * Modified by:   Dag Brattli <dagb@cs.uit.no>
11      * Sources:       skeleton.c by Donald Becker <becker@CESDIS.gsfc.nasa.gov>
12      *                slip.c by Laurence Culhane,   <loz@holmes.demon.co.uk>
13      *                          Fred N. van Kempen, <waltje@uwalt.nl.mugnet.org>
14      * 
15      *     Copyright (c) 1998-2000 Dag Brattli, All Rights Reserved.
16      *      
17      *     This program is free software; you can redistribute it and/or 
18      *     modify it under the terms of the GNU General Public License as 
19      *     published by the Free Software Foundation; either version 2 of 
20      *     the License, or (at your option) any later version.
21      *  
22      *     Neither Dag Brattli nor University of Tromsų admit liability nor
23      *     provide warranty for any of this software. This material is 
24      *     provided "AS-IS" and at no charge.
25      *     
26      ********************************************************************/
27     
28     #include <linux/config.h>
29     #include <linux/netdevice.h>
30     #include <linux/etherdevice.h>
31     #include <linux/inetdevice.h>
32     #include <linux/if_arp.h>
33     #include <linux/random.h>
34     #include <net/arp.h>
35     
36     #include <net/irda/irda.h>
37     #include <net/irda/irmod.h>
38     #include <net/irda/irlan_common.h>
39     #include <net/irda/irlan_client.h>
40     #include <net/irda/irlan_event.h>
41     #include <net/irda/irlan_eth.h>
42     
43     /*
44      * Function irlan_eth_init (dev)
45      *
46      *    The network device initialization function.
47      *
48      */
49     int irlan_eth_init(struct net_device *dev)
50     {
51     	struct irlan_cb *self;
52     
53     	IRDA_DEBUG(2, __FUNCTION__"()\n");
54     
55     	ASSERT(dev != NULL, return -1;);
56            
57     	self = (struct irlan_cb *) dev->priv;
58     
59     	dev->open               = irlan_eth_open;
60     	dev->stop               = irlan_eth_close;
61     	dev->hard_start_xmit    = irlan_eth_xmit; 
62     	dev->get_stats	        = irlan_eth_get_stats;
63     	dev->set_multicast_list = irlan_eth_set_multicast_list;
64     	dev->features          |= NETIF_F_DYNALLOC;
65     
66     	ether_setup(dev);
67     	
68     	/* 
69     	 * Lets do all queueing in IrTTP instead of this device driver.
70     	 * Queueing here as well can introduce some strange latency
71     	 * problems, which we will avoid by setting the queue size to 0.
72     	 */
73     	dev->tx_queue_len = 0;
74     
75     	if (self->provider.access_type == ACCESS_DIRECT) {
76     		/*  
77     		 * Since we are emulating an IrLAN sever we will have to
78     		 * give ourself an ethernet address!  
79     		 */
80     		dev->dev_addr[0] = 0x40;
81     		dev->dev_addr[1] = 0x00;
82     		dev->dev_addr[2] = 0x00;
83     		dev->dev_addr[3] = 0x00;
84     		get_random_bytes(dev->dev_addr+4, 1);
85     		get_random_bytes(dev->dev_addr+5, 1);
86     	}
87     
88     	return 0;
89     }
90     
91     /*
92      * Function irlan_eth_open (dev)
93      *
94      *    Network device has been opened by user
95      *
96      */
97     int irlan_eth_open(struct net_device *dev)
98     {
99     	struct irlan_cb *self;
100     	
101     	IRDA_DEBUG(2, __FUNCTION__ "()\n");
102     
103     	ASSERT(dev != NULL, return -1;);
104     
105     	self = (struct irlan_cb *) dev->priv;
106     
107     	ASSERT(self != NULL, return -1;);
108     
109     	/* Ready to play! */
110      	netif_stop_queue(dev); /* Wait until data link is ready */
111     
112     	/* We are now open, so time to do some work */
113     	self->disconnect_reason = 0;
114     	irlan_client_wakeup(self, self->saddr, self->daddr);
115     
116     	irlan_mod_inc_use_count();
117     
118     	/* Make sure we have a hardware address before we return, so DHCP clients gets happy */
119     	interruptible_sleep_on(&self->open_wait);
120     	
121     	return 0;
122     }
123     
124     /*
125      * Function irlan_eth_close (dev)
126      *
127      *    Stop the ether network device, his function will usually be called by
128      *    ifconfig down. We should now disconnect the link, We start the 
129      *    close timer, so that the instance will be removed if we are unable
130      *    to discover the remote device after the disconnect.
131      */
132     int irlan_eth_close(struct net_device *dev)
133     {
134     	struct irlan_cb *self = (struct irlan_cb *) dev->priv;
135     	struct sk_buff *skb;
136     	
137     	IRDA_DEBUG(2, __FUNCTION__ "()\n");
138     	
139     	/* Stop device */
140     	netif_stop_queue(dev);
141     	
142     	irlan_mod_dec_use_count();
143     
144     	irlan_close_data_channel(self);
145     	irlan_close_tsaps(self);
146     
147     	irlan_do_client_event(self, IRLAN_LMP_DISCONNECT, NULL);
148     	irlan_do_provider_event(self, IRLAN_LMP_DISCONNECT, NULL);	
149     	
150     	/* Remove frames queued on the control channel */
151     	while ((skb = skb_dequeue(&self->client.txq)))
152     			dev_kfree_skb(skb);
153     
154     	self->client.tx_busy = 0;
155     	
156     	return 0;
157     }
158     
159     /*
160      * Function irlan_eth_tx (skb)
161      *
162      *    Transmits ethernet frames over IrDA link.
163      *
164      */
165     int irlan_eth_xmit(struct sk_buff *skb, struct net_device *dev)
166     {
167     	struct irlan_cb *self;
168     	int ret;
169     
170     	self = (struct irlan_cb *) dev->priv;
171     
172     	ASSERT(self != NULL, return 0;);
173     	ASSERT(self->magic == IRLAN_MAGIC, return 0;);
174     
175     	/* skb headroom large enough to contain all IrDA-headers? */
176     	if ((skb_headroom(skb) < self->max_header_size) || (skb_shared(skb))) {
177     		struct sk_buff *new_skb = 
178     			skb_realloc_headroom(skb, self->max_header_size);
179     
180     		/*  We have to free the original skb anyway */
181     		dev_kfree_skb(skb);
182     
183     		/* Did the realloc succeed? */
184     		if (new_skb == NULL)
185     			return 0;
186     
187     		/* Use the new skb instead */
188     		skb = new_skb;
189     	} 
190     
191     	dev->trans_start = jiffies;
192     
193     	/* Now queue the packet in the transport layer */
194     	if (self->use_udata)
195     		ret = irttp_udata_request(self->tsap_data, skb);
196     	else
197     		ret = irttp_data_request(self->tsap_data, skb);
198     
199     	if (ret < 0) {
200     		/*   
201     		 * IrTTPs tx queue is full, so we just have to
202     		 * drop the frame! You might think that we should
203     		 * just return -1 and don't deallocate the frame,
204     		 * but that is dangerous since it's possible that
205     		 * we have replaced the original skb with a new
206     		 * one with larger headroom, and that would really
207     		 * confuse do_dev_queue_xmit() in dev.c! I have
208     		 * tried :-) DB 
209     		 */
210     		dev_kfree_skb(skb);
211     		self->stats.tx_dropped++;
212     	} else {
213     		self->stats.tx_packets++;
214     		self->stats.tx_bytes += skb->len; 
215     	}
216     	
217     	return 0;
218     }
219     
220     /*
221      * Function irlan_eth_receive (handle, skb)
222      *
223      *    This function gets the data that is received on the data channel
224      *
225      */
226     int irlan_eth_receive(void *instance, void *sap, struct sk_buff *skb)
227     {
228     	struct irlan_cb *self;
229     
230     	self = (struct irlan_cb *) instance;
231     
232     	if (skb == NULL) {
233     		++self->stats.rx_dropped; 
234     		return 0;
235     	}
236     	ASSERT(skb->len > 1, return 0;);
237     		
238     	/* 
239     	 * Adopt this frame! Important to set all these fields since they 
240     	 * might have been previously set by the low level IrDA network
241     	 * device driver 
242     	 */
243     	skb->dev = &self->dev;
244     	skb->protocol=eth_type_trans(skb, skb->dev); /* Remove eth header */
245     	
246     	self->stats.rx_packets++;
247     	self->stats.rx_bytes += skb->len; 
248     
249     	netif_rx(skb);   /* Eat it! */
250     	
251     	return 0;
252     }
253     
254     /*
255      * Function irlan_eth_flow (status)
256      *
257      *    Do flow control between IP/Ethernet and IrLAN/IrTTP. This is done by 
258      *    controlling the queue stop/start.
259      */
260     void irlan_eth_flow_indication(void *instance, void *sap, LOCAL_FLOW flow)
261     {
262     	struct irlan_cb *self;
263     	struct net_device *dev;
264     
265     	self = (struct irlan_cb *) instance;
266     
267     	ASSERT(self != NULL, return;);
268     	ASSERT(self->magic == IRLAN_MAGIC, return;);
269     	
270     	dev = &self->dev;
271     
272     	ASSERT(dev != NULL, return;);
273     	
274     	switch (flow) {
275     	case FLOW_STOP:
276     		netif_stop_queue(dev);
277     		break;
278     	case FLOW_START:
279     	default:
280     		/* Tell upper layers that its time to transmit frames again */
281     		/* Schedule network layer */
282     		netif_start_queue(dev);
283     		break;
284     	}
285     }
286     
287     /*
288      * Function irlan_eth_rebuild_header (buff, dev, dest, skb)
289      *
290      *    If we don't want to use ARP. Currently not used!!
291      *
292      */
293     void irlan_eth_rebuild_header(void *buff, struct net_device *dev, 
294     			      unsigned long dest, struct sk_buff *skb)
295     {
296     	struct ethhdr *eth = (struct ethhdr *) buff;
297     
298     	memcpy(eth->h_source, dev->dev_addr, dev->addr_len);
299     	memcpy(eth->h_dest, dev->dev_addr, dev->addr_len);
300     
301     	/* return 0; */
302     }
303     
304     /*
305      * Function irlan_etc_send_gratuitous_arp (dev)
306      *
307      *    Send gratuitous ARP to announce that we have changed
308      *    hardware address, so that all peers updates their ARP tables
309      */
310     void irlan_eth_send_gratuitous_arp(struct net_device *dev)
311     {
312     	struct in_device *in_dev;
313     
314     	/* 
315     	 * When we get a new MAC address do a gratuitous ARP. This
316     	 * is useful if we have changed access points on the same
317     	 * subnet.  
318     	 */
319     #ifdef CONFIG_INET
320     	IRDA_DEBUG(4, "IrLAN: Sending gratuitous ARP\n");
321     	in_dev = in_dev_get(dev);
322     	if (in_dev == NULL)
323     		return;
324     	read_lock(&in_dev->lock);
325     	if (in_dev->ifa_list)
326     		
327     	arp_send(ARPOP_REQUEST, ETH_P_ARP, 
328     		 in_dev->ifa_list->ifa_address,
329     		 dev, 
330     		 in_dev->ifa_list->ifa_address,
331     		 NULL, dev->dev_addr, NULL);
332     	read_unlock(&in_dev->lock);
333     	in_dev_put(in_dev);
334     #endif /* CONFIG_INET */
335     }
336     
337     /*
338      * Function set_multicast_list (dev)
339      *
340      *    Configure the filtering of the device
341      *
342      */
343     #define HW_MAX_ADDRS 4 /* Must query to get it! */
344     void irlan_eth_set_multicast_list(struct net_device *dev) 
345     {
346      	struct irlan_cb *self;
347     
348      	self = dev->priv; 
349     
350     	IRDA_DEBUG(2, __FUNCTION__ "()\n");
351     
352      	ASSERT(self != NULL, return;); 
353      	ASSERT(self->magic == IRLAN_MAGIC, return;);
354     
355     	/* Check if data channel has been connected yet */
356     	if (self->client.state != IRLAN_DATA) {
357     		IRDA_DEBUG(1, __FUNCTION__ "(), delaying!\n");
358     		return;
359     	}
360     
361     	if (dev->flags & IFF_PROMISC) {
362     		/* Enable promiscuous mode */
363     		WARNING("Promiscous mode not implemented by IrLAN!\n");
364     	} 
365     	else if ((dev->flags & IFF_ALLMULTI) || dev->mc_count > HW_MAX_ADDRS) {
366     		/* Disable promiscuous mode, use normal mode. */
367     		IRDA_DEBUG(4, __FUNCTION__ "(), Setting multicast filter\n");
368     		/* hardware_set_filter(NULL); */
369     
370     		irlan_set_multicast_filter(self, TRUE);
371     	}
372     	else if (dev->mc_count) {
373     		IRDA_DEBUG(4, __FUNCTION__ "(), Setting multicast filter\n");
374     		/* Walk the address list, and load the filter */
375     		/* hardware_set_filter(dev->mc_list); */
376     
377     		irlan_set_multicast_filter(self, TRUE);
378     	}
379     	else {
380     		IRDA_DEBUG(4, __FUNCTION__ "(), Clearing multicast filter\n");
381     		irlan_set_multicast_filter(self, FALSE);
382     	}
383     
384     	if (dev->flags & IFF_BROADCAST)
385     		irlan_set_broadcast_filter(self, TRUE);
386     	else
387     		irlan_set_broadcast_filter(self, FALSE);
388     }
389     
390     /*
391      * Function irlan_get_stats (dev)
392      *
393      *    Get the current statistics for this device
394      *
395      */
396     struct net_device_stats *irlan_eth_get_stats(struct net_device *dev) 
397     {
398     	struct irlan_cb *self = (struct irlan_cb *) dev->priv;
399     
400     	ASSERT(self != NULL, return NULL;);
401     	ASSERT(self->magic == IRLAN_MAGIC, return NULL;);
402     
403     	return &self->stats;
404     }
405