⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 arp.c

📁 An implementation of the TCP/IP protocol suite for the LINUX operating system. INET is implemented u
💻 C
📖 第 1 页 / 共 3 页
字号:
  1 /*
  2  * INET         An implementation of the TCP/IP protocol suite for the LINUX
  3  *              operating system.  INET is implemented using the  BSD Socket
  4  *              interface as the means of communication with the user level.
  5  *
  6  *              This file implements the Address Resolution Protocol (ARP),
  7  *              which is used by TCP/IP to map the IP addresses from a host
  8  *              to a low-level hardware address (like an Ethernet address)
  9  *              which it can use to talk to that host.
 10  *
 11  * NOTE:        This module will be rewritten completely in the near future,
 12  *              because I want it to become a multi-address-family address
 13  *              resolver, like it should be.  It will be put in a separate
 14  *              directory under 'net', being a protocol of its own. -FvK
 15  *
 16  * Version:     @(#)arp.c       1.0.15  05/25/93
 17  *
 18  * Authors:     Ross Biro, <bir7@leland.Stanford.Edu>
 19  *              Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
 20  *              Arnt Gulbrandsen, <agulbra@pvv.unit.no>
 21  *
 22  * Fixes:
 23  *              Stephen A. Wood :       arp problems
 24  *              'Mr Linux'      :       arp problems.
 25  *              Alan Cox        :       arp_ioctl now checks memory areas with verify_area.
 26  *              Alan Cox        :       Non IP arp message now only appears with debugging on.
 27  *              Alan Cox        :       arp queue is volatile (may be altered by arp messages while doing sends) 
 28  *                                      Generic queue code is urgently needed!
 29  *              Alan Cox        :       Deleting your own ip addr now gives EINVAL not a printk message.
 30  *              Alan Cox        :       Fix to arp linked list error
 31  *              Alan Cox        :       Ignore broadcast arp (Linus' idea 8-))
 32  *              Alan Cox        :       arp_send memory leak removed
 33  *              Alan Cox        :       generic skbuff code fixes.
 34  *              Alan Cox        :       'Bad Packet' only reported on debugging
 35  *              Alan Cox        :       Proxy arp.
 36  *              Alan Cox        :       skb->link3 maintained by letting the other xmit queue kill the packet.
 37  *              Alan Cox        :       Knows about type 3 devices (AX.25) using an AX.25 protocol ID not the ethernet
 38  *                                      one.
 39  *              Dominik Kubla   :       Better checking
 40  *              Tegge           :       Assorted corrections on cross port stuff
 41  *              Alan Cox        :       ATF_PERM was backwards! - might be useful now (sigh)
 42  *              Alan Cox        :       Arp timer added.
 43  *
 44  * To Fix:
 45  *                              :       arp response allocates an skbuff to send. However there is a perfectly
 46  *                                      good spare skbuff the right size about to be freed (the query). Use the
 47  *                                      query for the reply. This avoids an out of memory case _and_ speeds arp
 48  *                                      up.
 49  *                              :       FREE_READ v FREE_WRITE errors. Not critical as loopback arps don't occur
 50  *
 51  *
 52  *              This program is free software; you can redistribute it and/or
 53  *              modify it under the terms of the GNU General Public License
 54  *              as published by the Free Software Foundation; either version
 55  *              2 of the License, or (at your option) any later version.
 56  */
 57 #include <linux/types.h>
 58 #include <linux/string.h>
 59 #include <linux/kernel.h>
 60 #include <linux/sched.h>
 61 #include <linux/config.h>
 62 #include <linux/socket.h>
 63 #include <linux/sockios.h>
 64 #include <linux/timer.h>
 65 #include <linux/errno.h>
 66 #include <linux/if_arp.h>
 67 #include <linux/in.h>
 68 #include <asm/system.h>
 69 #include <asm/segment.h>
 70 #include <stdarg.h>
 71 #include "inet.h"
 72 #include "dev.h"
 73 #include "eth.h"
 74 #include "ip.h"
 75 #include "route.h"
 76 #include "protocol.h"
 77 #include "tcp.h"
 78 #include "skbuff.h"
 79 #include "sock.h"
 80 #include "arp.h"
 81 
 82 
 83 #define ARP_MAX_TRIES   3
 84 
 85 
 86 static char *unk_print(unsigned char *, int);
 87 static char *eth_aprint(unsigned char *, int);
 88 
 89 
 90 static char *arp_cmds[] = {
 91   "0x%04X",
 92   "REQUEST",
 93   "REPLY",
 94   "REVERSE REQUEST",
 95   "REVERSE REPLY",
 96   NULL
 97 };
 98 #define ARP_MAX_CMDS    (sizeof(arp_cmds) / sizeof(arp_cmds[0]))
 99 
