root/net/tcp/arp.c

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

DEFINITIONS

This source file includes following definitions.
  1. send_arp_q
  2. print_arp
  3. arp_sourceh
  4. arp_targeth
  5. arp_sourcep
  6. arp_targetp
  7. arp_free
  8. arp_malloc
  9. arp_response
  10. arp_lookup
  11. arp_destroy
  12. create_arp
  13. arp_rcv
  14. arp_snd
  15. arp_find
  16. arp_add
  17. arp_add_broad
  18. arp_queue

   1 /* arp.c */
   2 /*
   3     Copyright (C) 1992  Ross Biro
   4 
   5     This program is free software; you can redistribute it and/or modify
   6     it under the terms of the GNU General Public License as published by
   7     the Free Software Foundation; either version 2, or (at your option)
   8     any later version.
   9 
  10     This program is distributed in the hope that it will be useful,
  11     but WITHOUT ANY WARRANTY; without even the implied warranty of
  12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13     GNU General Public License for more details.
  14 
  15     You should have received a copy of the GNU General Public License
  16     along with this program; if not, write to the Free Software
  17     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 
  18 
  19     The Author may be reached as bir7@leland.stanford.edu or
  20     C/O Department of Mathematics; Stanford University; Stanford, CA 94305
  21 */
  22 /* $Id: arp.c,v 0.8.4.5 1992/12/12 19:25:04 bir7 Exp $ */
  23 /* $Log: arp.c,v $
  24  * Revision 0.8.4.5  1992/12/12  19:25:04  bir7
  25  * Cleaned up Log messages.
  26  *
  27  * Revision 0.8.4.4  1992/12/03  19:52:20  bir7
  28  * Added paranoid queue checking.
  29  *
  30  * Revision 0.8.4.3  1992/11/15  14:55:30  bir7
  31  * Put more cli/sti pairs in send_q and another sanity check
  32  * in arp_queue.
  33  *
  34  * Revision 0.8.4.2  1992/11/10  10:38:48  bir7
  35  * Change free_s to kfree_s and accidently changed free_skb to kfree_skb.
  36  *
  37  * Revision 0.8.4.1  1992/11/10  00:17:18  bir7
  38  * version change only.
  39  *
  40  * Revision 0.8.3.3  1992/11/10  00:14:47  bir7
  41  * Changed malloc to kmalloc and added Id and Log
  42  *
  43  */
  44 
  45 #include <linux/types.h>
  46 #include <linux/string.h>
  47 #include <linux/kernel.h>
  48 #include <linux/sched.h>
  49 #include <linux/config.h>
  50 
  51 #include <linux/socket.h>
  52 #include <netinet/in.h>
  53 #include <asm/system.h>
  54 
  55 #include "timer.h"
  56 #include "ip.h"
  57 #include "tcp.h"
  58 #include "sock.h"
  59 #include "arp.h"
  60 
  61 #undef ARP_DEBUG
  62 
  63 #ifdef  ARP_DEBUG
  64 #define PRINTK(x) printk x
  65 #else
  66 #define PRINTK(x) /**/
  67 #endif
  68 
  69 static struct arp_table *arp_table[ARP_TABLE_SIZE] ={NULL, };
  70 struct sk_buff *arp_q=NULL;
  71 
  72 /* this will try to retransmit everything on the queue. */
  73 static void
  74 send_arp_q(void)
     /* [previous][next][first][last][top][bottom][index][help] */
  75 {
  76    struct sk_buff *skb;
  77    struct sk_buff *next;
  78 
  79    cli();
  80    next = arp_q;
  81    arp_q = NULL;
  82    sti();
  83    while ((skb = next) != NULL) {
  84      if (skb->magic != ARP_QUEUE_MAGIC)
  85        {
  86          printk ("arp.c skb with bad magic - %X: squashing queue\n", skb->magic);
  87          return;
  88        }
  89      /* extra consistancy check. */
  90      if (skb->next == NULL
  91 #ifdef CONFIG_MAX_16M
  92          || (unsigned long)(skb->next) > 16*1024*1024
  93 #endif
  94          )
  95        {
  96          printk ("dev.c: *** bug bad skb->next, squashing queue \n");
  97          return;
  98        }
  99 
 100      /* first remove skb from the queue. */
 101      next = skb->next;
 102      if (next == skb)
 103        {
 104          next = NULL;
 105        }
 106      else
 107        {
 108          skb->prev->next = next;
 109          next->prev = skb->prev;
 110        }
 111 
 112      skb->magic = 0;
 113      skb->next = NULL;
 114      skb->prev = NULL;
 115 
 116      if (!skb->dev->rebuild_header (skb+1, skb->dev))
 117        {
 118            skb->next = NULL;
 119            skb->prev = NULL;
 120            skb->arp  = 1;
 121            skb->dev->queue_xmit (skb, skb->dev, 0);
 122         }
 123      else
 124        {
 125          cli();
 126          skb->magic = ARP_QUEUE_MAGIC;      
 127          if (arp_q == NULL)
 128            {
 129              skb->next = skb;
 130              skb->prev = skb;
 131              arp_q = skb;
 132            }
 133          else
 134            {
 135              skb->next = arp_q;
 136              skb->prev = arp_q->prev;  
 137              arp_q->prev->next = skb;
 138              arp_q->prev = skb;
 139            }
 140          sti();
 141        }
 142    }
 143 }
 144 
 145 static  void
 146 print_arp(struct arp *arp)
     /* [previous][next][first][last][top][bottom][index][help] */
 147 {
 148   int i;
 149   unsigned long *lptr;
 150   unsigned char *ptr;
 151   PRINTK (("arp: \n"));
 152   if (arp == NULL)
 153     {
 154       PRINTK (("(null)\n"));
 155       return;
 156     }
 157   PRINTK (("   hrd = %d\n",net16(arp->hrd)));
 158   PRINTK (("   pro = %d\n",net16(arp->pro)));
 159   PRINTK (("   hlen = %d plen = %d\n",arp->hlen, arp->plen));
 160   PRINTK (("   op = %d\n", net16(arp->op)));
 161   ptr = (unsigned char *)(arp+1);
 162   PRINTK (("   sender haddr = "));
 163   for (i = 0; i < arp->hlen; i++)
 164     {
 165       PRINTK (("0x%02X ",*ptr++));
 166     }
 167   lptr = (void *)ptr;
 168   PRINTK ((" send paddr = %X\n",*lptr));
 169   lptr ++;
 170   ptr = (void *)lptr;
 171   PRINTK (("   destination haddr = "));
 172   for (i = 0; i < arp->hlen; i++)
 173     {
 174       PRINTK (("0x%02X ",*ptr++));
 175     }
 176   lptr = (void *)ptr;
 177   PRINTK ((" destination paddr = %X\n",*lptr));
 178 }
 179 
 180 static  unsigned char *
 181 arp_sourceh(struct arp *arp)
     /* [previous][next][first][last][top][bottom][index][help] */
 182 {
 183   unsigned char *ptr;
 184   ptr = (unsigned char *)(arp + 1);
 185   return (ptr);
 186 }
 187 
 188 static  unsigned char *
 189 arp_targeth(struct arp *arp)
     /* [previous][next][first][last][top][bottom][index][help] */
 190 {
 191   unsigned char *ptr;
 192   ptr = (unsigned char *)(arp + 1);
 193   ptr += arp->hlen+4;
 194   return (ptr);
 195 }
 196 
 197 static  unsigned long *
 198 arp_sourcep(struct arp *arp)
     /* [previous][next][first][last][top][bottom][index][help] */
 199 {
 200   unsigned long *lptr;
 201   unsigned char *ptr;
 202   ptr = (unsigned char *)(arp + 1);
 203   ptr += arp->hlen;
 204   lptr = (unsigned long *)ptr;
 205   return (lptr);
 206 }
 207 
 208 
 209 static  unsigned long *
 210 arp_targetp(struct arp *arp)
     /* [previous][next][first][last][top][bottom][index][help] */
 211 {
 212   unsigned long *lptr;
 213   unsigned char *ptr;
 214   ptr = (unsigned char *)(arp + 1);
 215   ptr += 2*arp->hlen+4;
 216   lptr = (unsigned long *)ptr;
 217   return (lptr);
 218 }
 219 
 220 static  void
 221 arp_free (void *ptr, unsigned long len)
     /* [previous][next][first][last][top][bottom][index][help] */
 222 {
 223   kfree_s(ptr, len);
 224 }
 225 
 226 static  void *
 227 arp_malloc (unsigned long amount, int priority)
     /* [previous][next][first][last][top][bottom][index][help] */
 228 {
 229   return (kmalloc (amount, priority));
 230 }
 231 
 232 static  int
 233 arp_response (struct arp *arp1, struct device *dev)
     /* [previous][next][first][last][top][bottom][index][help] */
 234 {
 235   struct arp *arp2;
 236   struct sk_buff *skb;
 237   int tmp;
 238 
 239   /* get some mem and initialize it for the return trip. */
 240   skb = arp_malloc (sizeof (*skb) + sizeof (*arp2) +
 241                     2*arp1->hlen + 2*arp1->plen + dev->hard_header_len,
 242                     GFP_ATOMIC);
 243   if (skb == NULL) return (1);
 244 
 245   skb->lock = 0;
 246   skb->mem_addr = skb;
 247   skb->mem_len = sizeof (*skb) + sizeof (*arp2) + 2*arp1->hlen + 
 248     2*arp1->plen + dev->hard_header_len;
 249   skb->len = sizeof (*arp2) + 2*arp1->hlen + 
 250     2*arp1->plen + dev->hard_header_len;
 251 
 252   tmp = dev->hard_header((unsigned char *)(skb+1), dev,
 253                          ETHERTYPE_ARP, *arp_sourcep(arp1),
 254                          *arp_targetp(arp1),skb->len);
 255 
 256   if (tmp < 0) return (1);
 257 
 258   arp2 =(struct arp *) ((unsigned char *)skb+sizeof (*skb) + tmp );
 259   memcpy (arp2, arp1, sizeof (*arp2));
 260 
 261   /* now swap the addresses. */
 262   *arp_sourcep(arp2) = *arp_targetp(arp1);
 263   memcpy(arp_sourceh(arp2), dev->dev_addr, arp1->hlen);
 264 
 265   *arp_targetp(arp2) = *arp_sourcep(arp1);
 266   memcpy(arp_targeth(arp2), arp_sourceh(arp1), arp1->hlen);
 267 
 268   arp2->op = NET16(ARP_REPLY);
 269   skb->free = 1;
 270   skb->arp = 1; /* so the code will know it's not waiting on an arp. */
 271   skb->sk = NULL;
 272   skb->next = NULL;
 273   PRINTK ((">>"));
 274   print_arp(arp2);
 275   /* send it. */
 276   dev->queue_xmit (skb, dev, 0);
 277   return (0);
 278 }
 279 
 280 /* This will find an entry in the arp table by looking at the ip
 281    address. */
 282 static  struct arp_table *
 283 arp_lookup (unsigned long paddr)
     /* [previous][next][first][last][top][bottom][index][help] */
 284 {
 285   unsigned long hash;
 286   struct arp_table *apt;
 287   PRINTK (("arp_lookup(paddr=%X)\n", paddr));
 288   /* we don't want to arp ourselves. */
 289   if (my_ip_addr(paddr)) return (NULL);
 290   hash = net32(paddr) & (ARP_TABLE_SIZE - 1);
 291   cli();
 292   for (apt = arp_table[hash]; apt != NULL; apt = apt->next)
 293     {
 294       if (apt->ip == paddr)
 295         {
 296            sti();
 297            return (apt);
 298         }
 299     }
 300   sti();
 301   return (NULL);
 302 }
 303 
 304 void
 305 arp_destroy(unsigned long paddr)
     /* [previous][next][first][last][top][bottom][index][help] */
 306 {
 307   unsigned long hash;
 308   struct arp_table *apt;
 309   struct arp_table *lapt;
 310   PRINTK (("arp_destroy (paddr=%X)\n",paddr));
 311   /* we don't want to destroy are own arp */
 312   if (my_ip_addr(paddr)) return;
 313   hash = net32(paddr) & (ARP_TABLE_SIZE - 1);
 314 
 315   cli(); /* can't be interrupted. */
 316   /* make sure there is something there. */
 317   if (arp_table[hash] == NULL) return;
 318 
 319   /* check the first one. */
 320   if (arp_table[hash]->ip == paddr)
 321     {
 322       apt = arp_table[hash];
 323       arp_table[hash] = arp_table[hash]->next;
 324       arp_free (apt, sizeof (*apt));
 325       sti();
 326       return;
 327     }
 328 
 329   /* now deal with it any where else in the chain. */
 330   lapt = arp_table[hash];
 331   for (apt = arp_table[hash]->next; apt != NULL; apt = apt->next)
 332     {
 333       if (apt->ip == paddr) 
 334         {
 335           lapt->next = apt->next;
 336           arp_free (apt, sizeof (*apt));
 337           sti();
 338           return;
 339         }
 340     }
 341   sti();
 342 }
 343 
 344 /* this routine does not check for duplicates.  It assumes the caller
 345    does. */
 346 static  struct arp_table *
 347 create_arp (unsigned long paddr, unsigned char *addr, int hlen)
     /* [previous][next][first][last][top][bottom][index][help] */
 348 {
 349   struct arp_table *apt;
 350   unsigned long hash;
 351   apt = arp_malloc (sizeof (*apt), GFP_ATOMIC);
 352   if (apt == NULL) return (NULL);
 353 
 354   hash = net32(paddr) & (ARP_TABLE_SIZE - 1);
 355   apt->ip = paddr;
 356   apt->hlen =hlen;
 357   memcpy (apt->hard, addr, hlen);
 358   apt->last_used=timer_seq;
 359   cli();
 360   apt->next = arp_table[hash];
 361   arp_table[hash] = apt;
 362   sti();
 363   return (apt);
 364 }
 365 
 366 int
 367 arp_rcv(struct sk_buff *skb, struct device *dev, struct packet_type *pt)
     /* [previous][next][first][last][top][bottom][index][help] */
 368 {
 369    struct arp *arp;
 370    struct arp_table *tbl;
 371    int ret;
 372 
 373    PRINTK (("<<\n"));
 374    arp = skb->h.arp;
 375    print_arp(arp);
 376 
 377   /* if this test doesn't pass, something fishy is going on. */
 378   if (arp->hlen != dev->addr_len || dev->type !=NET16( arp->hrd))
 379     {
 380        kfree_skb(skb, FREE_READ);
 381        return (0);
 382     }
 383 
 384   /* for now we will only deal with ip addresses. */
 385   if (arp->pro != NET16(ARP_IP_PROT) || arp->plen != 4)
 386     {
 387        kfree_skb (skb, FREE_READ);
 388        return (0);
 389     }
 390 
 391   /* now look up the ip address in the table. */
 392   tbl = arp_lookup (*arp_sourcep(arp));
 393   if (tbl != NULL)
 394     {
 395        memcpy (tbl->hard, arp+1, arp->hlen);
 396        tbl->hlen = arp->hlen;
 397        tbl->last_used = timer_seq;
 398     }
 399 
 400   if (!my_ip_addr(*arp_targetp(arp)))
 401     {
 402        kfree_skb (skb, FREE_READ);
 403        return (0);
 404     }
 405 
 406   if (tbl == NULL)
 407     create_arp (*arp_sourcep(arp), arp_sourceh(arp), arp->hlen);
 408 
 409    /* now see if we can send anything. */
 410    send_arp_q();
 411      
 412   if (arp->op != NET16(ARP_REQUEST))
 413     {
 414        kfree_skb (skb, FREE_READ);
 415        return (0);
 416     }
 417 
 418   /* now we need to create a new packet. */
 419    ret = arp_response(arp, dev);
 420    kfree_skb (skb, FREE_READ);
 421    return (ret);
 422 }
 423 
 424 void
 425 arp_snd (unsigned long paddr, struct device *dev, unsigned long saddr)
     /* [previous][next][first][last][top][bottom][index][help] */
 426 {
 427   struct sk_buff *skb;
 428   struct arp *arp;
 429   struct arp_table *apt;
 430   int tmp;
 431   PRINTK (("arp_snd (paddr=%X, dev=%X, saddr=%X)\n",paddr, dev, saddr));
 432 
 433   /* first we build a dummy arp table entry. */
 434   apt = create_arp (paddr, NULL, 0);
 435   if (apt == NULL) return;
 436 
 437   skb = arp_malloc (sizeof (*arp) + sizeof (*skb) + dev->hard_header_len +
 438                     2*dev->addr_len+8, GFP_ATOMIC);
 439   if (skb == NULL) return;
 440   
 441   skb->lock = 0;
 442   skb->sk = NULL;
 443   skb->mem_addr = skb;
 444   skb->mem_len = sizeof (*arp) + sizeof (*skb) + dev->hard_header_len +
 445                     2*dev->addr_len+8;
 446   skb->arp = 1;
 447   skb->dev = dev;
 448   skb->len = sizeof (*arp) + dev->hard_header_len + 2*dev->addr_len+8;
 449   skb->next = NULL;
 450 
 451   tmp = dev->hard_header ((unsigned char *)(skb+1), dev,
 452                           ETHERTYPE_ARP, 0, saddr, skb->len);
 453   if (tmp < 0)
 454     {
 455        arp_free (skb->mem_addr, skb->mem_len);
 456        return;
 457     }
 458 
 459   arp =(struct arp *) ((unsigned char *)skb+sizeof (*skb) + tmp );
 460   arp->hrd = net16(dev->type);
 461   arp->pro = NET16(ARP_IP_PROT);
 462   arp->hlen = dev->addr_len;
 463   arp->plen = 4;
 464   arp->op = NET16(ARP_REQUEST);
 465   *arp_sourcep(arp) = saddr;
 466   *arp_targetp(arp) = paddr;
 467   memcpy (arp_sourceh(arp), dev->dev_addr, dev->addr_len);
 468   memcpy (arp_targeth(arp), dev->broadcast, dev->addr_len);
 469   PRINTK((">>\n"));
 470   print_arp(arp);
 471   dev->queue_xmit (skb, dev, 0);
 472 }
 473 
 474 int
 475 arp_find(unsigned char *haddr, unsigned long paddr, struct device *dev,
     /* [previous][next][first][last][top][bottom][index][help] */
 476            unsigned long saddr)
 477 {
 478   struct arp_table *apt;
 479   PRINTK (("arp_find(haddr=%X, paddr=%X, dev=%X, saddr=%X)\n",
 480           haddr, paddr, dev, saddr));
 481   if (my_ip_addr (paddr))
 482     {
 483       memcpy (haddr, dev->dev_addr, dev->addr_len);
 484       return (0);
 485     }
 486   apt = arp_lookup (paddr);
 487   if (apt != NULL)
 488     {
 489        /* make sure it's not too old. If it is too old, we will
 490           just pretend we did not find it, and then arp_snd
 491           will verify the address for us. */
 492        if (!before (apt->last_used, timer_seq+ARP_TIMEOUT) &&
 493            apt->hlen != 0)
 494          {
 495             apt->last_used=timer_seq;
 496             memcpy (haddr, apt->hard, dev->addr_len);
 497             return (0);
 498          }
 499     }
 500 
 501   /* this assume haddr are at least 4 bytes.
 502      If this isn't true we can use a lookup
 503      table, one for every dev. */
 504   *(unsigned long *)haddr = paddr;
 505 
 506   /* if we didn't find an entry, we will try to 
 507      send an arp packet. */
 508   arp_snd(paddr,dev,saddr);
 509 
 510   return (1);
 511 }
 512 
 513 void
 514 arp_add (unsigned long addr, unsigned char *haddr, struct device *dev)
     /* [previous][next][first][last][top][bottom][index][help] */
 515 {
 516    struct arp_table *apt;
 517    /* first see if the address is already in the table. */
 518    apt = arp_lookup (addr);
 519    if (apt != NULL)
 520      {
 521         apt->last_used = timer_seq;
 522         memcpy (apt->hard, haddr , dev->addr_len);
 523         return;
 524      }
 525    create_arp (addr, haddr, dev->addr_len);
 526 }
 527 
 528 void
 529 arp_add_broad (unsigned long addr, struct device *dev)
     /* [previous][next][first][last][top][bottom][index][help] */
 530 {
 531   arp_add (addr,  dev->broadcast , dev);
 532 }
 533 
 534 void
 535 arp_queue(struct sk_buff *skb)
     /* [previous][next][first][last][top][bottom][index][help] */
 536 {
 537   cli();
 538   if (skb->next != NULL)
 539     {
 540       sti();
 541       printk ("arp.c: arp_queue skb already on queue magic=%X. \n",
 542               skb->magic);
 543       return;
 544     }
 545    if (arp_q == NULL)
 546      {
 547         arp_q = skb;
 548         skb->next = skb;
 549         skb->prev = skb;
 550      }
 551    else
 552      {
 553         skb->next = arp_q;
 554         skb->prev = arp_q->prev;
 555         skb->next->prev = skb;
 556         skb->prev->next = skb;
 557      }
 558   skb->magic = ARP_QUEUE_MAGIC;
 559    sti();
 560 }

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