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

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