100 static struct {
101   char  *name;
102   char  *(*print)(unsigned char *ptr, int len);
103 } arp_types[] = {
104   { "0x%04X",                   unk_print       },
105   { "10 Mbps Ethernet",         eth_aprint      },
106   { "3 Mbps Ethernet",          eth_aprint      },
107   { "AX.25",                    unk_print       },
108   { "Pronet",                   unk_print       },
109   { "Chaos",                    unk_print       },
110   { "IEEE 802.2 Ethernet (?)",  eth_aprint      },
111   { "Arcnet",                   unk_print       },
112   { "AppleTalk",                unk_print       },
113   { NULL,                       NULL            }
114 };
115 #define ARP_MAX_TYPE    (sizeof(arp_types) / sizeof(arp_types[0]))
116 
117 
118 struct arp_table *arp_tables[ARP_TABLE_SIZE] = {
119   NULL,
120 };
121 
122 static int arp_proxies=0;       /* So we can avoid the proxy arp 
123                                    overhead with the usual case of
124                                    no proxy arps */
125 
126 struct sk_buff * volatile arp_q = NULL;
127 
128 static struct arp_table *arp_lookup(unsigned long addr);
129 static struct arp_table *arp_lookup_proxy(unsigned long addr);
130 
131 /* Dump the ADDRESS bytes of an unknown hardware type. */
132 static char *
133 unk_print(unsigned char *ptr, int len)
134 {
135   static char buff[32];
136   char *bufp = buff;
137   int i;
138 
139   for (i = 0; i < len; i++)
140         bufp += sprintf(bufp, "%02X ", (*ptr++ & 0377));
141   return(buff);
142 }
143 
144 
145 /* Dump the ADDRESS bytes of an Ethernet hardware type. */
146 static char *
147 eth_aprint(unsigned char *ptr, int len)
148 {
149   if (len != ETH_ALEN) return("");
150   return(eth_print(ptr));
151 }
152 
153 
154 /* Dump an ARP packet. Not complete yet for non-Ethernet packets. */
155 static void
156 arp_print(struct arphdr *arp)
157 {
158   int len, idx;
159   unsigned char *ptr;
160 
161   if (inet_debug != DBG_ARP) return;
162 
163   printk("ARP: ");
164   if (arp == NULL) {
165         printk("(null)\n");
166         return;
167   }
168 
169   /* Print the opcode name. */
170   len = htons(arp->ar_op);
171   if (len < ARP_MAX_CMDS) idx = len;
172     else idx = 0;
173   printk("op ");
174   printk(arp_cmds[idx], len);
175 
176   /* Print the ARP header. */
177   len = htons(arp->ar_hrd);
178   if (len < ARP_MAX_TYPE) idx = len;
179     else idx = 0;
180   printk("   hrd = "); printk(arp_types[idx].name, len);
181   printk("   pro = 0x%04X\n", htons(arp->ar_pro));
182   printk("   hlen = %d plen = %d\n", arp->ar_hln, arp->ar_pln);
183 
184   /*
185    * Print the variable data.
186    * When ARP gets redone (after the formal introduction of NET-2),
187    * this part will be redone.  ARP will then be a multi-family address
188    * resolver, and the code below will be made more general. -FvK
189    */
190   ptr = ((unsigned char *) &arp->ar_op) + sizeof(u_short);
191   printk("   sender HA = %s ", arp_types[idx].print(ptr, arp->ar_hln));
192   ptr += arp->ar_hln;
193   printk("  PA = %s\n", in_ntoa(*(unsigned long *) ptr));
194   ptr += arp->ar_pln;
195   printk("   target HA = %s ", arp_types[idx].print(ptr, arp->ar_hln));
196   ptr += arp->ar_hln;
197   printk("  PA = %s\n", in_ntoa(*(unsigned long *) ptr));
198 }
199 
200 
201 /* This will try to retransmit everything on the queue. */
202 static void
203 arp_send_q(void)
204 {
205   struct sk_buff *skb;
206   struct sk_buff *volatile work_q;
207   cli();
208   work_q = arp_q;
209   skb_new_list_head(&work_q);
210   arp_q = NULL;
211   sti();
212   while((skb=skb_dequeue(&work_q))!=NULL)
213   {
214         IS_SKB(skb);
215         skb->magic = 0;
216         skb->next = NULL;
217         skb->prev = NULL;
218 
219         /* Decrement the 'tries' counter. */
220         cli();
221         skb->tries--;
222         if (skb->tries == 0) {
223                 /*
224                  * Grmpf.
225                  * We have tried ARP_MAX_TRIES to resolve the IP address
226                  * from this datagram.  This means that the machine does
227                  * not listen to our ARP requests.  Perhaps someone tur-
228                  * ned off the thing?
229                  * In any case, trying further is useless.  So, we kill
230                  * this packet from the queue.  (grinnik) -FvK
231                  */
232                 skb->sk = NULL;
233                 if(skb->free)
234                         kfree_skb(skb, FREE_WRITE);
235                         /* If free was 0, magic is now 0, next is 0 and 
236                            the write queue will notice and kill */
237                 sti();
238                 continue;
239         }
240 
241         /* Can we now complete this packet? */
242         sti();
243         if (skb->arp || !skb->dev->rebuild_header(skb->data, skb->dev)) {
244                 skb->arp  = 1;
245                 skb->dev->queue_xmit(skb, skb->dev, 0);
246         } else {
247                 /* Alas.  Re-queue it... */
248                 skb->magic = ARP_QUEUE_MAGIC;      
249                 skb_queue_head(&arp_q,skb);
250         }
251   }
252 }
253 
254 
255 static struct timer_list arp_timer;
256 
257 static void arp_queue_ticker(unsigned long data);
258 
259 static void arp_queue_kick(void)
260 {
261         arp_timer.expires = 500;        /* 5 seconds */
262         arp_timer.data = 0;
263         arp_timer.function = arp_queue_ticker;
264         del_timer(&arp_timer);
265         add_timer(&arp_timer);
266 }
267 
268 static void arp_queue_ticker(unsigned long data/*UNUSED*/)
269 {
270         arp_send_q();
271         if (skb_peek(&arp_q))
272                 arp_queue_kick();
273 }
274 
275 
276 
277 /* Create and send our response to an ARP request. */
278 static int
279 arp_response(struct arphdr *arp1, struct device *dev,  int addrtype)
280 {
281   struct arphdr *arp2;
282   struct sk_buff *skb;
283   unsigned long src, dst;
284   unsigned char *ptr1, *ptr2;
285   int hlen;
286   struct arp_table *apt = NULL;/* =NULL otherwise the compiler gives warnings */
287 
288   /* Decode the source (REQUEST) message. */
289   ptr1 = ((unsigned char *) &arp1->ar_op) + sizeof(u_short);
290   src = *((unsigned long *) (ptr1 + arp1->ar_hln));
291   dst = *((unsigned long *) (ptr1 + (arp1->ar_hln * 2) + arp1->ar_pln));
292   
293   if(addrtype!=IS_MYADDR)
294   {
295         apt=arp_lookup_proxy(dst);
296         if(apt==NULL)
297                 return(1);
298   }
299 
300   /* Get some mem and initialize it for the return trip. */
301   skb = alloc_skb(sizeof(struct sk_buff) +
302                 sizeof(struct arphdr) +
303                 (2 * arp1->ar_hln) + (2 * arp1->ar_pln) +
304                 dev->hard_header_len, GFP_ATOMIC);
305   if (skb == NULL) {
306         printk("ARP: no memory available for ARP REPLY!\n");
307         return(1);
308   }
309 
310   skb->mem_addr = skb;
311   skb->len      = sizeof(struct arphdr) + (2 * arp1->ar_hln) + 
312                   (2 * arp1->ar_pln) + dev->hard_header_len;
313   skb->mem_len  = sizeof(struct sk_buff) + skb->len;
314   hlen = dev->hard_header(skb->data, dev, ETH_P_ARP, src, dst, skb->len);
315   if (hlen < 0) {
316         printk("ARP: cannot create HW frame header for REPLY !\n");
317         kfree_skb(skb, FREE_WRITE);
318         return(1);
319   }
320 
321   /*
322    * Fill in the ARP REPLY packet.
323    * This looks ugly, but we have to deal with the variable-length
324    * ARP packets and such.  It is not as bad as it looks- FvK
325    */
326   arp2 = (struct arphdr *) (skb->data + hlen);
327   ptr2 = ((unsigned char *) &arp2->ar_op) + sizeof(u_short);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -