Annotation of linux/net/tcp/arp.c, revision 1.1

1.1     ! root        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 [email protected] 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)
        !            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)
        !            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)
        !           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)
        !           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)
        !           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)
        !           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)
        !           154: {
        !           155:   free_s(ptr, len);
        !           156: }
        !           157: 
        !           158: static  void *
        !           159: arp_malloc (unsigned long amount)
        !           160: {
        !           161:   return (malloc (amount));
        !           162: }
        !           163: 
        !           164: static  int
        !           165: arp_response (struct arp *arp1, struct device *dev)
        !           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)
        !           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)
        !           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)
        !           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:   sti();
        !           290:   apt->next = arp_table[hash];
        !           291:   arp_table[hash]=apt;
        !           292:   cli();
        !           293:   return (apt);
        !           294: }
        !           295: 
        !           296: int
        !           297: arp_rcv(struct sk_buff *skb, struct device *dev, struct packet_type *pt)
        !           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)
        !           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,
        !           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: 
        !           443: void
        !           444: arp_add (unsigned long addr, unsigned char *haddr, struct device *dev)
        !           445: {
        !           446:    struct arp_table *apt;
        !           447:    /* first see if the address is already in the table. */
        !           448:    apt = arp_lookup (addr);
        !           449:    if (apt != NULL)
        !           450:      {
        !           451:        apt->last_used = timer_seq;
        !           452:        memcpy (apt->hard, haddr , dev->addr_len);
        !           453:        return;
        !           454:      }
        !           455:    create_arp (addr, haddr, dev->addr_len);
        !           456: }
        !           457: 
        !           458: void
        !           459: arp_add_broad (unsigned long addr, struct device *dev)
        !           460: {
        !           461:   arp_add (addr,  dev->broadcast , dev);
        !           462: }
        !           463: 
        !           464: 
        !           465: void
        !           466: arp_queue(struct sk_buff *skb)
        !           467: {
        !           468:    cli();
        !           469:    if (arp_q == NULL)
        !           470:      {
        !           471:        arp_q = skb;
        !           472:        skb->next = skb;
        !           473:        skb->prev = skb;
        !           474:      }
        !           475:    else
        !           476:     {
        !           477:       skb->next = arp_q;
        !           478:       skb->prev = arp_q->prev;
        !           479:       skb->next->prev = skb;
        !           480:       skb->prev->next = skb;
        !           481:     }
        !           482:   sti();
        !           483: 
        !           484: }
        !           485: 

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.