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