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
  19. arpreq_check
  20. arp_ioctl_set
  21. arp_ioctl_get
  22. arp_ioctl_del

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

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