File: /usr/src/linux/net/802/tr.c

1     /*
2      * NET3:	Token ring device handling subroutines
3      * 
4      *		This program is free software; you can redistribute it and/or
5      *		modify it under the terms of the GNU General Public License
6      *		as published by the Free Software Foundation; either version
7      *		2 of the License, or (at your option) any later version.
8      *
9      * Fixes:       3 Feb 97 Paul Norton <pnorton@cts.com> Minor routing fixes.
10      *              Added rif table to /proc/net/tr_rif and rif timeout to
11      *              /proc/sys/net/token-ring/rif_timeout.
12      *              22 Jun 98 Paul Norton <p.norton@computer.org> Rearranged
13      *              tr_header and tr_type_trans to handle passing IPX SNAP and
14      *              802.2 through the correct layers. Eliminated tr_reformat.
15      *        
16      */
17     
18     #include <asm/uaccess.h>
19     #include <asm/system.h>
20     #include <linux/config.h>
21     #include <linux/types.h>
22     #include <linux/kernel.h>
23     #include <linux/sched.h>
24     #include <linux/string.h>
25     #include <linux/mm.h>
26     #include <linux/socket.h>
27     #include <linux/in.h>
28     #include <linux/inet.h>
29     #include <linux/netdevice.h>
30     #include <linux/trdevice.h>
31     #include <linux/skbuff.h>
32     #include <linux/errno.h>
33     #include <linux/timer.h>
34     #include <linux/net.h>
35     #include <linux/proc_fs.h>
36     #include <linux/init.h>
37     #include <net/arp.h>
38     
39     static void tr_source_route(struct sk_buff *skb, struct trh_hdr *trh, struct net_device *dev);
40     static void tr_add_rif_info(struct trh_hdr *trh, struct net_device *dev);
41     static void rif_check_expire(unsigned long dummy);
42     
43     #define TR_SR_DEBUG 0
44     
45     typedef struct rif_cache_s *rif_cache;
46     
47     /*
48      *	Each RIF entry we learn is kept this way
49      */
50      
51     struct rif_cache_s {	
52     	unsigned char addr[TR_ALEN];
53     	int iface;
54     	__u16 rcf;
55     	__u16 rseg[8];
56     	rif_cache next;
57     	unsigned long last_used;
58     	unsigned char local_ring;
59     };
60     
61     #define RIF_TABLE_SIZE 32
62     
63     /*
64      *	We hash the RIF cache 32 ways. We do after all have to look it
65      *	up a lot.
66      */
67      
68     rif_cache rif_table[RIF_TABLE_SIZE]={ NULL, };
69     
70     static spinlock_t rif_lock = SPIN_LOCK_UNLOCKED;
71     
72     #define RIF_TIMEOUT 60*10*HZ
73     #define RIF_CHECK_INTERVAL 60*HZ
74     
75     /*
76      *	Garbage disposal timer.
77      */
78      
79     static struct timer_list rif_timer;
80     
81     int sysctl_tr_rif_timeout = RIF_TIMEOUT;
82     
83     /*
84      *	Put the headers on a token ring packet. Token ring source routing
85      *	makes this a little more exciting than on ethernet.
86      */
87      
88     int tr_header(struct sk_buff *skb, struct net_device *dev, unsigned short type,
89                   void *daddr, void *saddr, unsigned len) 
90     {
91     	struct trh_hdr *trh;
92     	int hdr_len;
93     
94     	/* 
95     	 * Add the 802.2 SNAP header if IP as the IPv4 code calls  
96     	 * dev->hard_header directly.
97     	 */
98     	if (type == ETH_P_IP || type == ETH_P_ARP)
99     	{
100     		struct trllc *trllc=(struct trllc *)(trh+1);
101     
102     		hdr_len = sizeof(struct trh_hdr) + sizeof(struct trllc);
103     		trh = (struct trh_hdr *)skb_push(skb, hdr_len);
104     		trllc = (struct trllc *)(trh+1);
105     		trllc->dsap = trllc->ssap = EXTENDED_SAP;
106     		trllc->llc = UI_CMD;
107     		trllc->protid[0] = trllc->protid[1] = trllc->protid[2] = 0x00;
108     		trllc->ethertype = htons(type);
109     	}
110     	else
111     	{
112     		hdr_len = sizeof(struct trh_hdr);
113     		trh = (struct trh_hdr *)skb_push(skb, hdr_len);	
114     	}
115     
116     	trh->ac=AC;
117     	trh->fc=LLC_FRAME;
118     
119     	if(saddr)
120     		memcpy(trh->saddr,saddr,dev->addr_len);
121     	else
122     		memcpy(trh->saddr,dev->dev_addr,dev->addr_len);
123     
124     	/*
125     	 *	Build the destination and then source route the frame
126     	 */
127     	 
128     	if(daddr) 
129     	{
130     		memcpy(trh->daddr,daddr,dev->addr_len);
131     		tr_source_route(skb,trh,dev);
132     		return(hdr_len);
133     	}
134     
135     	return -hdr_len;
136     }
137     	
138     /*
139      *	A neighbour discovery of some species (eg arp) has completed. We
140      *	can now send the packet.
141      */
142      
143     int tr_rebuild_header(struct sk_buff *skb) 
144     {
145     	struct trh_hdr *trh=(struct trh_hdr *)skb->data;
146     	struct trllc *trllc=(struct trllc *)(skb->data+sizeof(struct trh_hdr));
147     	struct net_device *dev = skb->dev;
148     
149     	/*
150     	 *	FIXME: We don't yet support IPv6 over token rings
151     	 */
152     	 
153     	if(trllc->ethertype != htons(ETH_P_IP)) {
154     		printk("tr_rebuild_header: Don't know how to resolve type %04X addresses ?\n",(unsigned int)htons(trllc->ethertype));
155     		return 0;
156     	}
157     
158     #ifdef CONFIG_INET
159     	if(arp_find(trh->daddr, skb)) {
160     			return 1;
161     	}
162     	else 
163     #endif	
164     	{	
165     		tr_source_route(skb,trh,dev); 
166     		return 0;
167     	}
168     }
169     	
170     /*
171      *	Some of this is a bit hackish. We intercept RIF information
172      *	used for source routing. We also grab IP directly and don't feed
173      *	it via SNAP.
174      */
175      
176     unsigned short tr_type_trans(struct sk_buff *skb, struct net_device *dev) 
177     {
178     
179     	struct trh_hdr *trh=(struct trh_hdr *)skb->data;
180     	struct trllc *trllc;
181     	unsigned riflen=0;
182     	
183     	skb->mac.raw = skb->data;
184     	
185            	if(trh->saddr[0] & TR_RII)
186     		riflen = (ntohs(trh->rcf) & TR_RCF_LEN_MASK) >> 8;
187     
188     	trllc = (struct trllc *)(skb->data+sizeof(struct trh_hdr)-TR_MAXRIFLEN+riflen);
189     
190     	skb_pull(skb,sizeof(struct trh_hdr)-TR_MAXRIFLEN+riflen);
191     
192     	if(*trh->daddr & 0x80) 
193     	{
194     		if(!memcmp(trh->daddr,dev->broadcast,TR_ALEN)) 	
195     			skb->pkt_type=PACKET_BROADCAST;
196     		else
197     			skb->pkt_type=PACKET_MULTICAST;
198     	}
199     	else if ( (trh->daddr[0] & 0x01) && (trh->daddr[1] & 0x00) && (trh->daddr[2] & 0x5E))
200     	{
201     		skb->pkt_type=PACKET_MULTICAST;
202     	}
203     	else if(dev->flags & IFF_PROMISC) 
204     	{
205     		if(memcmp(trh->daddr, dev->dev_addr, TR_ALEN))
206     			skb->pkt_type=PACKET_OTHERHOST;
207     	}
208     
209     	if ((skb->pkt_type != PACKET_BROADCAST) &&
210     	    (skb->pkt_type != PACKET_MULTICAST))
211     		tr_add_rif_info(trh,dev) ; 
212     
213     	/*
214     	 * Strip the SNAP header from ARP packets since we don't 
215     	 * pass them through to the 802.2/SNAP layers.
216     	 */
217     
218     	if (trllc->dsap == EXTENDED_SAP &&
219     	    (trllc->ethertype == ntohs(ETH_P_IP) ||
220     	     trllc->ethertype == ntohs(ETH_P_ARP)))
221     	{
222     		skb_pull(skb, sizeof(struct trllc));
223     		return trllc->ethertype;
224     	}
225     
226     	return ntohs(ETH_P_802_2);
227     }
228     
229     /*
230      *	We try to do source routing... 
231      */
232     
233     static void tr_source_route(struct sk_buff *skb,struct trh_hdr *trh,struct net_device *dev) 
234     {
235     	int i, slack;
236     	unsigned int hash;
237     	rif_cache entry;
238     	unsigned char *olddata;
239     	unsigned char mcast_func_addr[] = {0xC0,0x00,0x00,0x04,0x00,0x00};
240     	unsigned long flags ; 
241     	
242     	spin_lock_irqsave(&rif_lock,flags);
243     
244     	/*
245     	 *	Broadcasts are single route as stated in RFC 1042 
246     	 */
247     	if( (!memcmp(&(trh->daddr[0]),&(dev->broadcast[0]),TR_ALEN)) ||
248     	    (!memcmp(&(trh->daddr[0]),&(mcast_func_addr[0]), TR_ALEN))  )
249     	{
250     		trh->rcf=htons((((sizeof(trh->rcf)) << 8) & TR_RCF_LEN_MASK)  
251     			       | TR_RCF_FRAME2K | TR_RCF_LIMITED_BROADCAST);
252     		trh->saddr[0]|=TR_RII;
253     	}
254     	else 
255     	{
256     		for(i=0,hash=0;i<TR_ALEN;hash+=trh->daddr[i++]);
257     		hash&=RIF_TABLE_SIZE-1;
258     		/*
259     		 *	Walk the hash table and look for an entry
260     		 */
261     		for(entry=rif_table[hash];entry && memcmp(&(entry->addr[0]),&(trh->daddr[0]),TR_ALEN);entry=entry->next);
262     
263     		/*
264     		 *	If we found an entry we can route the frame.
265     		 */
266     		if(entry) 
267     		{
268     #if TR_SR_DEBUG
269     printk("source routing for %02X:%02X:%02X:%02X:%02X:%02X\n",trh->daddr[0],
270     		  trh->daddr[1],trh->daddr[2],trh->daddr[3],trh->daddr[4],trh->daddr[5]);
271     #endif
272     			if(!entry->local_ring && (ntohs(entry->rcf) & TR_RCF_LEN_MASK) >> 8)
273     			{
274     				trh->rcf=entry->rcf;
275     				memcpy(&trh->rseg[0],&entry->rseg[0],8*sizeof(unsigned short));
276     				trh->rcf^=htons(TR_RCF_DIR_BIT);	
277     				trh->rcf&=htons(0x1fff);	/* Issam Chehab <ichehab@madge1.demon.co.uk> */
278     
279     				trh->saddr[0]|=TR_RII;
280     #if TR_SR_DEBUG
281     				printk("entry found with rcf %04x\n", entry->rcf);
282     			}
283     			else
284     			{
285     				printk("entry found but without rcf length, local=%02x\n", entry->local_ring);
286     #endif
287     			}
288     			entry->last_used=jiffies;
289     		}
290     		else 
291     		{
292     			/*
293     			 *	Without the information we simply have to shout
294     			 *	on the wire. The replies should rapidly clean this
295     			 *	situation up.
296     			 */
297     			trh->rcf=htons((((sizeof(trh->rcf)) << 8) & TR_RCF_LEN_MASK)  
298     				       | TR_RCF_FRAME2K | TR_RCF_LIMITED_BROADCAST);
299     			trh->saddr[0]|=TR_RII;
300     #if TR_SR_DEBUG
301     			printk("no entry in rif table found - broadcasting frame\n");
302     #endif
303     		}
304     	}
305     
306     	/* Compress the RIF here so we don't have to do it in the driver(s) */
307     	if (!(trh->saddr[0] & 0x80))
308     		slack = 18;
309     	else 
310     		slack = 18 - ((ntohs(trh->rcf) & TR_RCF_LEN_MASK)>>8);
311     	olddata = skb->data;
312     	spin_unlock_irqrestore(&rif_lock,flags);
313     
314     	skb_pull(skb, slack);
315     	memmove(skb->data, olddata, sizeof(struct trh_hdr) - slack);
316     }
317     
318     /*
319      *	We have learned some new RIF information for our source
320      *	routing.
321      */
322      
323     static void tr_add_rif_info(struct trh_hdr *trh, struct net_device *dev)
324     {
325     	int i;
326     	unsigned int hash, rii_p = 0;
327     	rif_cache entry;
328     
329     
330     	spin_lock_bh(&rif_lock);
331     	
332     	/*
333     	 *	Firstly see if the entry exists
334     	 */
335     
336            	if(trh->saddr[0] & TR_RII)
337     	{
338     		trh->saddr[0]&=0x7f;
339     		if (((ntohs(trh->rcf) & TR_RCF_LEN_MASK) >> 8) > 2)
340     		{
341     			rii_p = 1;
342     	        }
343     	}
344     
345     	for(i=0,hash=0;i<TR_ALEN;hash+=trh->saddr[i++]);
346     	hash&=RIF_TABLE_SIZE-1;
347     	for(entry=rif_table[hash];entry && memcmp(&(entry->addr[0]),&(trh->saddr[0]),TR_ALEN);entry=entry->next);
348     
349     	if(entry==NULL) 
350     	{
351     #if TR_SR_DEBUG
352     printk("adding rif_entry: addr:%02X:%02X:%02X:%02X:%02X:%02X rcf:%04X\n",
353     		trh->saddr[0],trh->saddr[1],trh->saddr[2],
354            		trh->saddr[3],trh->saddr[4],trh->saddr[5],
355     		ntohs(trh->rcf));
356     #endif
357     		/*
358     		 *	Allocate our new entry. A failure to allocate loses
359     		 *	use the information. This is harmless.
360     		 *
361     		 *	FIXME: We ought to keep some kind of cache size
362     		 *	limiting and adjust the timers to suit.
363     		 */
364     		entry=kmalloc(sizeof(struct rif_cache_s),GFP_ATOMIC);
365     
366     		if(!entry) 
367     		{
368     			printk(KERN_DEBUG "tr.c: Couldn't malloc rif cache entry !\n");
369     			spin_unlock_bh(&rif_lock);
370     			return;
371     		}
372     
373     		memcpy(&(entry->addr[0]),&(trh->saddr[0]),TR_ALEN);
374     		entry->iface = dev->ifindex;
375     		entry->next=rif_table[hash];
376     		entry->last_used=jiffies;
377     		rif_table[hash]=entry;
378     
379     		if (rii_p)
380     		{
381     			entry->rcf = trh->rcf & htons((unsigned short)~TR_RCF_BROADCAST_MASK);
382     			memcpy(&(entry->rseg[0]),&(trh->rseg[0]),8*sizeof(unsigned short));
383     			entry->local_ring = 0;
384     			trh->saddr[0]|=TR_RII; /* put the routing indicator back for tcpdump */
385     		}
386     		else
387     		{
388     			entry->local_ring = 1;
389     		}
390     	} 	
391     	else	/* Y. Tahara added */
392     	{ 
393     		/*
394     		 *	Update existing entries
395     		 */
396     		if (!entry->local_ring) 
397     		    if (entry->rcf != (trh->rcf & htons((unsigned short)~TR_RCF_BROADCAST_MASK)) &&
398     			 !(trh->rcf & htons(TR_RCF_BROADCAST_MASK)))
399     		    {
400     #if TR_SR_DEBUG
401     printk("updating rif_entry: addr:%02X:%02X:%02X:%02X:%02X:%02X rcf:%04X\n",
402     		trh->saddr[0],trh->saddr[1],trh->saddr[2],
403     		trh->saddr[3],trh->saddr[4],trh->saddr[5],
404     		ntohs(trh->rcf));
405     #endif
406     			    entry->rcf = trh->rcf & htons((unsigned short)~TR_RCF_BROADCAST_MASK);
407             		    memcpy(&(entry->rseg[0]),&(trh->rseg[0]),8*sizeof(unsigned short));
408     		    }                                         
409                	entry->last_used=jiffies;               
410     	}
411     	spin_unlock_bh(&rif_lock);
412     }
413     
414     /*
415      *	Scan the cache with a timer and see what we need to throw out.
416      */
417     
418     static void rif_check_expire(unsigned long dummy) 
419     {
420     	int i;
421     	unsigned long now=jiffies;
422     	unsigned long flags ; 
423     
424     	spin_lock_irqsave(&rif_lock,flags);
425     	
426     	for(i=0; i < RIF_TABLE_SIZE;i++) 
427     	{
428     		rif_cache entry, *pentry=rif_table+i;	
429     		while((entry=*pentry)) 
430     		{
431     			/*
432     			 *	Out it goes
433     			 */
434     			if((now-entry->last_used) > sysctl_tr_rif_timeout) 
435     			{
436     				*pentry=entry->next;
437     				kfree(entry);
438     			}
439     			else
440     				pentry=&entry->next;
441     		}
442     	}
443     	
444     	spin_unlock_irqrestore(&rif_lock,flags);
445     
446     	/*
447     	 *	Reset the timer
448     	 */
449     	 
450     	mod_timer(&rif_timer, jiffies+sysctl_tr_rif_timeout);
451     
452     }
453     
454     /*
455      *	Generate the /proc/net information for the token ring RIF
456      *	routing.
457      */
458      
459     #ifndef CONFIG_PROC_FS
460     static int rif_get_info(char *buffer,char **start, off_t offset, int length)  { return 0;}
461     #else
462     static int rif_get_info(char *buffer,char **start, off_t offset, int length) 
463     {
464     	int len=0;
465     	off_t begin=0;
466     	off_t pos=0;
467     	int size,i,j,rcf_len,segment,brdgnmb;
468     	unsigned long now=jiffies;
469     
470     	rif_cache entry;
471     
472     	size=sprintf(buffer,
473     		     "if     TR address       TTL   rcf   routing segments\n");
474     	pos+=size;
475     	len+=size;
476     
477     	spin_lock_bh(&rif_lock);
478     	for(i=0;i < RIF_TABLE_SIZE;i++) 
479     	{
480     		for(entry=rif_table[i];entry;entry=entry->next) {
481     			struct net_device *dev = __dev_get_by_index(entry->iface);
482     
483     			size=sprintf(buffer+len,"%s %02X:%02X:%02X:%02X:%02X:%02X %7li ",
484     				     dev?dev->name:"?",entry->addr[0],entry->addr[1],entry->addr[2],entry->addr[3],entry->addr[4],entry->addr[5],
485     				     sysctl_tr_rif_timeout-(now-entry->last_used));
486     			len+=size;
487     			pos=begin+len;
488     			if (entry->local_ring)
489     			        size=sprintf(buffer+len,"local\n");
490     			else {
491     			        size=sprintf(buffer+len,"%04X", ntohs(entry->rcf));
492     				rcf_len = ((ntohs(entry->rcf) & TR_RCF_LEN_MASK)>>8)-2; 
493     				if (rcf_len)
494     				        rcf_len >>= 1;
495     				for(j = 1; j < rcf_len; j++) {
496     					if(j==1) {
497     						segment=ntohs(entry->rseg[j-1])>>4;
498     						len+=size;
499     						pos=begin+len;
500     						size=sprintf(buffer+len,"  %03X",segment);
501     					};
502     					segment=ntohs(entry->rseg[j])>>4;
503     					brdgnmb=ntohs(entry->rseg[j-1])&0x00f;
504     					len+=size;
505     					pos=begin+len;
506     					size=sprintf(buffer+len,"-%01X-%03X",brdgnmb,segment);
507     				}
508     				len+=size;
509     				pos=begin+len;
510     			        size=sprintf(buffer+len,"\n");
511     			}
512     			len+=size;
513     			pos=begin+len;
514     
515     			if(pos<offset) 
516     			{
517     				len=0;
518     				begin=pos;
519     			}
520     			if(pos>offset+length)
521     				break;
522     	   	}
523     		if(pos>offset+length)
524     			break;
525     	}
526     	spin_unlock_bh(&rif_lock);
527     
528     	*start=buffer+(offset-begin); /* Start of wanted data */
529     	len-=(offset-begin);    /* Start slop */
530     	if(len>length)
531     		len=length;    /* Ending slop */
532     	if (len<0)
533     		len=0;
534     	return len;
535     }
536     #endif
537     
538     /*
539      *	Called during bootup.  We don't actually have to initialise
540      *	too much for this.
541      */
542     
543     static int __init rif_init(void)
544     {
545     	rif_timer.expires  = RIF_TIMEOUT;
546     	rif_timer.data     = 0L;
547     	rif_timer.function = rif_check_expire;
548     	init_timer(&rif_timer);
549     	add_timer(&rif_timer);
550     
551     	proc_net_create("tr_rif",0,rif_get_info);
552     	return 0;
553     }
554     
555     module_init(rif_init);
556