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