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

1.1     ! root        1: /* ip.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 <asm/segment.h>
        !            24: #include <asm/system.h>
        !            25: #include <linux/types.h>
        !            26: #include <linux/kernel.h>
        !            27: #include <linux/sched.h>
        !            28: #include <linux/string.h>
        !            29: #include <linux/socket.h>
        !            30: #include <netinet/in.h>
        !            31: #include "timer.h"
        !            32: #include "ip.h"
        !            33: #include "tcp.h"
        !            34: #include "sock.h"
        !            35: #include <linux/errno.h>
        !            36: #include "arp.h"
        !            37: #include "icmp.h"
        !            38: 
        !            39: unsigned long ip_addr[MAX_IP_ADDRES]={0,0,0};
        !            40: 
        !            41: #undef IP_DEBUG
        !            42: #ifdef IP_DEBUG
        !            43: #define PRINTK printk
        !            44: #else
        !            45: #define PRINTK dummy_routine
        !            46: #endif
        !            47: 
        !            48: static struct rtable *rt_base=NULL; /* used to base all the routing data. */
        !            49: 
        !            50: struct ip_protocol *ip_protos[MAX_IP_PROTOS] = { NULL, };
        !            51: 
        !            52: #if 0
        !            53: static  struct ip_protocol *
        !            54: get_protocol(unsigned char prot)
        !            55: {
        !            56:    unsigned char hash;
        !            57:    struct ip_protocol *p;
        !            58:    PRINTK ("get_protocol (%d)\n ", prot);
        !            59:    hash = prot & (MAX_IP_PROTOS -1);
        !            60:    for (p = ip_protos[hash] ; p != NULL; p=p->next)
        !            61:      {
        !            62:        PRINTK ("trying protocol %d\n", p->protocol);
        !            63:        if (p->protocol == prot)
        !            64:             return (p);
        !            65:      }
        !            66:    return (NULL);
        !            67:     
        !            68: }
        !            69: #endif
        !            70: 
        !            71: void
        !            72: add_ip_protocol (struct ip_protocol *prot)
        !            73: {
        !            74:    unsigned char hash;
        !            75:    struct ip_protocol *p2;
        !            76:    hash = prot->protocol & (MAX_IP_PROTOS-1);
        !            77:    prot ->next = ip_protos[hash];
        !            78:    ip_protos[hash] = prot;
        !            79:    prot->copy = 0;
        !            80:    /* set the copy bit if we need to. */
        !            81:    for (p2 = prot->next; p2 != NULL; p2=p2->next)
        !            82:      {
        !            83:        if (p2->protocol == prot->protocol)
        !            84:          {
        !            85:             prot->copy = 1;
        !            86:             break;
        !            87:          }
        !            88:      }
        !            89: 
        !            90: }
        !            91: 
        !            92: int
        !            93: delete_ip_protocol (struct ip_protocol *prot)
        !            94: {
        !            95:    struct ip_protocol *p;
        !            96:    struct ip_protocol *lp=NULL;
        !            97:    unsigned char hash;
        !            98: 
        !            99: 
        !           100:    hash = prot->protocol & (MAX_IP_PROTOS -1);
        !           101:    if (prot == ip_protos[hash])
        !           102:      {
        !           103:         ip_protos[hash]=ip_protos[hash]->next;
        !           104:        return (0);
        !           105:      }
        !           106: 
        !           107:    for (p = ip_protos[hash]; p != NULL; p = p->next)
        !           108:      {
        !           109:        /* we have to worry if the protocol being deleted is the
        !           110:           last one on the list, then we may need to reset someones
        !           111:           copied bit. */
        !           112:        if (p->next != NULL && p->next == prot)
        !           113:          {
        !           114:             /* if we are the last one with this protocol and
        !           115:                there is a previous one, reset its copy bit. */
        !           116: 
        !           117:             if (p->copy == 0 && lp != NULL)
        !           118:               lp->copy = 0;
        !           119:             p->next = prot->next;
        !           120:             return (0);
        !           121:          }
        !           122: 
        !           123:        if (p->next != NULL && p->next->protocol == prot->protocol)
        !           124:          {
        !           125:             lp = p;
        !           126:          }
        !           127:      }
        !           128:    return (-1);
        !           129: }
        !           130: 
        !           131: /* addr1 is the address which may or may not be broadcast etc.
        !           132:    addr2 is the "real addr." */
        !           133: 
        !           134: int
        !           135: ip_addr_match (unsigned long addr1, unsigned long addr2)
        !           136: {
        !           137:   int i;
        !           138:   if (addr1 == addr2) return (1);
        !           139:   for (i = 0; i < 4; i++, addr1 >>= 8, addr2 >>= 8)
        !           140:     {
        !           141:       if ((addr1 & 0xff) != (addr2 & 0xff))
        !           142:        {
        !           143:          /* the only way this could be a match is for the rest of
        !           144:             addr1 to be 0. */
        !           145:          if (addr1 != 0) 
        !           146:            {
        !           147:              return (0);
        !           148:            }
        !           149:          return (1);
        !           150:        }
        !           151:     }
        !           152:   return (1);
        !           153: }
        !           154: 
        !           155: int
        !           156: my_ip_addr(unsigned long addr)
        !           157: {
        !           158:   int i;
        !           159:   for (i = 0; i < MAX_IP_ADDRES; i++)
        !           160:     {
        !           161:       if (ip_addr[i] == 0) return (0);
        !           162:       if (ip_addr_match (addr, ip_addr[i])) return (1);
        !           163:     }
        !           164:   return (0);
        !           165: }
        !           166: 
        !           167: /* these two routines will do routining. */
        !           168: static  void
        !           169: strict_route(struct ip_header *iph, struct options *opt)
        !           170: {
        !           171: }
        !           172: 
        !           173: static  void
        !           174: loose_route(struct ip_header *iph, struct options *opt)
        !           175: {
        !           176: }
        !           177: 
        !           178: void
        !           179: print_rt(struct rtable *rt)
        !           180: {
        !           181:   PRINTK ("net = %08X router = %08X\n",rt->net, rt->router);
        !           182:   PRINTK ("dev = %X, next = %X\n",rt->dev, rt->next);
        !           183: }
        !           184: 
        !           185: void
        !           186: print_ipprot (struct ip_protocol *ipprot)
        !           187: {
        !           188:    PRINTK ("handler = %X, protocol = %d\n",
        !           189:           ipprot->handler, ipprot->protocol);
        !           190: }
        !           191: 
        !           192: /* This assumes that address are all in net order. */
        !           193: static  struct device *
        !           194: ip_route(struct options *opt, unsigned long daddr , unsigned long *raddr)
        !           195: {
        !           196:   struct rtable *rt;
        !           197:   /* look through the routing table for some
        !           198:      kind of match. */
        !           199:   for (rt=rt_base; rt != NULL; rt=rt->next)
        !           200:     {
        !           201:       /* see if we found one. */
        !           202:       if (ip_addr_match (rt->net, daddr))
        !           203:        {
        !           204:          *raddr = rt->router;
        !           205:          return (rt->dev);
        !           206:        }
        !           207:     }
        !           208:   return (NULL);
        !           209: };
        !           210: 
        !           211: void
        !           212: add_route (struct rtable *rt)
        !           213: {
        !           214:   int mask;
        !           215:   struct rtable *r;
        !           216:   struct rtable *r1;
        !           217:   PRINTK ("add_route (rt=%X):\n",rt);
        !           218:   print_rt(rt);
        !           219: 
        !           220:   if (rt_base == NULL)
        !           221:     {
        !           222:       rt->next = NULL;
        !           223:       rt_base = rt;
        !           224:       return;
        !           225:     }
        !           226: 
        !           227:   /* what we have to do is loop though this until we have found the
        !           228:      first address which has the same generality as the one in rt.  Then
        !           229:      we can put rt in after it. */
        !           230:   for (mask = 0xff000000; mask != 0xffffffff; mask = (mask >> 8) | mask)
        !           231:     {
        !           232:       if (mask & rt->net)
        !           233:        {
        !           234:          mask = mask << 8;
        !           235:          break;
        !           236:        }
        !           237:     }
        !           238:   PRINTK ("mask = %X\n",mask);
        !           239:   r1=rt_base;
        !           240:   for (r=rt_base; r != NULL; r=r->next)
        !           241:     {
        !           242:        /* see if we are getting a duplicate. */
        !           243:        if (r->net == rt->net)
        !           244:         {
        !           245:            if (r == rt_base)
        !           246:              {
        !           247:                 rt->next = r->next;
        !           248:                 rt_base = rt;
        !           249:              }
        !           250:            else
        !           251:              {
        !           252:                 rt->next = r->next;
        !           253:                 r1->next = rt;
        !           254:              }
        !           255:            free_s (r, sizeof (*r));
        !           256:            return;
        !           257:         }
        !           258: 
        !           259:       if (!(r->net & mask))
        !           260:        {
        !           261:           PRINTK("adding before r=%X\n",r);
        !           262:           print_rt(r);
        !           263:           if (r == rt_base)
        !           264:             {
        !           265:                rt->next = rt_base;
        !           266:                rt_base = rt;
        !           267:                return;
        !           268:             }
        !           269:           rt->next = r;
        !           270:           r1->next = rt;
        !           271:           return;
        !           272:        }
        !           273:       r1 = r;
        !           274:     }
        !           275:   PRINTK ("adding after r1=%X\n",r1);
        !           276:   print_rt(r1);
        !           277:   /* goes at the end. */
        !           278:   rt->next = NULL;
        !           279:   r1->next = rt;
        !           280: }
        !           281: 
        !           282: int
        !           283: ip_set_dev (struct ip_config *u_ipc)
        !           284: {
        !           285:   struct rtable *rt;
        !           286:   struct device *dev;
        !           287:   struct ip_config ipc;
        !           288:   static int ip_ads = 0;
        !           289: 
        !           290:   if (ip_ads >= MAX_IP_ADDRES) return (-EINVAL);
        !           291: 
        !           292:   verify_area (u_ipc, sizeof (ipc));
        !           293:   memcpy_fromfs(&ipc, u_ipc, sizeof (ipc));
        !           294:   ipc.name[MAX_IP_NAME-1] = 0;
        !           295:   dev = get_dev (ipc.name);
        !           296: 
        !           297:   if (dev == NULL) return (-EINVAL);
        !           298: 
        !           299:   /* see if we need to add a broadcast address. */
        !           300:   if (ipc.net != -1)
        !           301:     {
        !           302:        arp_add_broad (ipc.net, dev);
        !           303:        rt = malloc (sizeof (*rt));
        !           304:        if (rt == NULL) return (-ENOMEM);
        !           305: 
        !           306:        rt->net = ipc.net;
        !           307:        rt->dev = dev;
        !           308:        rt->router = 0;
        !           309:        add_route (rt);
        !           310: /*     dev->net = ipc.net;*/
        !           311:     }
        !           312: 
        !           313:   if (ipc.router != -1)
        !           314:     {
        !           315:        rt = malloc (sizeof (*rt));
        !           316:        if (rt == NULL) return (-ENOMEM);
        !           317:        rt->net = 0;
        !           318:        rt->dev = dev;
        !           319:        rt->router = ipc.router;
        !           320:        add_route (rt);
        !           321:     }
        !           322: 
        !           323:   if (dev->loopback)
        !           324:     {
        !           325:        rt = malloc (sizeof (*rt));
        !           326:        if (rt == NULL) return (-ENOMEM);
        !           327:        rt->net = ipc.paddr;
        !           328:        rt->dev = dev;
        !           329:        rt->router = 0;
        !           330:        add_route (rt);
        !           331: 
        !           332:     }
        !           333: 
        !           334: 
        !           335:   if (!my_ip_addr (ipc.paddr))
        !           336:     ip_addr[ip_ads++] = ipc.paddr;
        !           337: 
        !           338:   dev->up = ipc.up;
        !           339:   if (dev->up)
        !           340:     {
        !           341:        if (dev->open)
        !           342:         dev->open(dev);
        !           343:     }
        !           344:   else
        !           345:     {
        !           346:        if (dev->stop)
        !           347:         dev->stop(dev);
        !           348:     }
        !           349:   return (0);
        !           350: 
        !           351: }
        !           352: 
        !           353: /* this routine will check to see if we have lost a gateway. */
        !           354: void
        !           355: ip_route_check (unsigned long daddr)
        !           356: {
        !           357: }
        !           358: 
        !           359: /* this routine puts the options at the end of an ip header. */
        !           360: static  int
        !           361: build_options (struct ip_header *iph, struct options *opt)
        !           362: {
        !           363:   unsigned char *ptr;
        !           364:   /* currently we don't support any options. */
        !           365:   ptr = (unsigned char *)(iph+1);
        !           366:   *ptr = 0;
        !           367:   return (4);
        !           368: }
        !           369: 
        !           370: /* This routine builds the appropriate hardware/ip headers for
        !           371:    the routine.  It assumes that if *prot != NULL then the
        !           372:    protocol knows what it's doing, otherwise it uses the
        !           373:    routing/arp tables to select a protocol struct. */
        !           374: 
        !           375: int
        !           376: ip_build_header (struct sk_buff *skb, unsigned long saddr,
        !           377:                 unsigned long daddr, struct device **dev, int type,
        !           378:                 struct options *opt, int len)
        !           379: {
        !           380:   static struct options optmem;
        !           381:   struct ip_header *iph;
        !           382:   unsigned char *buff;
        !           383:   static int count = 0;
        !           384:   unsigned long raddr; /* for the router. */
        !           385:   int tmp;
        !           386:   if (saddr == 0) saddr = MY_IP_ADDR;
        !           387:   PRINTK ("ip_build_header (skb=%X, saddr=%X, daddr=%X, *dev=%X,\n"
        !           388:          "                 type=%d, opt=%X, len = %d)\n",
        !           389:          skb, saddr, daddr, *dev, type, opt, len);
        !           390:   buff = (unsigned char *)(skb + 1);
        !           391:   /* see if we need to look up the device. */
        !           392:   if (*dev == NULL)
        !           393:     {
        !           394:       *dev = ip_route(&optmem,daddr, &raddr);
        !           395:       if (*dev == NULL)
        !           396:        {
        !           397:          return (-ENETUNREACH);
        !           398:        }
        !           399:       opt = &optmem;
        !           400:     }
        !           401:   else
        !           402:     {
        !           403:       /* we still need the address of the first hop. */
        !           404:       ip_route (&optmem, daddr, &raddr);
        !           405:     }
        !           406:   if (raddr == 0) raddr = daddr;
        !           407:   /* now build the header. */
        !           408:   /* we need to worry about routing in here.  daddr should
        !           409:      really be the address of the next hop. */
        !           410:   /* but raddr is . */
        !           411:   if ((*dev)->hard_header)
        !           412:     {
        !           413:        tmp = (*dev)->hard_header(buff, *dev, ETHERTYPE_IP, raddr, saddr, len);
        !           414:     }
        !           415:   else
        !           416:     {
        !           417:        tmp = 0;
        !           418:     }
        !           419:   if (tmp < 0)
        !           420:     {
        !           421:        tmp = -tmp;
        !           422:        skb->arp = 0;
        !           423:     }
        !           424:   else
        !           425:     {
        !           426:        skb->arp = 1;
        !           427:     }
        !           428:   buff += tmp;
        !           429:   len -= tmp;
        !           430:   skb->dev = *dev;
        !           431:   /* now build the ip header. */
        !           432:   iph = (struct ip_header *)buff;
        !           433:   iph->version = 4;
        !           434:   iph->tos = 0;
        !           435:   iph->frag_off = 0;
        !           436:   iph->ttl = 32;
        !           437:   iph->daddr = daddr;
        !           438:   iph->saddr = saddr;
        !           439:   iph->protocol=type;
        !           440:   iph->ihl = 5;
        !           441:   iph->id = net16(count++);
        !           442:   /* build_options (iph, opt);*/
        !           443:   return (20+tmp);
        !           444: }
        !           445: 
        !           446: static  int
        !           447: do_options(struct ip_header *iph, struct options *opt)
        !           448: {
        !           449:   unsigned char *buff;
        !           450:   int done = 0;
        !           451:   int len=sizeof (*iph);
        !           452:   int i;
        !           453:   /* zero  out the options. */
        !           454:   opt->record_route.route_size = 0;
        !           455:   opt->loose_route.route_size = 0;
        !           456:   opt->strict_route.route_size = 0;
        !           457:   opt->tstamp.ptr = 0;
        !           458:   opt->security = 0;
        !           459:   opt->compartment = 0;
        !           460:   opt->handling = 0;
        !           461:   opt->stream = 0;
        !           462:   opt->tcc = 0;
        !           463:   return (0);
        !           464:   /* advance the pointer to start at the options. */
        !           465:   buff = (unsigned char *)(iph + 1);
        !           466: 
        !           467:   /*now start the processing. */
        !           468:   while (!done && len < iph->ihl*4)
        !           469:     {
        !           470:       switch (*buff)
        !           471:        {
        !           472:        case IPOPT_END:
        !           473:          done=1;
        !           474:          break;
        !           475: 
        !           476:        case IPOPT_NOOP:
        !           477:          buff++;
        !           478:          len ++;
        !           479:          break;
        !           480: 
        !           481:        case IPOPT_SEC:
        !           482:          buff++;
        !           483:          if (*buff != 11)
        !           484:            return (1);
        !           485:          buff++;
        !           486:          opt->security = net16(*(unsigned short *)buff);
        !           487:          buff += 2;
        !           488:          opt->compartment = net16(*(unsigned short *)buff);
        !           489:          buff += 2;
        !           490:          opt-> handling = net16(*(unsigned short *)buff);
        !           491:          buff += 2;
        !           492:          opt->tcc = ((*buff) << 16) + net16(*(unsigned short *)(buff+1));
        !           493:          buff += 3;
        !           494:          len += 11;
        !           495:          break;
        !           496: 
        !           497:        case IPOPT_LSRR:
        !           498:          buff ++;
        !           499:          if ((*buff - 3)% 4 != 0) return (1);
        !           500:          len += *buff;
        !           501:          opt->loose_route.route_size = (*buff -3)/4;
        !           502:          buff ++;
        !           503:          if (*buff % 4 != 0) return (1);
        !           504:          opt->loose_route.pointer = *buff/4 - 1;
        !           505:          buff ++;
        !           506:          buff ++;
        !           507:          for (i = 0; i < opt->loose_route.route_size; i++)
        !           508:            {
        !           509:              opt->loose_route.route[i]=*(unsigned long *)buff;
        !           510:              buff += 4;
        !           511:            }
        !           512:          break;
        !           513: 
        !           514: 
        !           515:        case IPOPT_SSRR:
        !           516:          buff ++;
        !           517:          if ((*buff - 3)% 4 != 0) return (1);
        !           518:          len += *buff;
        !           519:          opt->strict_route.route_size = (*buff -3)/4;
        !           520:          buff ++;
        !           521:          if (*buff % 4 != 0) return (1);
        !           522:          opt->strict_route.pointer = *buff/4 - 1;
        !           523:          buff ++;
        !           524:          buff ++;
        !           525:          for (i = 0; i < opt->strict_route.route_size; i++)
        !           526:            {
        !           527:              opt->strict_route.route[i]=*(unsigned long *)buff;
        !           528:              buff += 4;
        !           529:            }
        !           530:          break;
        !           531: 
        !           532:        case IPOPT_RR:
        !           533:          buff ++;
        !           534:          if ((*buff - 3)% 4 != 0) return (1);
        !           535:          len += *buff;
        !           536:          opt->record_route.route_size = (*buff -3)/4;
        !           537:          buff ++;
        !           538:          if (*buff % 4 != 0) return (1);
        !           539:          opt->record_route.pointer = *buff/4 - 1;
        !           540:          buff ++;
        !           541:          buff ++;
        !           542:          for (i = 0; i < opt->record_route.route_size; i++)
        !           543:            {
        !           544:              opt->record_route.route[i]=*(unsigned long *)buff;
        !           545:              buff += 4;
        !           546:            }
        !           547:          break;
        !           548: 
        !           549:        case IPOPT_SID:
        !           550:          len += 4;
        !           551:          buff +=2;
        !           552:          opt->stream = *(unsigned short *)buff;
        !           553:          buff += 2;
        !           554:          break;
        !           555: 
        !           556:        case IPOPT_TIMESTAMP:
        !           557:          buff ++;
        !           558:          len += *buff;
        !           559:          if (*buff % 4 != 0) return (1);
        !           560:          opt->tstamp.len = *buff / 4 - 1;
        !           561:          buff ++;
        !           562:          if ((*buff - 1) % 4 != 0) return (1);
        !           563:          opt->tstamp.ptr = (*buff-1)/4;
        !           564:          buff ++;
        !           565:          opt->tstamp.x.full_char = *buff;
        !           566:          buff ++;
        !           567:          for (i = 0; i < opt->tstamp.len; i++)
        !           568:            {
        !           569:              opt->tstamp.data[i] = *(unsigned long *)buff;
        !           570:              buff += 4;
        !           571:            }
        !           572:          break;
        !           573: 
        !           574:        default:
        !           575:          return (1);
        !           576:        }
        !           577:     }
        !           578:   if (opt->record_route.route_size == 0)
        !           579:     {
        !           580:       if (opt->strict_route.route_size != 0)
        !           581:        {
        !           582:          memcpy (&(opt->record_route), &(opt->strict_route),
        !           583:                  sizeof (opt->record_route));
        !           584:        }
        !           585:       else if (opt->loose_route.route_size != 0)
        !           586:        {
        !           587:          memcpy (&(opt->record_route), &(opt->loose_route),
        !           588:                  sizeof (opt->record_route));
        !           589:        }
        !           590:     }
        !           591: 
        !           592:   if (opt->strict_route.route_size != 0 &&
        !           593:       opt->strict_route.route_size != opt->strict_route.pointer)
        !           594:     {
        !           595:       strict_route (iph, opt);
        !           596:       return (0);
        !           597:     }
        !           598: 
        !           599:   if (opt->loose_route.route_size != 0 &&
        !           600:       opt->loose_route.route_size != opt->loose_route.pointer)
        !           601:     {
        !           602:       loose_route (iph, opt);
        !           603:       return (0);
        !           604:     }
        !           605: 
        !           606:   return (0);
        !           607: }
        !           608: 
        !           609: 
        !           610: /* This routine does all the checksum computations that don't require
        !           611:    anything special (like copying or special headers.) */
        !           612: 
        !           613: unsigned short
        !           614: ip_compute_csum(unsigned char * buff, int len)
        !           615: {
        !           616:   unsigned long sum = 0;
        !           617:   if (len > 3)
        !           618:     {
        !           619:        /* do the first multiple of 4 bytes and convert to 16 bits. */
        !           620:        __asm__("\t clc\n"
        !           621:               "1:\n"
        !           622:               "\t lodsl\n"
        !           623:               "\t adcl %%eax, %%ebx\n"
        !           624:               "\t loop 1b\n"
        !           625:               "\t adcl $0, %%ebx\n"
        !           626:               "\t movl %%ebx, %%eax\n"
        !           627:               "\t shrl $16, %%eax\n"
        !           628:               "\t addw %%ax, %%bx\n"
        !           629:               "\t adcw $0, %%bx\n"
        !           630:               : "=b" (sum) , "=S" (buff)
        !           631:               : "0" (sum), "c" (len >> 2) ,"1" (buff)
        !           632:               : "ax", "cx", "si", "bx" );
        !           633:     }
        !           634:   if (len & 2)
        !           635:     {
        !           636:        __asm__("\t lodsw\n"
        !           637:               "\t addw %%ax, %%bx\n"
        !           638:               "\t adcw $0, %%bx\n"
        !           639:               : "=b" (sum), "=S" (buff)
        !           640:               : "0" (sum), "1" (buff)
        !           641:               : "bx", "ax", "si");
        !           642:     }
        !           643:   if (len & 1)
        !           644:     {
        !           645:        __asm__("\t lodsb\n"
        !           646:               "\t movb $0, %%ah\n"
        !           647:               "\t addw %%ax, %%bx\n"
        !           648:               "\t adcw $0, %%bx\n"
        !           649:               : "=b" (sum), "=S" (buff)
        !           650:               : "0" (sum), "1" (buff)
        !           651:               : "bx", "ax", "si");
        !           652:     }
        !           653:   sum =~sum;
        !           654:   return (sum&0xffff);
        !           655: }
        !           656: 
        !           657: static  int
        !           658: ip_csum(struct ip_header *iph)
        !           659: {
        !           660:   if (iph->check == 0) return (0);
        !           661:   if (ip_compute_csum((unsigned char *)iph, iph->ihl*4) == 0)  return (0);
        !           662:   return (1);
        !           663: }
        !           664: 
        !           665: static  void
        !           666: ip_send_check(struct ip_header *iph)
        !           667: {
        !           668:    iph->check = 0;
        !           669:    iph->check = ip_compute_csum((unsigned char *)iph, iph->ihl*4);
        !           670: }
        !           671: 
        !           672: int
        !           673: ip_rcv(struct sk_buff *skb, struct device *dev, struct packet_type *pt)
        !           674: {
        !           675:   struct ip_header *iph;
        !           676:   unsigned char hash;
        !           677:   unsigned char flag=0;
        !           678:   static struct options opt; /* since we don't use these yet, and they
        !           679:                                take up stack space. */
        !           680:   struct ip_protocol *ipprot;
        !           681: 
        !           682:   iph=skb->h.iph;
        !           683: 
        !           684:   PRINTK("<<\n");
        !           685:   print_iph(iph);
        !           686: 
        !           687:   if (ip_csum (iph) || do_options (iph,&opt) || iph->version != 4)
        !           688:     {
        !           689:        PRINTK ("ip packet thrown out. \n");
        !           690:        skb->sk = NULL;
        !           691:        free_skb(skb, 0);
        !           692:        return (0);
        !           693:     }
        !           694: 
        !           695:   /* for now we will only deal with packets meant for us. */
        !           696:   if (!my_ip_addr(iph->daddr))
        !           697:     {
        !           698:        PRINTK ("packet meant for someone else.\n");
        !           699:        skb->sk = NULL;
        !           700:        free_skb(skb, 0);
        !           701:        return (0);
        !           702:     }
        !           703: 
        !           704:   /* deal with fragments.  or don't for now.*/
        !           705:   if ((iph->frag_off & 64) || (net16(iph->frag_off)&0x1fff))
        !           706:     {
        !           707:        printk ("packet fragmented. \n");
        !           708:        skb->sk = NULL;
        !           709:        free_skb(skb, 0);
        !           710:        return(0);
        !           711:     }
        !           712: 
        !           713:   skb->h.raw += iph->ihl*4;
        !           714: 
        !           715:   /* add it to the arp table if it's talking to us.  That way we
        !           716:      will be able to talk to them also. */
        !           717: 
        !           718:   hash = iph->protocol & (MAX_IP_PROTOS -1);
        !           719:   for (ipprot = ip_protos[hash]; ipprot != NULL; ipprot=ipprot->next)
        !           720:     {
        !           721:        struct sk_buff *skb2;
        !           722:        PRINTK ("Using protocol = %X:\n", ipprot);
        !           723:        print_ipprot (ipprot);
        !           724:        /* pass it off to everyone who wants it. */
        !           725:        /* we should check the return values here. */
        !           726:        /* see if we need to make a copy of it.  This will
        !           727:          only be set if more than one protpocol wants it. 
        !           728:          and then not for the last one. */
        !           729: 
        !           730:        if (ipprot->copy)
        !           731:         {
        !           732:            skb2 = malloc (skb->mem_len);
        !           733:            if (skb2 == NULL) continue;
        !           734:            memcpy (skb2, skb, skb->mem_len);
        !           735:            skb2->mem_addr = skb2;
        !           736:         }
        !           737:        else
        !           738:         {
        !           739:            skb2 = skb;
        !           740:         }
        !           741:        flag = 1;
        !           742:        ipprot->handler (skb2, dev, &opt, iph->daddr,
        !           743:                        net16(iph->tot_len) - iph->ihl*4,
        !           744:                        iph->saddr, 0, ipprot);
        !           745: 
        !           746:     }
        !           747:   if (!flag)
        !           748:     {
        !           749:        icmp_reply (skb, ICMP_DEST_UNREACH, ICMP_PROT_UNREACH, dev);
        !           750:        skb->sk = NULL;
        !           751:        free_skb (skb, 0);
        !           752:     }
        !           753: 
        !           754: 
        !           755:   return (0);
        !           756: }
        !           757: 
        !           758: 
        !           759: /* queues a packet to be sent, and starts the transmitter if
        !           760:    necessary.  if free = 1 then we free the block after transmit,
        !           761:    otherwise we don't. */
        !           762: /* This routine also needs to put in the total length, and compute
        !           763:    the checksum. */
        !           764: void
        !           765: ip_queue_xmit (volatile struct sock *sk, struct device *dev, 
        !           766:               struct sk_buff *skb, int free)
        !           767: {
        !           768:   struct ip_header *iph;
        !           769:   unsigned char *ptr;
        !           770:   if (sk == NULL) free = 1;
        !           771:   skb->free = free;
        !           772:   skb->dev = dev;
        !           773:   skb->when = jiffies;
        !           774:   PRINTK(">>\n");
        !           775:   ptr = (unsigned char *)(skb + 1);
        !           776:   ptr += dev->hard_header_len;
        !           777:   iph = (struct ip_header *)ptr;
        !           778:   iph->tot_len = net16(skb->len-dev->hard_header_len);
        !           779:   ip_send_check (iph);
        !           780:   print_iph(iph);
        !           781:   skb->next = NULL;
        !           782:   if (!free)
        !           783:     {
        !           784:       skb->link3 = NULL;
        !           785:       sk->packets_out++;
        !           786:       cli();
        !           787:       if (sk->send_tail == NULL)
        !           788:        {
        !           789:          sk->send_tail = skb;
        !           790:          sk->send_head = skb;
        !           791:        }
        !           792:       else
        !           793:        {
        !           794:          sk->send_tail->link3 = skb;
        !           795:          sk->send_tail = skb;
        !           796:        }
        !           797:       sti();
        !           798:       sk->time_wait.len = sk->rtt*2;
        !           799:       sk->timeout=TIME_WRITE;
        !           800:       reset_timer ((struct timer *)&sk->time_wait);
        !           801:    }
        !           802:   else
        !           803:     {
        !           804:        skb->sk = sk;
        !           805:     }
        !           806:   if (dev->up)
        !           807:     {
        !           808:        if (sk)
        !           809:         dev->queue_xmit(skb, dev, sk->priority);
        !           810:        else
        !           811:         dev->queue_xmit (skb, dev, SOPRI_NORMAL);
        !           812:     }
        !           813:   else
        !           814:     {
        !           815:        if (free) 
        !           816:         free_skb (skb, FREE_WRITE);
        !           817:     }
        !           818: }
        !           819: 
        !           820: void
        !           821: ip_retransmit (volatile struct sock *sk, int all)
        !           822: {
        !           823:   struct sk_buff * skb;
        !           824:   struct proto *prot;
        !           825:   struct device *dev;
        !           826: 
        !           827:   prot = sk->prot;
        !           828:   skb = sk->send_head;
        !           829:   while (skb != NULL)
        !           830:     {
        !           831:       dev = skb->dev;
        !           832:       /* rebuild_header sees if the arp is done.  If not it sends a new
        !           833:         arp, and if so it builds the header. */
        !           834:       if (!skb->arp)
        !           835:        {
        !           836:          if (dev->rebuild_header ((struct enet_header *)(skb+1),dev))
        !           837:            {
        !           838:               if (!all) break;
        !           839:               skb=skb->link3;
        !           840:               continue;
        !           841:            }
        !           842:        }
        !           843:       skb->arp = 1;
        !           844:       skb->when = jiffies;
        !           845: 
        !           846:       if (dev->up)
        !           847:        if (sk)
        !           848:          dev->queue_xmit(skb, dev, sk->priority);
        !           849:        else
        !           850:          dev->queue_xmit(skb, dev, SOPRI_NORMAL );
        !           851: 
        !           852:       sk->retransmits++;
        !           853:       sk->prot->retransmits ++;
        !           854:       if (!all) break;
        !           855:       /* this should cut it off before we send too
        !           856:         many packets. */
        !           857:       if (sk->retransmits > sk->cong_window) break;
        !           858:       skb=skb->link3;
        !           859:     }
        !           860:   sk->time_wait.len = sk->rtt*2;
        !           861:   sk->timeout = TIME_WRITE;
        !           862:   reset_timer ((struct timer *)&sk->time_wait);
        !           863: }
        !           864: 
        !           865: void
        !           866: print_iph (struct ip_header *ip)
        !           867: {
        !           868:   PRINTK ("ip header:\n");
        !           869:   PRINTK ("  ihl = %d, version = %d, tos = %d, tot_len = %d\n",
        !           870:          ip->ihl, ip->version, ip->tos, net16(ip->tot_len));
        !           871:   PRINTK ("  id = %x, ttl = %d, prot = %d, check=%x\n",
        !           872:          ip->id, ip->ttl, ip->protocol, ip->check);
        !           873:   PRINTK (" frag_off=%d\n", ip->frag_off);
        !           874:   PRINTK ("  saddr = %X, daddr = %X\n",ip->saddr, ip->daddr);
        !           875: }
        !           876: 
        !           877: #if 0
        !           878: int
        !           879: ip_handoff (volatile struct sock *sk)
        !           880: {
        !           881:    struct ip_protocol *p;
        !           882:    struct sk_buff *skb;
        !           883:    p = get_protocol (sk->protocol);
        !           884: 
        !           885:    if (p == NULL)
        !           886:      {
        !           887:        /* this can never happen. */
        !           888:        printk ("sock_ioctl: protocol not found. \n");
        !           889:        /* what else can I do, I suppose I could send a sigkill. */
        !           890:        return (-EIO);
        !           891:      }
        !           892: 
        !           893:    while (p->handler != sk->prot->rcv)
        !           894:      {
        !           895:        p=p->next;
        !           896:        if (p == NULL)
        !           897:          {
        !           898:             /* this can never happen. */
        !           899:             printk ("sock_ioctl: protocol not found. \n");
        !           900:             /* what else can I do, I suppose I could send a sigkill. */
        !           901:             return (-EIO);
        !           902:          }
        !           903:      }
        !           904:    p = p-> next;
        !           905:    sk->inuse = 1;
        !           906:    
        !           907:    /* now we have to remove the top sock buff.  If there are none, then
        !           908:       we return. */
        !           909:    if (sk->rqueue == NULL) return (0);
        !           910:    skb = sk->rqueue;
        !           911:    if (skb->next == skb)
        !           912:      {
        !           913:        sk->rqueue = NULL;
        !           914:      }
        !           915:    else
        !           916:      {
        !           917:        sk->rqueue = skb->next;
        !           918:        skb->next->prev = skb->prev;
        !           919:        skb->prev->next = skb->next;
        !           920:      }
        !           921:    if (p != NULL)
        !           922:      {
        !           923:        p->handler ((unsigned char *)(skb+1), skb->dev, NULL, skb->saddr,
        !           924:                    skb->len, skb->daddr, p->protocol, 0);
        !           925:      }
        !           926:    free_skb (skb, FREE_READ);
        !           927:    release_sock (sk);
        !           928:    return (0);
        !           929: }
        !           930: 
        !           931: #endif

unix.superglobalmegacorp.com

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