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

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