root/net/inet/arp.c

/* [previous][next][first][last][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. unk_print
  2. eth_aprint
  3. arp_print
  4. arp_send_q
  5. arp_response
  6. arp_lookup
  7. arp_destroy
  8. arp_create
  9. arp_rcv
  10. arp_send
  11. arp_find
  12. arp_add
  13. arp_add_broad
  14. arp_queue
  15. arp_get_info
  16. arp_req_set
  17. arp_req_get
  18. arp_req_del
  19. arp_ioctl

   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  *              Stephen A. Wood, <saw@hallc1.cebaf.gov>
  21  *              Arnt Gulbrandsen, <agulbra@pvv.unit.no>
  22  *
  23  *              This program is free software; you can redistribute it and/or
  24  *              modify it under the terms of the GNU General Public License
  25  *              as published by the Free Software Foundation; either version
  26  *              2 of the License, or (at your option) any later version.
  27  */
  28 #include <linux/types.h>
  29 #include <linux/string.h>
  30 #include <linux/kernel.h>
  31 #include <linux/sched.h>
  32 #include <linux/config.h>
  33 #include <linux/socket.h>
  34 #include <linux/sockios.h>
  35 #include <linux/errno.h>
  36 #include <linux/if_arp.h>
  37 #include <linux/in.h>
  38 #include <asm/system.h>
  39 #include <asm/segment.h>
  40 #include <stdarg.h>
  41 #include "inet.h"
  42 #include "dev.h"
  43 #include "eth.h"
  44 #include "ip.h"
  45 #include "route.h"
  46 #include "protocol.h"
  47 #include "tcp.h"
  48 #include "skbuff.h"
  49 #include "sock.h"
  50 #include "arp.h"
  51 
  52 
  53 #define ARP_MAX_TRIES   3
  54 
  55 
  56 static char *unk_print(unsigned char *, int);
  57 static char *eth_aprint(unsigned char *, int);
  58 
  59 
  60 static char *arp_cmds[] = {
  61   "0x%04X",
  62   "REQUEST",
  63   "REPLY",
  64   "REVERSE REQUEST",
  65   "REVERSE REPLY",
  66   NULL
  67 };
  68 #define ARP_MAX_CMDS    (sizeof(arp_cmds) / sizeof(arp_cmds[0]))
  69 
  70 static struct {
  71   char  *name;
  72   char  *(*print)(unsigned char *ptr, int len);
  73 } arp_types[] = {
  74   { "0x%04X",                   unk_print       },
  75   { "10 Mbps Ethernet",         eth_aprint      },
  76   { "3 Mbps Ethernet",          eth_aprint      },
  77   { "AX.25",                    unk_print       },
  78   { "Pronet",                   unk_print       },
  79   { "Chaos",                    unk_print       },
  80   { "IEEE 802.2 Ethernet (?)",  eth_aprint      },
  81   { "Arcnet",                   unk_print       },
  82   { "AppleTalk",                unk_print       },
  83   { NULL,                       NULL            }
  84 };
  85 #define ARP_MAX_TYPE    (sizeof(arp_types) / sizeof(arp_types[0]))
  86 
  87 
  88 struct arp_table *arp_tables[ARP_TABLE_SIZE] = {
  89   NULL,
  90 };
  91 struct sk_buff *arp_q = NULL;
  92 
  93 
  94 /* Dump the ADDRESS bytes of an unknown hardware type. */
  95 static char *
  96 unk_print(unsigned char *ptr, int len)
     /* [previous][next][first][last][top][bottom][index][help] */
  97 {
  98   static char buff[32];
  99   char *bufp = buff;
 100   int i;
 101 
 102   for (i = 0; i < len; i++)
 103         bufp += sprintf(bufp, "%02X ", (*ptr++ & 0377));
 104   return(buff);
 105 }
 106 
 107 
 108 /* Dump the ADDRESS bytes of an Ethernet hardware type. */
 109 static char *
 110 eth_aprint(unsigned char *ptr, int len)
     /* [previous][next][first][last][top][bottom][index][help] */
 111 {
 112   if (len != ETH_ALEN) return("");
 113   return(eth_print(ptr));
 114 }
 115 
 116 
 117 /* Dump an ARP packet. Not complete yet for non-Ethernet packets. */
 118 static void
 119 arp_print(struct arphdr *arp)
     /* [previous][next][first][last][top][bottom][index][help] */
 120 {
 121   int len, idx;
 122   unsigned char *ptr;
 123 
 124   if (inet_debug != DBG_ARP) return;
 125 
 126   printk("ARP: ");
 127   if (arp == NULL) {
 128         printk("(null)\n");
 129         return;
 130   }
 131 
 132   /* Print the opcode name. */
 133   len = htons(arp->ar_op);
 134   if (len < ARP_MAX_CMDS) idx = len;
 135     else idx = 0;
 136   printk("op ");
 137   printk(arp_cmds[idx], len);
 138 
 139   /* Print the ARP header. */
 140   len = htons(arp->ar_hrd);
 141   if (len < ARP_MAX_TYPE) idx = len;
 142     else idx = 0;
 143   printk("   hrd = "); printk(arp_types[idx].name, len);
 144   printk("   pro = 0x%04X\n", htons(arp->ar_pro));
 145   printk("   hlen = %d plen = %d\n", arp->ar_hln, arp->ar_pln);
 146 
 147   /*
 148    * Print the variable data.
 149    * When ARP gets redone (after the formal introduction of NET-2),
 150    * this part will be redone.  ARP will then be a multi-family address
 151    * resolver, and the code below will be made more general. -FvK
 152    */
 153   ptr = ((unsigned char *) &arp->ar_op) + sizeof(u_short);
 154   printk("   sender HA = %s ", arp_types[idx].print(ptr, arp->ar_hln));
 155   ptr += arp->ar_hln;
 156   printk("  PA = %s\n", in_ntoa(*(unsigned long *) ptr));
 157   ptr += arp->ar_pln;
 158   printk("   target HA = %s ", arp_types[idx].print(ptr, arp->ar_hln));
 159   ptr += arp->ar_hln;
 160   printk("  PA = %s\n", in_ntoa(*(unsigned long *) ptr));
 161 }
 162 
 163 
 164 /* This will try to retransmit everything on the queue. */
 165 static void
 166 arp_send_q(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 167 {
 168   struct sk_buff *skb;
 169   struct sk_buff *next;
 170 
 171   cli();
 172   next = arp_q;
 173   arp_q = NULL;
 174   sti();
 175   while ((skb = next) != NULL) {
 176         if (skb->magic != ARP_QUEUE_MAGIC) {
 177                 printk("ARP: *** Bug: skb with bad magic %X: squashing queue\n",
 178                                                                 skb->magic);
 179                 return;
 180         }
 181 
 182         /* Extra consistency check. */
 183         if (skb->next == NULL
 184 #ifdef CONFIG_MAX_16M
 185                 || ((unsigned long)(skb->next) > 16*1024*1024)
 186 #endif
 187                                                                 ) {
 188                 printk("ARP: *** Bug: bad skb->next, squashing queue\n");
 189                 return;
 190         }
 191 
 192         /* First remove skb from the queue. */
 193         next = skb->next;
 194         if (next != skb) {
 195                 skb->prev->next = next;
 196                 next->prev = skb->prev;
 197         } else {
 198                 next = NULL;
 199         }
 200 
 201         skb->magic = 0;
 202         skb->next = NULL;
 203         skb->prev = NULL;
 204 
 205         /* Decrement the 'tries' counter. */
 206         cli();
 207         skb->tries--;
 208         if (skb->tries == 0) {
 209                 /*
 210                  * Grmpf.
 211                  * We have tried ARP_MAX_TRIES to resolve the IP address
 212                  * from this datagram.  This means that the machine does
 213                  * not listen to our ARP requests.  Perhaps someone tur-
 214                  * ned off the thing?
 215                  * In any case, trying further is useless.  So, we kill
 216                  * this packet from the queue.  (grinnik) -FvK
 217                  */
 218                 skb->sk = NULL;
 219                 kfree_skb(skb, FREE_WRITE);
 220 
 221                 sti();
 222                 continue;
 223         }
 224 
 225         /* Can we now complete this packet? */
 226         sti();
 227         if (!skb->dev->rebuild_header(skb+1, skb->dev)) {
 228                 /* Yes, so send it out. */
 229                 skb->next = NULL;
 230                 skb->prev = NULL;
 231                 skb->arp  = 1;
 232                 skb->dev->queue_xmit(skb, skb->dev, 0);
 233         } else {
 234                 /* Alas.  Re-queue it... */
 235                 cli();
 236                 skb->magic = ARP_QUEUE_MAGIC;      
 237                 if (arp_q == NULL) {
 238                         skb->next = skb;
 239                         skb->prev = skb;
 240                         arp_q = skb;
 241                 } else {
 242                         skb->next = arp_q;
 243                         skb->prev = arp_q->prev;  
 244                         arp_q->prev->next = skb;
 245                         arp_q->prev = skb;
 246                 }
 247                 sti();
 248         }
 249   }
 250 }
 251 
 252 
 253 /* Create and send our response to an ARP request. */
 254 static int
 255 arp_response(struct arphdr *arp1, struct device *dev)
     /* [previous][next][first][last][top][bottom][index][help] */
 256 {
 257   struct arphdr *arp2;
 258   struct sk_buff *skb;
 259   unsigned long src, dst;
 260   unsigned char *ptr1, *ptr2;
 261   int hlen;
 262 
 263   /* Get some mem and initialize it for the return trip. */
 264   skb = (struct sk_buff *) kmalloc(sizeof(struct sk_buff) +
 265                 sizeof(struct arphdr) +
 266                 (2 * arp1->ar_hln) + (2 * arp1->ar_pln) +
 267                 dev->hard_header_len, GFP_ATOMIC);
 268   if (skb == NULL) {
 269         printk("ARP: no memory available for ARP REPLY!\n");
 270         return(1);
 271   }
 272 
 273   /* Decode the source (REQUEST) message. */
 274   ptr1 = ((unsigned char *) &arp1->ar_op) + sizeof(u_short);
 275   src = *((unsigned long *) (ptr1 + arp1->ar_hln));
 276   dst = *((unsigned long *) (ptr1 + (arp1->ar_hln * 2) + arp1->ar_pln));
 277 
 278   skb->lock     = 0;
 279   skb->mem_addr = skb;
 280   skb->len      = sizeof(struct arphdr) + (2 * arp1->ar_hln) + 
 281                   (2 * arp1->ar_pln) + dev->hard_header_len;
 282   skb->mem_len  = sizeof(struct sk_buff) + skb->len;
 283   hlen = dev->hard_header((unsigned char *)(skb+1), dev,
 284                          ETH_P_ARP, src, dst, skb->len);
 285   if (hlen < 0) {
 286         printk("ARP: cannot create HW frame header for REPLY !\n");
 287         return(1);
 288   }
 289 
 290   /*
 291    * Fill in the ARP REPLY packet.
 292    * This looks ugly, but we have to deal with the variable-length
 293    * ARP packets and such.  It is not as bad as it looks- FvK
 294    */
 295   arp2 = (struct arphdr *) ((unsigned char *) (skb+1) + hlen);
 296   ptr2 = ((unsigned char *) &arp2->ar_op) + sizeof(u_short);
 297   arp2->ar_hrd = arp1->ar_hrd;
 298   arp2->ar_pro = arp1->ar_pro;
 299   arp2->ar_hln = arp1->ar_hln;
 300   arp2->ar_pln = arp1->ar_pln;
 301   arp2->ar_op = htons(ARPOP_REPLY);
 302   memcpy(ptr2, dev->dev_addr, arp2->ar_hln);
 303   ptr2 += arp2->ar_hln;
 304   memcpy(ptr2, ptr1 + (arp1->ar_hln * 2) + arp1->ar_pln, arp2->ar_pln);
 305   ptr2 += arp2->ar_pln;
 306   memcpy(ptr2, ptr1, arp2->ar_hln);
 307   ptr2 += arp2->ar_hln;
 308   memcpy(ptr2, ptr1 + arp1->ar_hln, arp2->ar_pln);
 309 
 310   skb->free = 1;
 311   skb->arp = 1;
 312   skb->sk = NULL;
 313   skb->next = NULL;
 314 
 315   DPRINTF((DBG_ARP, ">>"));
 316   arp_print(arp2);
 317 
 318   /* Queue the packet for transmission. */
 319   dev->queue_xmit(skb, dev, 0);
 320   return(0);
 321 }
 322 
 323 
 324 /* This will find an entry in the ARP table by looking at the IP address. */
 325 static struct arp_table *
 326 arp_lookup(unsigned long paddr)
     /* [previous][next][first][last][top][bottom][index][help] */
 327 {
 328   struct arp_table *apt;
 329   unsigned long hash;
 330 
 331   DPRINTF((DBG_ARP, "ARP: lookup(%s)\n", in_ntoa(paddr)));
 332 
 333   /* We don't want to ARP ourselves. */
 334   if (chk_addr(paddr) == IS_MYADDR) {
 335         printk("ARP: ARPing my own IP address %s !\n", in_ntoa(paddr));
 336         return(NULL);
 337   }
 338 
 339   /* Loop through the table for the desired address. */
 340   hash = htonl(paddr) & (ARP_TABLE_SIZE - 1);
 341   cli();
 342   apt = arp_tables[hash];
 343   while(apt != NULL) {
 344         if (apt->ip == paddr) {
 345                 sti();
 346                 return(apt);
 347         }
 348         apt = apt->next;
 349   }
 350   sti();
 351   return(NULL);
 352 }
 353 
 354 
 355 /* Delete an ARP mapping entry in the cache. */
 356 void
 357 arp_destroy(unsigned long paddr)
     /* [previous][next][first][last][top][bottom][index][help] */
 358 {
 359   struct arp_table *apt;
 360   struct arp_table **lapt;
 361   unsigned long hash;
 362 
 363   DPRINTF((DBG_ARP, "ARP: destroy(%s)\n", in_ntoa(paddr)));
 364 
 365   /* We cannot destroy our own ARP entry. */
 366   if (chk_addr(paddr) == IS_MYADDR) {
 367         DPRINTF((DBG_ARP, "ARP: Destroying my own IP address %s !\n",
 368                                                         in_ntoa(paddr)));
 369         return;
 370   }
 371   hash = htonl(paddr) & (ARP_TABLE_SIZE - 1);
 372 
 373   cli();
 374   lapt = &arp_tables[hash];
 375   while ((apt = *lapt) != NULL) {
 376         if (apt->ip == paddr) {
 377                 *lapt = apt->next;
 378                 kfree_s(apt, sizeof(struct arp_table));
 379                 sti();
 380                 return;
 381         }
 382         lapt = &apt->next;
 383   }
 384   sti();
 385 }
 386 
 387 
 388 /* Create an ARP entry.  The caller should check for duplicates! */
 389 static struct arp_table *
 390 arp_create(unsigned long paddr, unsigned char *addr, int hlen, int htype)
     /* [previous][next][first][last][top][bottom][index][help] */
 391 {
 392   struct arp_table *apt;
 393   unsigned long hash;
 394 
 395   DPRINTF((DBG_ARP, "ARP: create(%s, ", in_ntoa(paddr)));
 396   DPRINTF((DBG_ARP, "%s, ", eth_print(addr)));
 397   DPRINTF((DBG_ARP, "%d, %d)\n", hlen, htype));
 398 
 399   apt = (struct arp_table *) kmalloc(sizeof(struct arp_table), GFP_ATOMIC);
 400   if (apt == NULL) {
 401         printk("ARP: no memory available for new ARP entry!\n");
 402         return(NULL);
 403   }
 404 
 405   /* Fill in the allocated ARP cache entry. */
 406   hash = htonl(paddr) & (ARP_TABLE_SIZE - 1);
 407   apt->ip = paddr;
 408   apt->hlen = hlen;
 409   apt->htype = htype;
 410   apt->flags = (ATF_INUSE | ATF_COM);   /* USED and COMPLETED entry */
 411   memcpy(apt->ha, addr, hlen);
 412   apt->last_used = jiffies;
 413   cli();
 414   apt->next = arp_tables[hash];
 415   arp_tables[hash] = apt;
 416   sti();
 417   return(apt);
 418 }
 419 
 420 
 421 /*
 422  * An ARP REQUEST packet has arrived.
 423  * We try to be smart here, and fetch the data of the sender of the
 424  * packet- we might need it later, so fetching it now can save us a
 425  * broadcast later.
 426  * Then, if the packet was meant for us (i.e. the TARGET address was
 427  * one of our own IP addresses), we set up and send out an ARP REPLY
 428  * packet to the sender.
 429  */
 430 int
 431 arp_rcv(struct sk_buff *skb, struct device *dev, struct packet_type *pt)
     /* [previous][next][first][last][top][bottom][index][help] */
 432 {
 433   struct arphdr *arp;
 434   struct arp_table *tbl;
 435   unsigned long src, dst;
 436   unsigned char *ptr;
 437   int ret;
 438 
 439   DPRINTF((DBG_ARP, "<<\n"));
 440   arp = skb->h.arp;
 441   arp_print(arp);
 442 
 443   /* If this test doesn't pass, something fishy is going on. */
 444   if (arp->ar_hln != dev->addr_len || dev->type != NET16(arp->ar_hrd)) {
 445         printk("ARP: Bad packet received on device \"%s\" !\n", dev->name);
 446         kfree_skb(skb, FREE_READ);
 447         return(0);
 448   }
 449 
 450   /* For now we will only deal with IP addresses. */
 451   if (arp->ar_pro != NET16(ETH_P_IP) || arp->ar_pln != 4) {
 452         if (arp->ar_op != NET16(ARPOP_REQUEST))
 453                 printk("ARP: Non-IP request on device \"%s\" !\n", dev->name);
 454         kfree_skb(skb, FREE_READ);
 455         return(0);
 456   }
 457 
 458   /*
 459    * As said before, we try to be smart by using the
 460    * info already present in the packet: the sender's
 461    * IP and hardware address.
 462    */
 463   ptr = ((unsigned char *) &arp->ar_op) + sizeof(u_short);
 464   memcpy(&src, ptr + arp->ar_hln, arp->ar_pln);
 465   tbl = arp_lookup(src);
 466   if (tbl != NULL) {
 467         DPRINTF((DBG_ARP, "ARP: udating entry for %s\n", in_ntoa(src)));
 468         memcpy(tbl->ha, ptr, arp->ar_hln);
 469         tbl->hlen = arp->ar_hln;
 470         tbl->flags |= ATF_COM;
 471         tbl->last_used = jiffies;
 472   } else {
 473         memcpy(&dst, ptr + (arp->ar_hln * 2) + arp->ar_pln, arp->ar_pln);
 474         if (chk_addr(dst) != IS_MYADDR) {
 475                 kfree_skb(skb, FREE_READ);
 476                 return(0);
 477         } else {
 478                 tbl = arp_create(src, ptr, arp->ar_hln, arp->ar_hrd);
 479                 if (tbl == NULL) {
 480                         kfree_skb(skb, FREE_READ);
 481                         return(0);
 482                 }
 483         }
 484   }
 485 
 486   /*
 487    * Since we updated the ARP cache, we might have enough
 488    * information to send out some previously queued IP
 489    * datagrams....
 490    */
 491   arp_send_q();
 492 
 493   /*
 494    * OK, we used that part of the info.  Now check if the
 495    * request was an ARP REQUEST for one of our own addresses...
 496    */
 497   if (arp->ar_op != NET16(ARPOP_REQUEST)) {
 498         kfree_skb(skb, FREE_READ);
 499         return(0);
 500   }
 501   memcpy(&dst, ptr + (arp->ar_hln * 2) + arp->ar_pln, arp->ar_pln);
 502   if (chk_addr(dst) != IS_MYADDR) {
 503         DPRINTF((DBG_ARP, "ARP: request was not for me!\n"));
 504         kfree_skb(skb, FREE_READ);
 505         return(0);
 506   }
 507 
 508   /*
 509    * Yes, it is for us.
 510    * Allocate, fill in and send an ARP REPLY packet.
 511    */
 512   ret = arp_response(arp, dev);
 513   kfree_skb(skb, FREE_READ);
 514   return(ret);
 515 }
 516 
 517 
 518 /* Create and send an ARP REQUEST packet. */
 519 void
 520 arp_send(unsigned long paddr, struct device *dev, unsigned long saddr)
     /* [previous][next][first][last][top][bottom][index][help] */
 521 {
 522   struct sk_buff *skb;
 523   struct arphdr *arp;
 524   unsigned char *ptr;
 525   int tmp;
 526 
 527   DPRINTF((DBG_ARP, "ARP: send(paddr=%s, ", in_ntoa(paddr)));
 528   DPRINTF((DBG_ARP, "dev=%s, ", dev->name));
 529   DPRINTF((DBG_ARP, "saddr=%s)\n", in_ntoa(saddr)));
 530 
 531   skb = (struct sk_buff *) kmalloc(sizeof(struct sk_buff) +
 532                 sizeof(struct arphdr) + (2 * dev->addr_len) +
 533                 dev->hard_header_len +
 534                 (2 * 4 /* arp->plen */), GFP_ATOMIC);
 535   if (skb == NULL) {
 536         printk("ARP: No memory available for REQUEST %s\n", in_ntoa(paddr));
 537         return;
 538   }
 539   
 540   /* Fill in the request. */
 541   skb->lock = 0;
 542   skb->sk = NULL;
 543   skb->mem_addr = skb;
 544   skb->len = sizeof(struct arphdr) +
 545              dev->hard_header_len + (2 * dev->addr_len) + 8;
 546   skb->mem_len = sizeof(struct sk_buff) + skb->len;
 547   skb->arp = 1;
 548   skb->dev = dev;
 549   skb->next = NULL;
 550   tmp = dev->hard_header((unsigned char *)(skb+1), dev,
 551                           ETH_P_ARP, 0, saddr, skb->len);
 552   if (tmp < 0) {
 553         kfree_s(skb->mem_addr, skb->mem_len);
 554         return;
 555   }
 556   arp = (struct arphdr *) ((unsigned char *) (skb+1) + tmp);
 557   arp->ar_hrd = htons(dev->type);
 558   arp->ar_pro = htons(ETH_P_IP);
 559   arp->ar_hln = dev->addr_len;
 560   arp->ar_pln = 4;
 561   arp->ar_op = htons(ARPOP_REQUEST);
 562 
 563   ptr = ((unsigned char *) &arp->ar_op) + sizeof(u_short);
 564   memcpy(ptr, dev->dev_addr, arp->ar_hln);
 565   ptr += arp->ar_hln;
 566   memcpy(ptr, &saddr, arp->ar_pln);
 567   ptr += arp->ar_pln;
 568   memcpy(ptr, dev->broadcast, arp->ar_hln);
 569   ptr += arp->ar_hln;
 570   memcpy(ptr, &paddr, arp->ar_pln);
 571 
 572   DPRINTF((DBG_ARP, ">>\n"));
 573   arp_print(arp);
 574   dev->queue_xmit(skb, dev, 0);
 575 }
 576 
 577 
 578 /* Find an ARP mapping in the cache. If not found, post a REQUEST. */
 579 int
 580 arp_find(unsigned char *haddr, unsigned long paddr, struct device *dev,
     /* [previous][next][first][last][top][bottom][index][help] */
 581            unsigned long saddr)
 582 {
 583   struct arp_table *apt;
 584 
 585   DPRINTF((DBG_ARP, "ARP: find(haddr=%s, ", eth_print(haddr)));
 586   DPRINTF((DBG_ARP, "paddr=%s, ", in_ntoa(paddr)));
 587   DPRINTF((DBG_ARP, "dev=%s, saddr=%s)\n", dev->name, in_ntoa(saddr)));
 588 
 589   switch(chk_addr(paddr)) {
 590         case IS_MYADDR:
 591                 memcpy(haddr, dev->dev_addr, dev->addr_len);
 592                 return(0);
 593         case IS_BROADCAST:
 594                 memcpy(haddr, dev->broadcast, dev->addr_len);
 595                 return(0);
 596   }
 597                 
 598   apt = arp_lookup(paddr);
 599   if (apt != NULL) {
 600         /*
 601          * Make sure it's not too old. If it is too old, we will
 602          * just pretend we did not find it, and then arp_send will
 603          * verify the address for us.
 604          */
 605         if ((!(apt->flags & ATF_PERM)) ||
 606             (!before(apt->last_used, jiffies+ARP_TIMEOUT) && apt->hlen != 0)) {
 607                 apt->last_used = jiffies;
 608                 memcpy(haddr, apt->ha, dev->addr_len);
 609                 return(0);
 610         } else {
 611                 DPRINTF((DBG_ARP, "ARP: find: found expired entry for %s\n",
 612                                                         in_ntoa(apt->ip)));
 613         }
 614   }
 615 
 616   /*
 617    * This assume haddr are at least 4 bytes.
 618    * If this isn't true we can use a lookup table, one for every dev.
 619    * NOTE: this bit of code still looks fishy to me- FvK
 620    */
 621   *(unsigned long *)haddr = paddr;
 622 
 623   /* If we didn't find an entry, we will try to send an ARP packet. */
 624   arp_send(paddr, dev, saddr);
 625 
 626   return(1);
 627 }
 628 
 629 
 630 /* Add an entry to the ARP cache.  Check for dupes! */
 631 void
 632 arp_add(unsigned long addr, unsigned char *haddr, struct device *dev)
     /* [previous][next][first][last][top][bottom][index][help] */
 633 {
 634   struct arp_table *apt;
 635 
 636   DPRINTF((DBG_ARP, "ARP: add(%s, ", in_ntoa(addr)));
 637   DPRINTF((DBG_ARP, "%s, ", eth_print(haddr)));
 638   DPRINTF((DBG_ARP, "%d, %d)\n", dev->hard_header_len, dev->type));
 639 
 640   /* This is probably a good check... */
 641   if (addr == 0) {
 642         printk("ARP: add: will not add entry for 0.0.0.0 !\n");
 643         return;
 644   }
 645 
 646   /* First see if the address is already in the table. */
 647   apt = arp_lookup(addr);
 648   if (apt != NULL) {
 649         DPRINTF((DBG_ARP, "ARP: updating entry for %s\n", in_ntoa(addr)));
 650         apt->last_used = jiffies;
 651         memcpy(apt->ha, haddr , dev->addr_len);
 652         return;
 653   }
 654   arp_create(addr, haddr, dev->addr_len, dev->type);
 655 }
 656 
 657 
 658 /* Create an ARP entry for a device's broadcast address. */
 659 void
 660 arp_add_broad(unsigned long addr, struct device *dev)
     /* [previous][next][first][last][top][bottom][index][help] */
 661 {
 662   struct arp_table *apt;
 663 
 664   arp_add(addr, dev->broadcast, dev);
 665   apt = arp_lookup(addr);
 666   if (apt != NULL) {
 667         apt->flags |= ATF_PERM;
 668   }
 669 }
 670 
 671 
 672 /* Queue an IP packet, while waiting for the ARP reply packet. */
 673 void
 674 arp_queue(struct sk_buff *skb)
     /* [previous][next][first][last][top][bottom][index][help] */
 675 {
 676   cli();
 677   skb->tries = ARP_MAX_TRIES;
 678 
 679   if (skb->next != NULL) {
 680         sti();
 681         printk("ARP: arp_queue skb already on queue magic=%X.\n", skb->magic);
 682         return;
 683   }
 684   if (arp_q == NULL) {
 685         arp_q = skb;
 686         skb->next = skb;
 687         skb->prev = skb;
 688   } else {
 689         skb->next = arp_q;
 690         skb->prev = arp_q->prev;
 691         skb->next->prev = skb;
 692         skb->prev->next = skb;
 693   }
 694   skb->magic = ARP_QUEUE_MAGIC;
 695   sti();
 696 }
 697 
 698 
 699 /*
 700  * Write the contents of the ARP cache to a PROCfs file.
 701  * This is not by long perfect, as the internal ARP table doesn't
 702  * have all the info we would like to have.  Oh well, it works for
 703  * now, eh? - FvK
 704  * Also note, that due to space limits, we cannot generate more than
 705  * 4Kbyte worth of data.  This usually is enough, but I have seen
 706  * machines die from under me because of a *very* large ARP cache.
 707  * This can be simply tested by doing:
 708  *
 709  *      # ping 255.255.255.255
 710  *      # arp -a
 711  *
 712  * Perhaps we should redo PROCfs to handle larger buffers?  Michael?
 713  */
 714 int
 715 arp_get_info(char *buffer)
     /* [previous][next][first][last][top][bottom][index][help] */
 716 {
 717   struct arpreq *req;
 718   struct arp_table *apt;
 719   int i;
 720   char *pos;
 721 
 722   /* Loop over the ARP table and copy structures to the buffer. */
 723   pos = buffer;
 724   i = 0;
 725   for (i = 0; i < ARP_TABLE_SIZE; i++) {
 726         cli();
 727         apt = arp_tables[i];
 728         sti();
 729         while (apt != NULL) {
 730                 if (pos < (buffer + 4000)) {
 731                         req = (struct arpreq *) pos;
 732                         memset((char *) req, 0, sizeof(struct arpreq));
 733                         req->arp_pa.sa_family = AF_INET;
 734                         memcpy((char *) req->arp_pa.sa_data, (char *) &apt->ip, 4);
 735                                 req->arp_ha.sa_family = apt->htype;
 736                         memcpy((char *) req->arp_ha.sa_data,
 737                                 (char *) &apt->ha, apt->hlen);
 738                 }
 739                 pos += sizeof(struct arpreq);
 740                 cli();
 741                 apt = apt->next;
 742                 sti();
 743         }
 744   }
 745   return(pos - buffer);
 746 }
 747 
 748 
 749 /* Set (create) an ARP cache entry. */
 750 static int
 751 arp_req_set(struct arpreq *req)
     /* [previous][next][first][last][top][bottom][index][help] */
 752 {
 753   struct arpreq r;
 754   struct arp_table *apt;
 755   struct sockaddr_in *si;
 756   int htype, hlen;
 757 
 758   /* We only understand about IP addresses... */
 759   memcpy_fromfs(&r, req, sizeof(r));
 760   if (r.arp_pa.sa_family != AF_INET) return(-EPFNOSUPPORT);
 761 
 762   /*
 763    * Find out about the hardware type.
 764    * We have to be compatible with BSD UNIX, so we have to
 765    * assume that a "not set" value (i.e. 0) means Ethernet.
 766    */
 767   si = (struct sockaddr_in *) &r.arp_pa;
 768   switch(r.arp_ha.sa_family) {
 769         case 0:
 770         case ARPHRD_ETHER:
 771                 htype = ARPHRD_ETHER;
 772                 hlen = ETH_ALEN;
 773                 break;
 774         default:
 775                 return(-EPFNOSUPPORT);
 776   }
 777 
 778   /* Is there an existing entry for this address? */
 779   if (si->sin_addr.s_addr == 0) {
 780         printk("ARP: SETARP: requested PA is 0.0.0.0 !\n");
 781         return(-EINVAL);
 782   }
 783   apt = arp_lookup(si->sin_addr.s_addr);
 784   if (apt == NULL) {
 785         apt = arp_create(si->sin_addr.s_addr,
 786                 (unsigned char *) r.arp_ha.sa_data, hlen, htype);
 787         if (apt == NULL) return(-ENOMEM);
 788   }
 789 
 790   /* We now have a pointer to an ARP entry.  Update it! */
 791   memcpy((char *) &apt->ha, (char *) &r.arp_ha.sa_data, hlen);
 792   apt->last_used = jiffies;
 793   apt->flags = r.arp_flags;
 794 
 795   return(0);
 796 }
 797 
 798 
 799 /* Get an ARP cache entry. */
 800 static int
 801 arp_req_get(struct arpreq *req)
     /* [previous][next][first][last][top][bottom][index][help] */
 802 {
 803   struct arpreq r;
 804   struct arp_table *apt;
 805   struct sockaddr_in *si;
 806 
 807   /* We only understand about IP addresses... */
 808   memcpy_fromfs(&r, req, sizeof(r));
 809   if (r.arp_pa.sa_family != AF_INET) return(-EPFNOSUPPORT);
 810 
 811   /* Is there an existing entry for this address? */
 812   si = (struct sockaddr_in *) &r.arp_pa;
 813   apt = arp_lookup(si->sin_addr.s_addr);
 814   if (apt == NULL) return(-ENXIO);
 815 
 816   /* We found it; copy into structure. */
 817   memcpy((char *) r.arp_ha.sa_data, (char *) &apt->ha, apt->hlen);
 818   r.arp_ha.sa_family = apt->htype;
 819 
 820   /* Copy the information back */
 821   memcpy_tofs(req, &r, sizeof(r));
 822   return(0);
 823 }
 824 
 825 
 826 /* Delete an ARP cache entry. */
 827 static int
 828 arp_req_del(struct arpreq *req)
     /* [previous][next][first][last][top][bottom][index][help] */
 829 {
 830   struct arpreq r;
 831   struct sockaddr_in *si;
 832 
 833   /* We only understand about IP addresses... */
 834   memcpy_fromfs(&r, req, sizeof(r));
 835   if (r.arp_pa.sa_family != AF_INET) return(-EPFNOSUPPORT);
 836 
 837   si = (struct sockaddr_in *) &r.arp_pa;
 838   arp_destroy(si->sin_addr.s_addr);
 839 
 840   return(0);
 841 }
 842 
 843 
 844 /* Handle an ARP layer I/O control request. */
 845 int
 846 arp_ioctl(unsigned int cmd, void *arg)
     /* [previous][next][first][last][top][bottom][index][help] */
 847 {
 848   switch(cmd) {
 849         case DDIOCSDBG:
 850                 return(dbg_ioctl(arg, DBG_ARP));
 851         case SIOCDARP:
 852                 if (!suser()) return(-EPERM);
 853                 return(arp_req_del((struct arpreq *)arg));
 854         case SIOCGARP:
 855                 return(arp_req_get((struct arpreq *)arg));
 856         case SIOCSARP:
 857                 if (!suser()) return(-EPERM);
 858                 return(arp_req_set((struct arpreq *)arg));
 859         default:
 860                 return(-EINVAL);
 861   }
 862   /*NOTREACHED*/
 863   return(0);
 864 }

/* [previous][next][first][last][top][bottom][index][help] */