This source file includes following definitions.
- rarp_init
- rarp_release_entry
- rarp_destroy
- rarp_rcv
- rarp_req_set
- rarp_req_get
- rarp_ioctl
- rarp_get_info
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30 #include <linux/types.h>
31 #include <linux/string.h>
32 #include <linux/kernel.h>
33 #include <linux/sched.h>
34 #include <linux/config.h>
35 #include <linux/socket.h>
36 #include <linux/sockios.h>
37 #include <linux/errno.h>
38 #include <linux/if_arp.h>
39 #include <linux/in.h>
40 #include <asm/system.h>
41 #include <asm/segment.h>
42 #include <stdarg.h>
43 #include <linux/inet.h>
44 #include <linux/netdevice.h>
45 #include <linux/etherdevice.h>
46 #include "ip.h"
47 #include "route.h"
48 #include "protocol.h"
49 #include "tcp.h"
50 #include <linux/skbuff.h>
51 #include "sock.h"
52 #include "arp.h"
53 #include "rarp.h"
54 #ifdef CONFIG_AX25
55 #include "ax25.h"
56 #endif
57
58 #ifdef CONFIG_INET_RARP
59
60
61
62
63
64
65 struct rarp_table
66 {
67 struct rarp_table *next;
68 unsigned long ip;
69 unsigned char ha[MAX_ADDR_LEN];
70 unsigned char hlen;
71 unsigned char htype;
72 struct device *dev;
73 };
74
75 struct rarp_table *rarp_tables = NULL;
76
77
78
79
80
81
82 struct arphdr
83 {
84 unsigned short ar_hrd;
85 unsigned short ar_pro;
86 unsigned char ar_hln;
87 unsigned char ar_pln;
88 unsigned short ar_op;
89 #if 0
90
91
92
93 unsigned char ar_sha[ETH_ALEN];
94 unsigned char ar_sip[4];
95 unsigned char ar_tha[ETH_ALEN];
96 unsigned char ar_tip[4];
97 #endif
98 };
99
100 static struct packet_type rarp_packet_type =
101 {
102 0,
103 0,
104 rarp_rcv,
105 NULL,
106 NULL
107 };
108
109 static initflag = 1;
110
111
112
113
114
115 static void rarp_init (void)
116 {
117
118 rarp_packet_type.type=htons(ETH_P_RARP);
119 dev_add_pack(&rarp_packet_type);
120 }
121
122
123
124
125
126 static inline void rarp_release_entry(struct rarp_table *entry)
127 {
128 kfree_s(entry, sizeof(struct rarp_table));
129 return;
130 }
131
132
133
134
135
136 static void rarp_destroy(unsigned long ip_addr)
137 {
138 struct rarp_table *entry;
139 struct rarp_table **pentry;
140
141 cli();
142 pentry = &rarp_tables;
143 while ((entry = *pentry) != NULL)
144 {
145 if (entry->ip == ip_addr)
146 {
147 *pentry = entry->next;
148 sti();
149 rarp_release_entry(entry);
150 return;
151 }
152 pentry = &entry->next;
153 }
154 sti();
155 }
156
157
158
159
160
161
162
163
164 int rarp_rcv(struct sk_buff *skb, struct device *dev, struct packet_type *pt)
165 {
166
167
168
169 struct arphdr *rarp = (struct arphdr *)skb->h.raw;
170 unsigned char *rarp_ptr = (unsigned char *)(rarp+1);
171 struct rarp_table *entry;
172 long sip,tip;
173 unsigned char *sha,*tha;
174
175
176
177
178
179 if (rarp->ar_hln != dev->addr_len || dev->type != ntohs(rarp->ar_hrd)
180 || dev->flags&IFF_NOARP)
181 {
182 kfree_skb(skb, FREE_READ);
183 return 0;
184 }
185
186
187
188
189 if (rarp->ar_op != htons(ARPOP_RREQUEST))
190 {
191 kfree_skb(skb, FREE_READ);
192 return 0;
193 }
194
195
196
197
198
199 if (
200 #ifdef CONFIG_AX25
201 (rarp->ar_pro != htons(AX25_P_IP) && dev->type == ARPHRD_AX25) ||
202 #endif
203 (rarp->ar_pro != htons(ETH_P_IP) && dev->type != ARPHRD_AX25)
204 || rarp->ar_pln != 4)
205 {
206
207
208
209 kfree_skb(skb, FREE_READ);
210 return 0;
211 }
212
213
214
215
216
217 sha=rarp_ptr;
218 rarp_ptr+=dev->addr_len;
219 memcpy(&sip,rarp_ptr,4);
220 rarp_ptr+=4;
221 tha=rarp_ptr;
222 rarp_ptr+=dev->addr_len;
223 memcpy(&tip,rarp_ptr,4);
224
225
226
227
228
229 cli();
230 for (entry = rarp_tables; entry != NULL; entry = entry->next)
231 if (!memcmp(entry->ha, sha, rarp->ar_hln))
232 break;
233
234 if (entry != NULL)
235 {
236 sip=entry->ip;
237 sti();
238
239 arp_send(ARPOP_RREPLY, ETH_P_RARP, sip, dev, dev->pa_addr, sha,
240 dev->dev_addr);
241 }
242 else
243 sti();
244
245 kfree_skb(skb, FREE_READ);
246 return 0;
247 }
248
249
250
251
252
253
254 static int rarp_req_set(struct arpreq *req)
255 {
256 struct arpreq r;
257 struct rarp_table *entry;
258 struct sockaddr_in *si;
259 int htype, hlen;
260 unsigned long ip;
261 struct rtable *rt;
262
263 memcpy_fromfs(&r, req, sizeof(r));
264
265
266
267
268
269 if (r.arp_pa.sa_family != AF_INET)
270 return -EPFNOSUPPORT;
271
272 switch (r.arp_ha.sa_family)
273 {
274 case ARPHRD_ETHER:
275 htype = ARPHRD_ETHER;
276 hlen = ETH_ALEN;
277 break;
278 #ifdef CONFIG_AX25
279 case ARPHRD_AX25:
280 htype = ARPHRD_AX25;
281 hlen = 7;
282 break;
283 #endif
284 default:
285 return -EPFNOSUPPORT;
286 }
287
288 si = (struct sockaddr_in *) &r.arp_pa;
289 ip = si->sin_addr.s_addr;
290 if (ip == 0)
291 {
292 printk("RARP: SETRARP: requested PA is 0.0.0.0 !\n");
293 return -EINVAL;
294 }
295
296
297
298
299
300 rt = ip_rt_route(ip, NULL, NULL);
301 if (rt == NULL)
302 return -ENETUNREACH;
303
304
305
306
307
308 cli();
309 for (entry = rarp_tables; entry != NULL; entry = entry->next)
310 if (entry->ip == ip)
311 break;
312
313
314
315
316
317 if (entry == NULL)
318 {
319 entry = (struct rarp_table *) kmalloc(sizeof(struct rarp_table),
320 GFP_ATOMIC);
321 if (entry == NULL)
322 {
323 sti();
324 return -ENOMEM;
325 }
326 if(initflag)
327 {
328 rarp_init();
329 initflag=0;
330 }
331
332 entry->next = rarp_tables;
333 rarp_tables = entry;
334 }
335
336 entry->ip = ip;
337 entry->hlen = hlen;
338 entry->htype = htype;
339 memcpy(&entry->ha, &r.arp_ha.sa_data, hlen);
340 entry->dev = rt->rt_dev;
341
342 sti();
343
344 return 0;
345 }
346
347
348
349
350
351
352 static int rarp_req_get(struct arpreq *req)
353 {
354 struct arpreq r;
355 struct rarp_table *entry;
356 struct sockaddr_in *si;
357 unsigned long ip;
358
359
360
361
362
363 memcpy_fromfs(&r, req, sizeof(r));
364
365 if (r.arp_pa.sa_family != AF_INET)
366 return -EPFNOSUPPORT;
367
368
369
370
371
372 si = (struct sockaddr_in *) &r.arp_pa;
373 ip = si->sin_addr.s_addr;
374
375 cli();
376 for (entry = rarp_tables; entry != NULL; entry = entry->next)
377 if (entry->ip == ip)
378 break;
379
380 if (entry == NULL)
381 {
382 sti();
383 return -ENXIO;
384 }
385
386
387
388
389
390 memcpy(r.arp_ha.sa_data, &entry->ha, entry->hlen);
391 r.arp_ha.sa_family = entry->htype;
392 sti();
393
394
395
396
397
398 memcpy_tofs(req, &r, sizeof(r));
399 return 0;
400 }
401
402
403
404
405
406
407 int rarp_ioctl(unsigned int cmd, void *arg)
408 {
409 struct arpreq r;
410 struct sockaddr_in *si;
411 int err;
412
413 switch(cmd)
414 {
415 case SIOCDRARP:
416 if (!suser())
417 return -EPERM;
418 err = verify_area(VERIFY_READ, arg, sizeof(struct arpreq));
419 if(err)
420 return err;
421 memcpy_fromfs(&r, arg, sizeof(r));
422 if (r.arp_pa.sa_family != AF_INET)
423 return -EPFNOSUPPORT;
424 si = (struct sockaddr_in *) &r.arp_pa;
425 rarp_destroy(si->sin_addr.s_addr);
426 return 0;
427
428 case SIOCGRARP:
429 err = verify_area(VERIFY_WRITE, arg, sizeof(struct arpreq));
430 if(err)
431 return err;
432 return rarp_req_get((struct arpreq *)arg);
433 case SIOCSRARP:
434 if (!suser())
435 return -EPERM;
436 err = verify_area(VERIFY_READ, arg, sizeof(struct arpreq));
437 if(err)
438 return err;
439 return rarp_req_set((struct arpreq *)arg);
440 default:
441 return -EINVAL;
442 }
443
444
445 return 0;
446 }
447
448 int rarp_get_info(char *buffer, char **start, off_t offset, int length)
449 {
450 int len=0;
451 off_t begin=0;
452 off_t pos=0;
453 int size;
454 struct rarp_table *entry;
455 char ipbuffer[20];
456 unsigned long netip;
457 if(initflag)
458 {
459 size = sprintf(buffer,"RARP disabled until entries added to cache.\n");
460 pos+=size;
461 len+=size;
462 }
463 else
464 {
465 size = sprintf(buffer,
466 "IP address HW type HW address\n");
467 pos+=size;
468 len+=size;
469
470 cli();
471 for(entry=rarp_tables; entry!=NULL; entry=entry->next)
472 {
473 netip=htonl(entry->ip);
474 sprintf(ipbuffer,"%d.%d.%d.%d",
475 (unsigned int)(netip>>24)&255,
476 (unsigned int)(netip>>16)&255,
477 (unsigned int)(netip>>8)&255,
478 (unsigned int)(netip)&255);
479
480 size = sprintf(buffer+len,
481 "%-17s%-20s%02x:%02x:%02x:%02x:%02x:%02x\n",
482 ipbuffer,
483 "10Mbps Ethernet",
484 (unsigned int)entry->ha[0],
485 (unsigned int)entry->ha[1],
486 (unsigned int)entry->ha[2],
487 (unsigned int)entry->ha[3],
488 (unsigned int)entry->ha[4],
489 (unsigned int)entry->ha[5]);
490
491 len+=size;
492 pos=begin+len;
493
494 if(pos<offset)
495 {
496 len=0;
497 begin=pos;
498 }
499 if(pos>offset+length)
500 break;
501 }
502 sti();
503 }
504
505 *start=buffer+(offset-begin);
506 len-=(offset-begin);
507 if(len>length)
508 len=length;
509 return len;
510 }
511
512 #endif