This source file includes following definitions.
- tr_header
- tr_rebuild_header
- tr_type_trans
- tr_source_route
- tr_add_rif_info
- rif_check_expire
- rif_get_info
- rif_init
1 #include <asm/segment.h>
2 #include <asm/system.h>
3 #include <linux/types.h>
4 #include <linux/kernel.h>
5 #include <linux/sched.h>
6 #include <linux/string.h>
7 #include <linux/mm.h>
8 #include <linux/socket.h>
9 #include <linux/in.h>
10 #include <linux/inet.h>
11 #include <linux/netdevice.h>
12 #include <linux/trdevice.h>
13 #include <linux/skbuff.h>
14 #include <linux/errno.h>
15 #include <linux/string.h>
16 #include <linux/timer.h>
17 #include <linux/net.h>
18 #include <net/arp.h>
19
20 static void tr_source_route(struct trh_hdr *trh,struct device *dev);
21 static void tr_add_rif_info(struct trh_hdr *trh);
22 static void rif_check_expire(unsigned long dummy);
23
24 typedef struct rif_cache_s *rif_cache;
25
26 struct rif_cache_s {
27 unsigned char addr[TR_ALEN];
28 unsigned short rcf;
29 unsigned short rseg[8];
30 rif_cache next;
31 unsigned long last_used;
32 };
33
34 #define RIF_TABLE_SIZE 16
35 rif_cache rif_table[RIF_TABLE_SIZE]={ NULL, };
36
37 #define RIF_TIMEOUT 60*10*HZ
38 #define RIF_CHECK_INTERVAL 60*HZ
39 static struct timer_list rif_timer={ NULL,NULL,RIF_CHECK_INTERVAL,0L,rif_check_expire };
40
41 int tr_header(unsigned char *buff, struct device *dev, unsigned short type,
42 void *daddr, void *saddr, unsigned len, struct sk_buff *skb) {
43
44 struct trh_hdr *trh=(struct trh_hdr *)skb_push(skb,dev->hard_header_len);
45 struct trllc *trllc=(struct trllc *)(buff+sizeof(struct trh_hdr));
46
47 trh->ac=AC;
48 trh->fc=LLC_FRAME;
49
50 if(saddr)
51 memcpy(trh->saddr,saddr,dev->addr_len);
52 else
53 memset(trh->saddr,0,dev->addr_len);
54
55 trllc->dsap=trllc->ssap=EXTENDED_SAP;
56 trllc->llc=UI_CMD;
57
58 trllc->protid[0]=trllc->protid[1]=trllc->protid[2]=0x00;
59 trllc->ethertype=htons(type);
60
61 if(daddr) {
62 memcpy(trh->daddr,daddr,dev->addr_len);
63 tr_source_route(trh,dev);
64 return(dev->hard_header_len);
65 }
66 return -dev->hard_header_len;
67
68 }
69
70 int tr_rebuild_header(void *buff, struct device *dev, unsigned long dest,
71 struct sk_buff *skb) {
72
73 struct trh_hdr *trh=(struct trh_hdr *)buff;
74 struct trllc *trllc=(struct trllc *)(buff+sizeof(struct trh_hdr));
75
76 if(trllc->ethertype != htons(ETH_P_IP)) {
77 printk("tr_rebuild_header: Don't know how to resolve type %04X addresses ?\n",(unsigned int)htons( trllc->ethertype));
78 return 0;
79 }
80
81 if(arp_find(trh->daddr, dest, dev, dev->pa_addr, skb)) {
82 return 1;
83 }
84 else {
85 tr_source_route(trh,dev);
86 return 0;
87 }
88 }
89
90 unsigned short tr_type_trans(struct sk_buff *skb, struct device *dev) {
91
92 struct trh_hdr *trh=(struct trh_hdr *)skb->data;
93 struct trllc *trllc=(struct trllc *)(skb->data+sizeof(struct trh_hdr));
94
95 skb_pull(skb,dev->hard_header_len);
96
97 if(trh->saddr[0] & TR_RII)
98 tr_add_rif_info(trh);
99
100 if(*trh->daddr & 1)
101 {
102 if(!memcmp(trh->daddr,dev->broadcast,TR_ALEN))
103 skb->pkt_type=PACKET_BROADCAST;
104 else
105 skb->pkt_type=PACKET_MULTICAST;
106 }
107
108 else if(dev->flags & IFF_PROMISC)
109 {
110 if(memcmp(trh->daddr, dev->dev_addr, TR_ALEN))
111 skb->pkt_type=PACKET_OTHERHOST;
112 }
113
114 return trllc->ethertype;
115 }
116
117
118
119 static void tr_source_route(struct trh_hdr *trh,struct device *dev) {
120
121 int i;
122 unsigned int hash;
123 rif_cache entry;
124
125
126 if(!memcmp(&(trh->daddr[0]),&(dev->broadcast[0]),TR_ALEN)) {
127 trh->rcf=htons((((sizeof(trh->rcf)) << 8) & TR_RCF_LEN_MASK)
128 | TR_RCF_FRAME2K | TR_RCF_LIMITED_BROADCAST);
129 trh->saddr[0]|=TR_RII;
130 }
131 else {
132 for(i=0,hash=0;i<TR_ALEN;hash+=trh->daddr[i++]);
133 hash&=RIF_TABLE_SIZE-1;
134 for(entry=rif_table[hash];entry && memcmp(&(entry->addr[0]),&(trh->daddr[0]),TR_ALEN);entry=entry->next);
135
136 if(entry) {
137 #if 0
138 printk("source routing for %02X %02X %02X %02X %02X %02X\n",trh->daddr[0],
139 trh->daddr[1],trh->daddr[2],trh->daddr[3],trh->daddr[4],trh->daddr[5]);
140 #endif
141 if((ntohs(entry->rcf) & TR_RCF_LEN_MASK) >> 8) {
142 trh->rcf=entry->rcf;
143 memcpy(&trh->rseg[0],&entry->rseg[0],8*sizeof(unsigned short));
144 trh->rcf^=htons(TR_RCF_DIR_BIT);
145 trh->rcf&=htons(0x1fff);
146
147 trh->saddr[0]|=TR_RII;
148 entry->last_used=jiffies;
149 }
150 }
151 else {
152 trh->rcf=htons((((sizeof(trh->rcf)) << 8) & TR_RCF_LEN_MASK)
153 | TR_RCF_FRAME2K | TR_RCF_LIMITED_BROADCAST);
154 trh->saddr[0]|=TR_RII;
155 }
156 }
157
158 }
159
160 static void tr_add_rif_info(struct trh_hdr *trh) {
161
162 int i;
163 unsigned int hash;
164 rif_cache entry;
165
166
167 trh->saddr[0]&=0x7f;
168 for(i=0,hash=0;i<TR_ALEN;hash+=trh->saddr[i++]);
169 hash&=RIF_TABLE_SIZE-1;
170 #if 0
171 printk("hash: %d\n",hash);
172 #endif
173 for(entry=rif_table[hash];entry && memcmp(&(entry->addr[0]),&(trh->saddr[0]),TR_ALEN);entry=entry->next);
174
175 if(entry==NULL) {
176 #if 0
177 printk("adding rif_entry: addr:%02X:%02X:%02X:%02X:%02X:%02X rcf:%04X\n",
178 trh->saddr[0],trh->saddr[1],trh->saddr[2],
179 trh->saddr[3],trh->saddr[4],trh->saddr[5],
180 trh->rcf);
181 #endif
182 entry=kmalloc(sizeof(struct rif_cache_s),GFP_ATOMIC);
183 if(!entry) {
184 printk("tr.c: Couldn't malloc rif cache entry !\n");
185 return;
186 }
187 entry->rcf=trh->rcf;
188 memcpy(&(entry->rseg[0]),&(trh->rseg[0]),8*sizeof(unsigned short));
189 memcpy(&(entry->addr[0]),&(trh->saddr[0]),TR_ALEN);
190 entry->next=rif_table[hash];
191 entry->last_used=jiffies;
192 rif_table[hash]=entry;
193 }
194
195 else {
196 if ( entry->rcf != trh->rcf ) {
197 if (!(trh->rcf & htons(TR_RCF_BROADCAST_MASK))) {
198 #if 0
199 printk("updating rif_entry: addr:%02X:%02X:%02X:%02X:%02X:%02X rcf:%04X\n",
200 trh->saddr[0],trh->saddr[1],trh->saddr[2],
201 trh->saddr[3],trh->saddr[4],trh->saddr[5],
202 trh->rcf);
203 #endif
204 entry->rcf = trh->rcf;
205 memcpy(&(entry->rseg[0]),&(trh->rseg[0]),8*sizeof(unsigned short));
206 entry->last_used=jiffies;
207 }
208 }
209 }
210
211 }
212
213 static void rif_check_expire(unsigned long dummy) {
214
215 int i;
216 unsigned long now=jiffies,flags;
217
218 save_flags(flags);
219 cli();
220
221 for(i=0; i < RIF_TABLE_SIZE;i++) {
222
223 rif_cache entry, *pentry=rif_table+i;
224
225 while((entry=*pentry))
226 if((now-entry->last_used) > RIF_TIMEOUT) {
227 *pentry=entry->next;
228 kfree_s(entry,sizeof(struct rif_cache_s));
229 }
230 else
231 pentry=&entry->next;
232 }
233 restore_flags(flags);
234
235 del_timer(&rif_timer);
236 rif_timer.expires=RIF_CHECK_INTERVAL;
237 add_timer(&rif_timer);
238
239 }
240
241 int rif_get_info(char *buffer,char **start, off_t offset, int length) {
242
243 int len=0;
244 off_t begin=0;
245 off_t pos=0;
246 int size,i;
247
248 rif_cache entry;
249
250 size=sprintf(buffer,
251 " TR address rcf routing segments TTL\n\n");
252 pos+=size;
253 len+=size;
254
255 for(i=0;i < RIF_TABLE_SIZE;i++) {
256 for(entry=rif_table[i];entry;entry=entry->next) {
257 size=sprintf(buffer+len,"%02X:%02X:%02X:%02X:%02X:%02X %04X %04X %04X %04X %04X %04X %04X %04X %04X %lu\n",
258 entry->addr[0],entry->addr[1],entry->addr[2],entry->addr[3],entry->addr[4],entry->addr[5],
259 entry->rcf,entry->rseg[0],entry->rseg[1],entry->rseg[2],entry->rseg[3],
260 entry->rseg[4],entry->rseg[5],entry->rseg[6],entry->rseg[7],jiffies-entry->last_used);
261 len+=size;
262 pos=begin+len;
263
264 if(pos<offset) {
265 len=0;
266 begin=pos;
267 }
268 if(pos>offset+length)
269 break;
270 }
271 if(pos>offset+length)
272 break;
273 }
274
275 *start=buffer+(offset-begin);
276 len-=(offset-begin);
277 if(len>length)
278 len=length;
279 return len;
280 }
281
282 void rif_init(struct net_proto *unused) {
283
284 add_timer(&rif_timer);
285
286 }
287