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

1.1     ! root        1: /* sock.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: #include <linux/errno.h>
        !            23: #include <linux/types.h>
        !            24: #include <linux/socket.h>
        !            25: #include <netinet/in.h>
        !            26: #include <linux/kernel.h>
        !            27: #include <linux/sched.h>
        !            28: #include <linux/timer.h>
        !            29: #include <linux/sock_ioctl.h>
        !            30: #include <asm/memory.h>
        !            31: #include "../kern_sock.h"
        !            32: #include "timer.h"
        !            33: #include "ip.h"
        !            34: #include "tcp.h"
        !            35: #include "udp.h"
        !            36: #include "sock.h"
        !            37: #include <asm/segment.h>
        !            38: #include <asm/system.h>
        !            39: #include <linux/fcntl.h>
        !            40: 
        !            41: #ifdef MEM_DEBUG
        !            42: #define MPRINTK printk
        !            43: #else
        !            44: #define MPRINTK dummy_routine
        !            45: #endif
        !            46: 
        !            47: #define min(a,b) ((a)<(b)?(a):(b))
        !            48: #define swap(a,b) {unsigned long c; c=a; a=b; b=c;}
        !            49: 
        !            50: extern struct proto tcp_prot;
        !            51: extern struct proto udp_prot;
        !            52: extern struct proto raw_prot;
        !            53: extern struct proto packet_prot;
        !            54: 
        !            55: static int ip_proto_init(void);
        !            56: static int ip_proto_create(struct socket *sock, int protocol);
        !            57: static int ip_proto_dup(struct socket *newsock, struct socket *oldsock);
        !            58: static int ip_proto_release(struct socket *sock, struct socket *peer);
        !            59: static int ip_proto_bind(struct socket *sock, struct sockaddr *umyaddr,
        !            60:                           int sockaddr_len);
        !            61: static int ip_proto_connect(struct socket *sock, struct sockaddr *uservaddr,
        !            62:                              int sockaddr_len, int flags);
        !            63: static int ip_proto_socketpair(struct socket *sock1, struct socket *sock2);
        !            64: static int ip_proto_accept(struct socket *sock, struct socket *newsock, int flags);
        !            65: static int ip_proto_getname(struct socket *sock, struct sockaddr *usockaddr,
        !            66:                              int *usockaddr_len, int peer);
        !            67: static int ip_proto_read(struct socket *sock, char *ubuf, int size,
        !            68:                           int nonblock);
        !            69: static int ip_proto_write(struct socket *sock, char *ubuf, int size,
        !            70:                            int nonblock);
        !            71: static int ip_proto_select(struct socket *sock, int which, select_table *wait);
        !            72: static int ip_proto_ioctl(struct socket *sock, unsigned int cmd,
        !            73:                            unsigned long arg);
        !            74: static int ip_proto_listen(struct socket *sock, int backlog);
        !            75: 
        !            76: static int ip_proto_send (struct socket *sock, void *buff, int len,
        !            77:                          int nonblock, unsigned flags);
        !            78: static int ip_proto_recv (struct socket *sock, void *buff, int len,
        !            79:                          int nonblock, unsigned flags);
        !            80: static int ip_proto_sendto (struct socket *sock, void *buff, int len,
        !            81:                            int nonblock, unsigned flags,
        !            82:                            struct sockaddr *addr, int addr_len);
        !            83: static int ip_proto_recvfrom (struct socket *sock, void *buff, int len,
        !            84:                              int nonblock, unsigned flags,
        !            85:                              struct sockaddr *addr, int *addr_len);
        !            86: 
        !            87: static int ip_proto_shutdown (struct socket *sock, int how);
        !            88: 
        !            89: 
        !            90: static int ip_proto_setsockopt (struct socket *sock, int level, int optname,
        !            91:                                char *optval, int optlen);
        !            92: static int ip_proto_getsockopt (struct socket *sock, int level, int optname,
        !            93:                                char *optval, int *optlen);
        !            94: static int ip_proto_fcntl (struct socket *sock, unsigned int cmd,
        !            95:                           unsigned long arg);
        !            96: 
        !            97: 
        !            98: struct proto_ops inet_proto_ops = 
        !            99: {
        !           100:   ip_proto_init,
        !           101:   ip_proto_create,
        !           102:   ip_proto_dup,
        !           103:   ip_proto_release,
        !           104:   ip_proto_bind,
        !           105:   ip_proto_connect,
        !           106:   ip_proto_socketpair,
        !           107:   ip_proto_accept,
        !           108:   ip_proto_getname, 
        !           109:   ip_proto_read,
        !           110:   ip_proto_write,
        !           111:   ip_proto_select,
        !           112:   ip_proto_ioctl,
        !           113:   ip_proto_listen,
        !           114:   ip_proto_send,
        !           115:   ip_proto_recv,
        !           116:   ip_proto_sendto,
        !           117:   ip_proto_recvfrom,
        !           118:   ip_proto_shutdown,
        !           119:   ip_proto_setsockopt,
        !           120:   ip_proto_getsockopt,
        !           121:   ip_proto_fcntl
        !           122: };
        !           123: 
        !           124: void
        !           125: print_sk (volatile struct sock *sk)
        !           126: {
        !           127:   PRINTK ("  wmem_alloc = %d\n", sk->wmem_alloc);
        !           128:   PRINTK ("  rmem_alloc = %d\n", sk->rmem_alloc);
        !           129:   PRINTK ("  send_head = %X\n", sk->send_head);
        !           130:   PRINTK ("  state = %d\n",sk->state);
        !           131:   PRINTK ("  wback = %X, rqueue = %X\n", sk->wback, sk->rqueue);
        !           132:   PRINTK ("  wfront = %X\n", sk->wfront);
        !           133:   PRINTK ("  daddr = %X, saddr = %X\n", sk->daddr,sk->saddr);
        !           134:   PRINTK ("  num = %d", sk->num);
        !           135:   PRINTK (" next = %X\n", sk->next);
        !           136:   PRINTK ("  send_seq = %d, acked_seq = %d, copied_seq = %d\n",
        !           137:          sk->send_seq, sk->acked_seq, sk->copied_seq);
        !           138:   PRINTK ("  rcv_ack_seq = %d, window_seq = %d, fin_seq = %d\n",
        !           139:          sk->rcv_ack_seq, sk->window_seq, sk->fin_seq);
        !           140:   PRINTK ("  prot = %X\n", sk->prot);
        !           141:   PRINTK ("  pair = %X, back_log = %X\n", sk->pair,sk->back_log);
        !           142:   PRINTK ("  inuse = %d , blog = %d\n", sk->inuse, sk->blog);
        !           143:   PRINTK ("  dead = %d delay_acks=%d\n", sk->dead, sk->delay_acks);
        !           144:   PRINTK ("  retransmits = %d, timeout = %d\n", sk->retransmits, sk->timeout);
        !           145:   PRINTK ("  cong_window = %d, packets_out = %d\n", sk->cong_window,
        !           146:          sk->packets_out);
        !           147: }
        !           148: 
        !           149: void
        !           150: print_skb(struct sk_buff *skb)
        !           151: {
        !           152:   PRINTK ("  prev = %X, next = %X\n", skb->prev, skb->next);
        !           153:   PRINTK ("  sk = %X link3 = %X\n", skb->sk, skb->link3);
        !           154:   PRINTK ("  mem_addr = %X, mem_len = %d\n", skb->mem_addr, skb->mem_len);
        !           155:   PRINTK ("  used = %d free = %d\n", skb->used,skb->free);
        !           156: }
        !           157: 
        !           158: /* just used to reference some pointers to keep gcc from over optimizing
        !           159:    my code so that it doesn't work. */
        !           160: void dummy_routine(void *dummy, ...)
        !           161: {
        !           162:    return;
        !           163: }
        !           164: 
        !           165: void
        !           166: lock_skb (struct sk_buff *skb)
        !           167: {
        !           168:    if (skb->lock)
        !           169:      {
        !           170:        printk ("*** bug more than one lock on sk_buff. \n");
        !           171:      }
        !           172:    skb->lock = 1;
        !           173: }
        !           174: 
        !           175: 
        !           176: void
        !           177: free_skb (struct sk_buff *skb, int rw)
        !           178: {
        !           179:    if (skb->lock)
        !           180:      {
        !           181:        skb->free = 1;
        !           182:        return;
        !           183:      }
        !           184:    if (skb->sk)
        !           185:      {
        !           186:        if (rw)
        !           187:          {
        !           188:             skb->sk->prot->rfree (skb->sk, skb->mem_addr, skb->mem_len);
        !           189:          }
        !           190:        else
        !           191:          {
        !           192:             skb->sk->prot->wfree (skb->sk, skb->mem_addr, skb->mem_len);
        !           193:          }
        !           194:      }
        !           195:    else
        !           196:      {
        !           197:        free_s (skb->mem_addr, skb->mem_len);
        !           198:      }
        !           199: }
        !           200: 
        !           201: void
        !           202: unlock_skb (struct sk_buff *skb, int rw)
        !           203: {
        !           204:    if (skb->lock != 1)
        !           205:      {
        !           206:        printk ("*** bug unlocking non-locked sk_buff. \n");
        !           207:      }
        !           208:    skb->lock = 0;
        !           209:    if (skb->free)
        !           210:      free_skb (skb, rw);
        !           211: }
        !           212: 
        !           213: static  int
        !           214: sk_inuse( struct proto *prot, int num)
        !           215: {
        !           216:   volatile struct sock *sk;
        !           217:   for (sk = prot->sock_array[num & (SOCK_ARRAY_SIZE -1 )];
        !           218:        sk != NULL; sk=sk->next)
        !           219:     {
        !           220:       if (sk->dummy_th.source == num) return (1);
        !           221:     }
        !           222:   return (0);
        !           223: }
        !           224: 
        !           225: unsigned short
        !           226: get_new_socknum(struct proto *prot, unsigned short base)
        !           227: {
        !           228:   static int start=0;
        !           229:   /* used to cycle through the port numbers so the chances of
        !           230:      a confused connection drop. */
        !           231: 
        !           232:   int i,j;
        !           233:   int best=0;
        !           234:   int size=32767; /* a big num. */
        !           235:   volatile struct sock *sk;
        !           236:   start++;
        !           237:   if (base == 0) base = PROT_SOCK+1+(start % 1024);
        !           238:   if (base <= PROT_SOCK)
        !           239:     {
        !           240:       base += PROT_SOCK+(start % 1024);
        !           241:     }
        !           242: 
        !           243:   /* now look through the entire array and try to find an empty
        !           244:      ptr. */
        !           245:   for (i = 0; i < SOCK_ARRAY_SIZE; i++)
        !           246:     {
        !           247:       j = 0;
        !           248:       sk = prot->sock_array[(i+base+1) & (SOCK_ARRAY_SIZE -1)];
        !           249:       while (sk != NULL)
        !           250:        {
        !           251:          sk = sk->next;
        !           252:          j++;
        !           253:        }
        !           254:       if (j == 0) return (i+base+1);
        !           255:       if (j < size) 
        !           256:        {
        !           257:          best = i;
        !           258:          size = j;
        !           259:        }
        !           260:     }
        !           261:   /* now make sure the one we want is not in use. */
        !           262:   while (sk_inuse (prot, base +best+1))
        !           263:     {
        !           264:       best += SOCK_ARRAY_SIZE;
        !           265:     }
        !           266:   return (best+base+1);
        !           267:   
        !           268: }
        !           269: 
        !           270: void
        !           271: put_sock(unsigned short num, volatile struct sock *sk)
        !           272: {
        !           273:    volatile struct sock *sk1;
        !           274:    volatile struct sock *sk2;
        !           275:    int mask;
        !           276: 
        !           277:    PRINTK ("put_sock (num = %d, sk = %X\n", num, sk);
        !           278:    sk->num = num;
        !           279:    sk->next = NULL;
        !           280:    num = num & (SOCK_ARRAY_SIZE -1);
        !           281: 
        !           282:    /* we can't have an interupt renter here. */
        !           283:    cli();
        !           284:    if (sk->prot->sock_array[num] == NULL)
        !           285:      {
        !           286:        sk->prot->sock_array[num] = sk;
        !           287:        sti();
        !           288:        return;
        !           289:      }
        !           290:    sti();
        !           291:    for (mask = 0xff000000; mask != 0xffffffff; mask = (mask >> 8) | mask)
        !           292:      {
        !           293:        if (mask & sk->saddr)
        !           294:          {
        !           295:             mask = mask << 8;
        !           296:             break;
        !           297:          }
        !           298:      }
        !           299: 
        !           300:    PRINTK ("mask = %X\n", mask);
        !           301: 
        !           302:    cli();
        !           303:    sk1 = sk->prot->sock_array[num];
        !           304:    for (sk2 = sk1; sk2 != NULL; sk2=sk2->next)
        !           305:      {
        !           306:        if (!(sk2->saddr & mask))
        !           307:          {
        !           308:             if (sk2 == sk1)
        !           309:               {
        !           310:                  sk->next = sk->prot->sock_array[num];
        !           311:                  sk->prot->sock_array[num] = sk;
        !           312:                  sti();
        !           313:                  return;
        !           314:               }
        !           315:             sk->next = sk2;
        !           316:             sk1->next= sk;
        !           317:             sti();
        !           318:             return;
        !           319:          }
        !           320:        sk1 = sk2;
        !           321:      }
        !           322:    /* goes at the end. */
        !           323:    sk->next = NULL;
        !           324:    sk1->next = sk;
        !           325:    sti();
        !           326: }
        !           327: 
        !           328: 
        !           329: static void
        !           330: remove_sock(volatile struct sock *sk1)
        !           331: {
        !           332:   volatile struct sock *sk2;
        !           333:   PRINTK ("remove_sock(sk1=%X)\n",sk1);
        !           334: 
        !           335:   /* we can't have this changing out from under us. */
        !           336:   cli();
        !           337:   sk2=sk1->prot->sock_array[sk1->num & (SOCK_ARRAY_SIZE -1)];
        !           338:   if (sk2 == sk1)
        !           339:     {
        !           340:        sk1->prot->sock_array[sk1->num & (SOCK_ARRAY_SIZE -1)] = sk1->next;
        !           341:        sti();
        !           342:        return;
        !           343:     }
        !           344:   while (sk2->next != sk1)
        !           345:     {
        !           346:       if (sk2 == NULL)
        !           347:        {
        !           348:          sti();
        !           349:          PRINTK ("remove_sock: sock  not found.\n");
        !           350:          return;
        !           351:        }
        !           352:       sk2=sk2->next;
        !           353:     }
        !           354:   sk2->next = sk1->next;
        !           355:   sti();
        !           356: }
        !           357: 
        !           358: void
        !           359: destroy_sock(volatile struct sock *sk)
        !           360: {
        !           361: 
        !           362:   struct sk_buff *skb;
        !           363:   PRINTK ("destroying socket %X\n",sk);
        !           364:   /* just to be safe. */
        !           365:   sk->inuse = 1;
        !           366: 
        !           367:   remove_sock (sk);
        !           368:   /* now we can no longer get new packets. */
        !           369: 
        !           370:   delete_timer((struct timer *)&sk->time_wait);
        !           371: 
        !           372:   /* cleanup up the write buffer. */
        !           373:   for (skb = sk->wfront; skb != NULL; )
        !           374:     {
        !           375:       struct sk_buff *skb2;
        !           376:       skb2=skb->next;
        !           377:       free_skb(skb, FREE_WRITE);
        !           378:       skb=skb2;
        !           379:     }
        !           380: 
        !           381:   sk->wfront = NULL;
        !           382: 
        !           383:   if (sk->rqueue != NULL)
        !           384:     {
        !           385:        skb = sk->rqueue;
        !           386:        do {
        !           387:          struct sk_buff *skb2;
        !           388:          skb2=skb->next;
        !           389:          /* this will take care of closing sockets that were
        !           390:             listening and didn't accept everything. */
        !           391: 
        !           392:          if (skb->sk != NULL && skb->sk != sk)
        !           393:            {
        !           394:               skb->sk->dead = 1;
        !           395:               skb->sk->prot->close (skb->sk, 0);
        !           396:            }
        !           397:          free_skb(skb, FREE_READ);
        !           398:          skb=skb2;
        !           399:        } while (skb != sk->rqueue);
        !           400:     }
        !           401: 
        !           402:   sk->rqueue = NULL;
        !           403: 
        !           404:   /* now we need to clean up the send head. */
        !           405:   for (skb = sk->send_head; skb != NULL; )
        !           406:     {
        !           407:       struct sk_buff *skb2;
        !           408:       /* we need to remove skb from the transmit queue. */
        !           409:       cli();
        !           410:       /* see if it's in a transmit queue. */
        !           411:       if (skb->next != NULL)
        !           412:        {
        !           413:           if (skb->next != skb)
        !           414:             {
        !           415:                skb->next->prev = skb->prev;
        !           416:                skb->prev->next = skb->next;
        !           417:             }
        !           418:           else
        !           419:             {
        !           420:                int i;
        !           421:                for (i = 0; i < DEV_NUMBUFFS; i++)
        !           422:                  {
        !           423:                     if (skb->dev && skb->dev->buffs[i] == skb)
        !           424:                       {
        !           425:                          skb->dev->buffs[i]= NULL;
        !           426:                          break;
        !           427:                       }
        !           428:                  }
        !           429:             }
        !           430:        }
        !           431:       sti();
        !           432:       skb2=skb->link3;
        !           433:       free_skb(skb, FREE_WRITE);
        !           434:       skb=skb2;
        !           435:     }
        !           436: 
        !           437:   sk->send_head = NULL;
        !           438: 
        !           439:   /* and now the backlog. */
        !           440: 
        !           441:   if (sk->back_log != NULL)
        !           442:     {
        !           443:        /* this should never happen. */
        !           444:        printk ("cleaning back_log. \n");
        !           445:        cli();
        !           446:        skb = sk->back_log;
        !           447:        do {
        !           448:          struct sk_buff *skb2;
        !           449:          skb2=skb->next;
        !           450:          free_skb(skb, FREE_READ);
        !           451:          skb=skb2;
        !           452:        } while (skb != sk->back_log);
        !           453:        sti();
        !           454:     }
        !           455: 
        !           456:   sk->back_log = NULL;
        !           457: 
        !           458:   /* now if everything is gone we can free the socket structure, 
        !           459:      otherwise we need to keep it around until everything is gone. */
        !           460:   if (sk->rmem_alloc == 0 && sk->wmem_alloc == 0)
        !           461:     {
        !           462:        free_s ((void *)sk,sizeof (*sk));
        !           463:     }
        !           464:   else
        !           465:     {
        !           466:        /* this should never happen. */
        !           467:        /* actually it can if an ack has just been sent. */
        !           468:        PRINTK ("possible memory leak in socket = %X\n", sk);
        !           469:        print_sk (sk);
        !           470:        sk->destroy = 1;
        !           471:        sk->ack_backlog = 0;
        !           472:        sk->inuse = 0;
        !           473:        sk->time_wait.len = SOCK_DESTROY_TIME;
        !           474:        sk->timeout = TIME_DESTROY;
        !           475:        reset_timer ((struct timer *)&sk->time_wait);
        !           476:     }
        !           477:   
        !           478: }
        !           479: 
        !           480: 
        !           481: static int
        !           482: ip_proto_fcntl (struct socket *sock, unsigned int cmd, unsigned long arg)
        !           483: {
        !           484:    volatile struct sock *sk;
        !           485:    sk=sock->data;
        !           486:    if (sk == NULL)
        !           487:      {
        !           488:        printk ("Warning: sock->data = NULL: %d\n" ,__LINE__);
        !           489:        return (0);
        !           490:      }
        !           491:    switch (cmd)
        !           492:      {
        !           493:        case F_SETOWN:
        !           494:        sk->proc = arg;
        !           495:        return (0);
        !           496: 
        !           497:        case F_GETOWN:
        !           498:        return (sk->proc);
        !           499: 
        !           500:        default:
        !           501:        return (-EINVAL);
        !           502:      }
        !           503: }
        !           504: 
        !           505: static int
        !           506: ip_proto_setsockopt(struct socket *sock, int level, int optname,
        !           507:                    char *optval, int optlen)
        !           508: {
        !           509:     volatile struct sock *sk;
        !           510:     int val;
        !           511:     /* This should really pass things on to the other levels. */
        !           512:     if (level != SOL_SOCKET) return (-EOPNOTSUPP);
        !           513:     sk = sock->data;
        !           514:    if (sk == NULL)
        !           515:      {
        !           516:        printk ("Warning: sock->data = NULL: %d\n" ,__LINE__);
        !           517:        return (0);
        !           518:      }
        !           519:     verify_area (optval, sizeof (int));
        !           520:     val = get_fs_long ((unsigned long *)optval);
        !           521:     switch (optname)
        !           522:       {
        !           523:        case SO_TYPE:
        !           524:        case SO_ERROR:
        !           525:        default:
        !           526:          return (-ENOPROTOOPT);
        !           527: 
        !           528:        case SO_DEBUG: /* not implemented. */
        !           529:        case SO_DONTROUTE:
        !           530:        case SO_BROADCAST:
        !           531:        case SO_SNDBUF:
        !           532:        case SO_RCVBUF:
        !           533:          return (0);
        !           534: 
        !           535:        case SO_REUSEADDR:
        !           536:          if (val)
        !           537:            sk->reuse = 1;
        !           538:          else 
        !           539:            sk->reuse = 1;
        !           540:          return (0);
        !           541: 
        !           542:        case SO_KEEPALIVE:
        !           543:          if (val)
        !           544:            sk->keepopen = 1;
        !           545:          else
        !           546:            sk->keepopen = 0;
        !           547:          return (0);
        !           548: 
        !           549:         case SO_OOBINLINE:
        !           550:          if (val)
        !           551:            sk->urginline = 1;
        !           552:          else
        !           553:            sk->urginline = 0;
        !           554:          return (0);
        !           555: 
        !           556:         case SO_NO_CHECK:
        !           557:          if (val)
        !           558:            sk->no_check = 1;
        !           559:          else
        !           560:            sk->no_check = 0;
        !           561:          return (0);
        !           562: 
        !           563:         case SO_PRIORITY:
        !           564:          if (val >= 0 && val < DEV_NUMBUFFS)
        !           565:            {
        !           566:               sk->priority = val;
        !           567:            }
        !           568:          else
        !           569:            {
        !           570:               return (-EINVAL);
        !           571:            }
        !           572:          return (0);
        !           573: 
        !           574:       }
        !           575: }
        !           576: 
        !           577: static int
        !           578: ip_proto_getsockopt(struct socket *sock, int level, int optname,
        !           579:                    char *optval, int *optlen)
        !           580: {
        !           581:     volatile struct sock *sk;
        !           582:     int val;
        !           583:     /* This should really pass things on to the other levels. */
        !           584:     if (level != SOL_SOCKET) return (-EOPNOTSUPP);
        !           585:     sk = sock->data;
        !           586:    if (sk == NULL)
        !           587:      {
        !           588:        printk ("Warning: sock->data = NULL: %d\n" ,__LINE__);
        !           589:        return (0);
        !           590:      }
        !           591:     switch (optname)
        !           592:       {
        !           593:        default:
        !           594:          return (-ENOPROTOOPT);
        !           595: 
        !           596:        case SO_DEBUG: /* not implemented. */
        !           597:        case SO_DONTROUTE:
        !           598:        case SO_BROADCAST:
        !           599:        case SO_SNDBUF:
        !           600:        case SO_RCVBUF:
        !           601:          val = 0;
        !           602:          break;
        !           603: 
        !           604:        case SO_REUSEADDR:
        !           605:          val = sk->reuse;
        !           606:          break;
        !           607: 
        !           608:        case SO_KEEPALIVE:
        !           609:          val = sk->keepopen;
        !           610:          break;
        !           611: 
        !           612:        case SO_TYPE:
        !           613:          if (sk->prot == &tcp_prot)
        !           614:            val = SOCK_STREAM;
        !           615:          else
        !           616:            val = SOCK_DGRAM;
        !           617:          break;
        !           618: 
        !           619:        case SO_ERROR:
        !           620:          val = sk->err;
        !           621:          sk->err = 0;
        !           622:          break;
        !           623: 
        !           624:         case SO_OOBINLINE:
        !           625:          val = sk->urginline;
        !           626:          break;
        !           627: 
        !           628:         case SO_NO_CHECK:
        !           629:          val = sk->no_check;
        !           630:          break;
        !           631: 
        !           632:         case SO_PRIORITY:
        !           633:          val = sk->priority;
        !           634:          break;
        !           635:       }
        !           636:     verify_area (optlen, sizeof (int));
        !           637:     put_fs_long (sizeof(int),(unsigned long *) optlen);
        !           638: 
        !           639:     verify_area(optval, sizeof (int));
        !           640:     put_fs_long (val, (unsigned long *)optval);
        !           641:     return (0);
        !           642: }
        !           643: 
        !           644: static int
        !           645: ip_proto_listen(struct socket *sock, int backlog)
        !           646: {
        !           647:   volatile struct sock *sk;
        !           648:   sk = sock->data;
        !           649:    if (sk == NULL)
        !           650:      {
        !           651:        printk ("Warning: sock->data = NULL: %d\n" ,__LINE__);
        !           652:        return (0);
        !           653:      }
        !           654:   sk->state = TCP_LISTEN;
        !           655:   return (0);
        !           656: }
        !           657: 
        !           658: /* Hardware should be inited here. */
        !           659: static int ip_proto_init(void)
        !           660: {
        !           661:   int i;
        !           662:   struct device *dev;
        !           663:   struct ip_protocol *p;
        !           664:   seq_offset = CURRENT_TIME*250;
        !           665:   /* add all the protocols. */
        !           666:   for (i = 0; i < SOCK_ARRAY_SIZE; i++)
        !           667:     {
        !           668:        tcp_prot.sock_array[i] = NULL;
        !           669:        udp_prot.sock_array[i] = NULL;
        !           670:        raw_prot.sock_array[i] = NULL;
        !           671:     }
        !           672: 
        !           673:   for (p = ip_protocol_base; p != NULL;)
        !           674:     {
        !           675:        struct ip_protocol *tmp;
        !           676:        /* add all the protocols. */
        !           677:        tmp = p->next;
        !           678:        add_ip_protocol (p);
        !           679:        p = tmp;
        !           680:     }
        !           681: 
        !           682:   /* add the devices */
        !           683:   for (dev = dev_base; dev != NULL; dev=dev->next)
        !           684:     {
        !           685:        if (dev->init)
        !           686:         dev->init(dev);
        !           687:     }
        !           688:   timer_table[NET_TIMER].fn = net_timer;
        !           689:   return (0);
        !           690: }
        !           691: 
        !           692: static int
        !           693: ip_proto_create (struct socket *sock, int protocol)
        !           694: {
        !           695:   volatile struct sock *sk;
        !           696:   struct proto *prot;
        !           697:   int err;
        !           698: 
        !           699:   sk = malloc (sizeof (*sk));
        !           700:   if (sk == NULL)
        !           701:     return (-ENOMEM);
        !           702:   sk->num = 0;
        !           703: 
        !           704: 
        !           705:   switch (sock->type)
        !           706:     {
        !           707:     case SOCK_STREAM:
        !           708:     case SOCK_SEQPACKET:
        !           709:        if (protocol && protocol != IP_TCP)
        !           710:         {
        !           711:            free_s ((void *)sk, sizeof (*sk));
        !           712:            return (-EPROTONOSUPPORT);
        !           713:         }
        !           714:        sk->no_check = TCP_NO_CHECK;
        !           715:        prot = &tcp_prot;
        !           716:        break;
        !           717: 
        !           718:     case SOCK_DGRAM:
        !           719:        if (protocol && protocol != IP_UDP)
        !           720:         {
        !           721:            free_s ((void *)sk, sizeof (*sk));
        !           722:            return (-EPROTONOSUPPORT);
        !           723:         }
        !           724:        sk->no_check = UDP_NO_CHECK;
        !           725:        prot=&udp_prot;
        !           726:        break;
        !           727:       
        !           728:      case SOCK_RAW:
        !           729:        if (!suser())
        !           730:         {
        !           731:            free_s ((void *)sk, sizeof (*sk));
        !           732:            return (-EPERM);
        !           733:         }
        !           734: 
        !           735:        if (!protocol)
        !           736:         {
        !           737:            free_s ((void *)sk, sizeof (*sk));
        !           738:            return (-EPROTONOSUPPORT);
        !           739:         }
        !           740:        prot = &raw_prot;
        !           741:        sk->reuse = 1;
        !           742:        sk->no_check = 0; /* doesn't matter no checksum is preformed
        !           743:                            anyway. */
        !           744:        sk->num = protocol;
        !           745:        break;
        !           746: 
        !           747:     case SOCK_PACKET:
        !           748:        if (!suser())
        !           749:         {
        !           750:            free_s ((void *)sk, sizeof (*sk));
        !           751:            return (-EPERM);
        !           752:         }
        !           753: 
        !           754:        if (!protocol)
        !           755:         {
        !           756:            free_s ((void *)sk, sizeof (*sk));
        !           757:            return (-EPROTONOSUPPORT);
        !           758:         }
        !           759:        prot = &packet_prot;
        !           760:        sk->reuse = 1;
        !           761:        sk->no_check = 0; /* doesn't matter no checksum is preformed
        !           762:                            anyway. */
        !           763:        sk->num = protocol;
        !           764:        break;
        !           765: 
        !           766:       
        !           767:     default:
        !           768:        free_s ((void *)sk, sizeof (*sk));
        !           769:        return (-ESOCKTNOSUPPORT);
        !           770: 
        !           771:     }
        !           772:   sk->protocol = protocol;
        !           773:   sk->wmem_alloc = 0;
        !           774:   sk->rmem_alloc = 0;
        !           775:   sk->pair = NULL;
        !           776:   sk->opt = NULL;
        !           777:   sk->send_seq = 0;
        !           778:   sk->acked_seq = 0;
        !           779:   sk->copied_seq = 0;
        !           780:   sk->fin_seq = 0;
        !           781:   sk->proc = 0;
        !           782:   sk->rtt = TCP_WRITE_TIME;
        !           783:   sk->packets_out = 0;
        !           784:   sk->cong_window = 1; /* start with only sending one packet at a time. */
        !           785:   sk->exp_growth = 1;  /* if set cong_window grow exponentially every time
        !           786:                          we get an ack. */
        !           787:   sk->urginline = 0;
        !           788:   sk->intr = 0;
        !           789:   sk->linger = 0;
        !           790:   sk->destroy = 0;
        !           791:   sk->reuse = 0;
        !           792:   sk->priority = 1;
        !           793:   sk->shutdown = 0;
        !           794:   sk->urg = 0;
        !           795:   sk->keepopen = 0;
        !           796:   sk->done = 0;
        !           797:   sk->ack_backlog = 0;
        !           798:   sk->window = 0;
        !           799:   sk->bytes_rcv = 0;
        !           800:   sk->state = TCP_CLOSE;
        !           801:   sk->dead = 0;
        !           802:   sk->ack_timed = 0;
        !           803: 
        !           804:   /* this is how many unacked bytes we will accept for
        !           805:      this socket.  */
        !           806: 
        !           807:   sk->max_unacked = 2048; /* needs to be at most 2 full packets. */
        !           808: 
        !           809:   /* how many packets we should send before forcing an ack. 
        !           810:      if this is set to zero it is the same as sk->delay_acks = 0 */
        !           811: 
        !           812:   sk->max_ack_backlog = MAX_ACK_BACKLOG;
        !           813:   sk->inuse = 0;
        !           814:   sk->delay_acks = 1; /* default to waiting a while before sending
        !           815:                         acks.  */
        !           816:   sk->wback = NULL;
        !           817:   sk->wfront = NULL;
        !           818:   sk->rqueue = NULL;
        !           819:   sk->mtu = 576;
        !           820:   sk->prot = prot;
        !           821:   sk->sleep = sock->wait;
        !           822:   sk->daddr = 0;
        !           823:   sk->saddr = MY_IP_ADDR;
        !           824:   sk->err = 0;
        !           825:   sk->next = NULL;
        !           826:   sk->pair = NULL;
        !           827:   sk->send_tail = NULL;
        !           828:   sk->send_head = NULL;
        !           829:   sk->time_wait.len = TCP_CONNECT_TIME;
        !           830:   sk->time_wait.when = 0;
        !           831:   sk->time_wait.sk = sk;
        !           832:   sk->time_wait.next = NULL;
        !           833:   sk->timeout = 0;
        !           834:   sk->back_log = NULL;
        !           835:   sk->blog = 0;
        !           836:   sock->data =(void *) sk;
        !           837:   sk->dummy_th.doff = sizeof (sk->dummy_th)/4;
        !           838:   sk->dummy_th.res1=0;
        !           839:   sk->dummy_th.res2=0;
        !           840:   sk->dummy_th.urg_ptr = 0;
        !           841:   sk->dummy_th.fin = 0;
        !           842:   sk->dummy_th.syn = 0;
        !           843:   sk->dummy_th.rst = 0;
        !           844:   sk->dummy_th.psh = 0;
        !           845:   sk->dummy_th.ack = 0;
        !           846:   sk->dummy_th.urg = 0;
        !           847:   sk->dummy_th.dest = 0;
        !           848:   if (sk->num)
        !           849:     {
        !           850:        put_sock (sk->num, sk);
        !           851:     }
        !           852:   else
        !           853:     {
        !           854:        sk->num = get_new_socknum(sk->prot, 0);
        !           855:     }
        !           856:   /* make sure there was a free socket. */
        !           857:   if (sk->num == 0)
        !           858:     {
        !           859:       destroy_sock(sk);
        !           860:       return (-EAGAIN);
        !           861:     }
        !           862:   put_sock(sk->num, sk);
        !           863:   sk->dummy_th.source = net16(sk->num);
        !           864:   if (sk->prot->init)
        !           865:     {
        !           866:        err = sk->prot->init(sk);
        !           867:        if (err != 0)
        !           868:         {
        !           869:            destroy_sock (sk);
        !           870:            return (err);
        !           871:         }
        !           872:     }
        !           873:   return (0);
        !           874: }
        !           875: 
        !           876: static int
        !           877: ip_proto_dup (struct socket *newsock, struct socket *oldsock)
        !           878: {
        !           879:   return (ip_proto_create (newsock,
        !           880:                           ((volatile struct sock *)(oldsock->data))->protocol));
        !           881: }
        !           882: 
        !           883: /* the peer socket should always be NULL. */
        !           884: static int
        !           885: ip_proto_release(struct socket *sock, struct socket *peer)
        !           886: {
        !           887:   volatile struct sock *sk;
        !           888:   sk = sock->data;
        !           889:   if (sk == NULL) return (0);
        !           890:   wake_up (sk->sleep);
        !           891:   /* start closing the connection.  This may take a while. */
        !           892:   /* if linger is set, we don't return until the close is
        !           893:      complete.  Other wise we return immediately.  The
        !           894:      actually closing is done the same either way. */
        !           895:   if (sk->linger == 0)
        !           896:     {
        !           897:        sk->prot->close(sk,0);
        !           898:        sk->dead = 1;
        !           899:     }
        !           900:   else
        !           901:     {
        !           902:        sk->prot->close(sk, 0);
        !           903:        cli();
        !           904:        while (sk->state != TCP_CLOSE)
        !           905:         {
        !           906:            interruptible_sleep_on (sk->sleep);
        !           907:            if (current->signal & ~current->blocked)
        !           908:              {
        !           909:                 sti();
        !           910:                 return (-ERESTARTSYS);
        !           911:              }
        !           912:         }
        !           913:        sti();
        !           914:        sk->dead = 1;
        !           915:     }
        !           916: 
        !           917:   sk->inuse = 1;
        !           918:   /* this will destroy it. */
        !           919:   release_sock (sk);
        !           920:   sock->data = NULL;
        !           921:   return (0);
        !           922: }
        !           923: 
        !           924: 
        !           925: static int
        !           926: ip_proto_bind (struct socket *sock, struct sockaddr *uaddr,
        !           927:               int addr_len)
        !           928: {
        !           929:   struct sockaddr_in addr;
        !           930:   volatile struct sock *sk, *sk2;
        !           931:   unsigned short snum;
        !           932:   sk = sock->data;
        !           933:    if (sk == NULL)
        !           934:      {
        !           935:        printk ("Warning: sock->data = NULL: %d\n" ,__LINE__);
        !           936:        return (0);
        !           937:      }
        !           938:   /* check this error. */
        !           939:   if (sk->state != TCP_CLOSE) return (-EIO);
        !           940:   verify_area (uaddr, addr_len);
        !           941:   memcpy_fromfs (&addr, uaddr, min (sizeof (addr), addr_len));
        !           942:   if (addr.sin_family && addr.sin_family != AF_INET)
        !           943:     return (-EIO); /* this needs to be changed. */
        !           944:   snum = net16(addr.sin_port);
        !           945:   PRINTK ("bind sk =%X to port = %d\n", sk, snum);
        !           946:   print_sk (sk);
        !           947:   sk = sock->data;
        !           948: 
        !           949:   /* we can't just leave the socket bound wherever it is, it might be bound
        !           950:      to a priveledged port. However, since there seems to be a bug here,
        !           951:      we will leave it if the port is not priveledged(sp?) */
        !           952: 
        !           953:   if (snum == 0)
        !           954:     {
        !           955:        if ( sk->num > PROT_SOCK) return (0);
        !           956:        snum = get_new_socknum (sk->prot, 0);
        !           957:     }
        !           958: 
        !           959:   if (snum <= PROT_SOCK && !suser())
        !           960:     return (-EPERM);
        !           961: 
        !           962:   if (my_ip_addr(addr.sin_addr.s_addr) || addr.sin_addr.s_addr == 0)
        !           963:     sk->saddr = addr.sin_addr.s_addr;
        !           964:   PRINTK ("sock_array[%d] = %X:\n", snum & (SOCK_ARRAY_SIZE -1),
        !           965:          sk->prot->sock_array[snum & (SOCK_ARRAY_SIZE -1)]);
        !           966:   print_sk (sk->prot->sock_array[snum & (SOCK_ARRAY_SIZE -1)]);
        !           967: 
        !           968:   /* make sure we are allowed to bind here. */
        !           969:   for (sk2 = sk->prot->sock_array[snum & (SOCK_ARRAY_SIZE -1)];
        !           970:        sk2 != NULL;
        !           971:        sk2 = sk2->next)
        !           972:     {
        !           973:        if (sk2->num != snum) continue;
        !           974:        if (sk2->saddr != sk->saddr) continue;
        !           975:        if (!sk->reuse) return (-EADDRINUSE);
        !           976:        if (!sk2->reuse) return (-EADDRINUSE);
        !           977:     }
        !           978:   remove_sock (sk);
        !           979:   put_sock(snum, sk);
        !           980:   sk->dummy_th.source = net16(sk->num);
        !           981:   sk->daddr = 0;
        !           982:   sk->dummy_th.dest = 0;
        !           983:   return (0);
        !           984: }
        !           985: 
        !           986: static int
        !           987: ip_proto_connect (struct socket *sock, struct sockaddr * uaddr,
        !           988:                  int addr_len, int flags)
        !           989: {
        !           990:   volatile struct sock *sk;
        !           991:   int err;
        !           992:   sock->conn = NULL;
        !           993:   sk = sock->data;
        !           994:    if (sk == NULL)
        !           995:      {
        !           996:        printk ("Warning: sock->data = NULL: %d\n" ,__LINE__);
        !           997:        return (0);
        !           998:      }
        !           999:   if (sk->prot->connect == NULL)
        !          1000:     return (-EOPNOTSUPP);
        !          1001: 
        !          1002:   if (sk->intr == 0)
        !          1003:     {
        !          1004:       err = sk->prot->connect (sk, (struct sockaddr_in *)uaddr, addr_len);
        !          1005:       if (err < 0) return (err);
        !          1006:     }
        !          1007: 
        !          1008:   sock->state = SS_CONNECTED;
        !          1009: 
        !          1010:   if (flags & O_NONBLOCK) return (0);
        !          1011: 
        !          1012:   cli(); /* avoid the race condition */
        !          1013: 
        !          1014:   while (sk->state != TCP_ESTABLISHED && sk->state < TCP_CLOSING)
        !          1015:     {
        !          1016:       interruptible_sleep_on (sk->sleep);
        !          1017:       if (current->signal & ~current->blocked)
        !          1018:        {
        !          1019:           sti();
        !          1020:           sk->intr = 1;
        !          1021:           return (-ERESTARTSYS);
        !          1022:        }
        !          1023:     }
        !          1024:   sti();
        !          1025:   sk->intr = 0;
        !          1026:   if (sk->state != TCP_ESTABLISHED && sk->err)
        !          1027:     {
        !          1028:       return (-sk->err);
        !          1029:     }
        !          1030:   return (0);
        !          1031: }
        !          1032: 
        !          1033: static int
        !          1034: ip_proto_socketpair (struct socket *sock1, struct socket *sock2)
        !          1035: {
        !          1036:   return (-EOPNOTSUPP);
        !          1037: }
        !          1038: 
        !          1039: static int
        !          1040: ip_proto_accept (struct socket *sock, struct socket *newsock, int flags)
        !          1041: {
        !          1042:   volatile struct sock *sk1, *sk2;
        !          1043:   sk1= sock->data;
        !          1044:    if (sk1 == NULL)
        !          1045:      {
        !          1046:        printk ("Warning: sock->data = NULL: %d\n" ,__LINE__);
        !          1047:        return (0);
        !          1048:      }
        !          1049:   newsock->data = NULL;
        !          1050:   if (sk1->prot->accept == NULL) return (-EOPNOTSUPP);
        !          1051:   /* restore the state if we have been interrupted, and
        !          1052:      then returned. */
        !          1053:   if (sk1->pair != NULL )
        !          1054:     {
        !          1055:       sk2 = sk1->pair;
        !          1056:       sk1->pair = NULL;
        !          1057:     }
        !          1058:   else
        !          1059:     {
        !          1060:       sk2 = sk1->prot->accept (sk1,flags);
        !          1061:       if (sk2 == NULL)
        !          1062:        return (-sk1->err);
        !          1063:     }
        !          1064:   newsock->data = (void *)sk2;
        !          1065:   sk2->sleep = (void *)newsock->wait;
        !          1066:   newsock->conn = NULL;
        !          1067:   if (flags & O_NONBLOCK)
        !          1068:     return (0);
        !          1069: 
        !          1070:   cli(); /* avoid the race. */
        !          1071:   while (sk2->state == TCP_SYN_RECV)
        !          1072:     {
        !          1073:       interruptible_sleep_on (sk2->sleep);
        !          1074:       if (current->signal & ~current->blocked)
        !          1075:        {
        !          1076:           sti();
        !          1077:           sk1->pair = sk2;
        !          1078:           sk2->sleep = NULL;
        !          1079:           newsock->data = NULL;
        !          1080:           return (-ERESTARTSYS);
        !          1081:        }
        !          1082:     }
        !          1083:   sti();
        !          1084: 
        !          1085:   if (sk2->state != TCP_ESTABLISHED && sk2->err)
        !          1086:     {
        !          1087:       int err;
        !          1088:       err = -sk2->err;
        !          1089:       destroy_sock (sk2);
        !          1090:       newsock->data = NULL;
        !          1091:       return (err);
        !          1092:     }
        !          1093:   newsock->state = SS_CONNECTED;
        !          1094:   return (0);
        !          1095: }
        !          1096: 
        !          1097: static int
        !          1098: ip_proto_getname(struct socket *sock, struct sockaddr *uaddr,
        !          1099:                 int *uaddr_len, int peer)
        !          1100: {
        !          1101:   struct sockaddr_in sin;
        !          1102:   volatile struct sock *sk;
        !          1103:   int len;
        !          1104:   verify_area(uaddr_len, sizeof (len));
        !          1105:   len = get_fs_long(uaddr_len);
        !          1106:   /* check this error. */
        !          1107:   if (len < sizeof (sin)) return (-EINVAL);
        !          1108:   verify_area (uaddr, len);
        !          1109:   sin.sin_family=AF_INET;
        !          1110:   sk = sock->data;
        !          1111:   if (sk == NULL)
        !          1112:     {
        !          1113:        printk ("Warning: sock->data = NULL: %d\n" ,__LINE__);
        !          1114:        return (0);
        !          1115:     }
        !          1116:   if (peer)
        !          1117:     {
        !          1118:       if (sk->state != TCP_ESTABLISHED)
        !          1119:        return (-ENOTCONN);
        !          1120:       sin.sin_port = sk->dummy_th.dest;
        !          1121:       sin.sin_addr.s_addr = sk->daddr;
        !          1122:       }
        !          1123:   else
        !          1124:     {
        !          1125:       sin.sin_port = sk->dummy_th.source;
        !          1126:       sin.sin_addr.s_addr = sk->saddr;
        !          1127:     }
        !          1128:   len = sizeof (sin);
        !          1129:   memcpy_tofs(uaddr, &sin, sizeof (sin));
        !          1130:   put_fs_long (len, uaddr_len);
        !          1131:   return (0);
        !          1132: }
        !          1133: 
        !          1134: static int
        !          1135: ip_proto_read (struct socket *sock, char *ubuf, int size, int noblock)
        !          1136: {
        !          1137:   volatile struct sock *sk;
        !          1138:   sk = sock->data;
        !          1139:    if (sk == NULL)
        !          1140:      {
        !          1141:        printk ("Warning: sock->data = NULL: %d\n" ,__LINE__);
        !          1142:        return (0);
        !          1143:      }
        !          1144:   if (sk->shutdown & RCV_SHUTDOWN)
        !          1145:     return (-EIO);
        !          1146:   return (sk->prot->read (sk, ubuf, size, noblock,0));
        !          1147: }
        !          1148: 
        !          1149: static int
        !          1150: ip_proto_recv (struct socket *sock, void *ubuf, int size, int noblock,
        !          1151:               unsigned flags)
        !          1152: {
        !          1153:   volatile struct sock *sk;
        !          1154:   sk = sock->data;
        !          1155:    if (sk == NULL)
        !          1156:      {
        !          1157:        printk ("Warning: sock->data = NULL: %d\n" ,__LINE__);
        !          1158:        return (0);
        !          1159:      }
        !          1160:   if (sk->shutdown & RCV_SHUTDOWN)
        !          1161:     return (-EIO);
        !          1162:   return (sk->prot->read (sk, ubuf, size, noblock, flags));
        !          1163: }
        !          1164: 
        !          1165: static int
        !          1166: ip_proto_write (struct socket *sock, char *ubuf, int size, int noblock)
        !          1167: {
        !          1168:   volatile struct sock *sk;
        !          1169:   sk = sock->data;
        !          1170:    if (sk == NULL)
        !          1171:      {
        !          1172:        printk ("Warning: sock->data = NULL: %d\n" ,__LINE__);
        !          1173:        return (0);
        !          1174:      }
        !          1175:   if (sk->shutdown & SEND_SHUTDOWN)
        !          1176:     return (-EIO);
        !          1177:   return (sk->prot->write (sk, ubuf, size, noblock, 0));
        !          1178: }
        !          1179: 
        !          1180: 
        !          1181: static int
        !          1182: ip_proto_send (struct socket *sock, void *ubuf, int size, int noblock, 
        !          1183:               unsigned flags)
        !          1184: {
        !          1185:   volatile struct sock *sk;
        !          1186:   sk = sock->data;
        !          1187:    if (sk == NULL)
        !          1188:      {
        !          1189:        printk ("Warning: sock->data = NULL: %d\n" ,__LINE__);
        !          1190:        return (0);
        !          1191:      }
        !          1192:   if (sk->shutdown & SEND_SHUTDOWN)
        !          1193:     return (-EIO);
        !          1194:   return (sk->prot->write (sk, ubuf, size, noblock, flags));
        !          1195: }
        !          1196: 
        !          1197: 
        !          1198: static int
        !          1199: ip_proto_sendto (struct socket *sock, void *ubuf, int size, int noblock, 
        !          1200:                 unsigned flags, struct sockaddr *sin, int addr_len )
        !          1201: {
        !          1202:   volatile struct sock *sk;
        !          1203:   sk = sock->data;
        !          1204:    if (sk == NULL)
        !          1205:      {
        !          1206:        printk ("Warning: sock->data = NULL: %d\n" ,__LINE__);
        !          1207:        return (0);
        !          1208:      }
        !          1209:   if (sk->shutdown & SEND_SHUTDOWN)
        !          1210:     return (-EIO);
        !          1211:   if (sk->prot->sendto == NULL) return (-EOPNOTSUPP);
        !          1212:   return (sk->prot->sendto (sk, ubuf, size, noblock, flags, 
        !          1213:                            (struct sockaddr_in *)sin, addr_len));
        !          1214: }
        !          1215: 
        !          1216: static int
        !          1217: ip_proto_recvfrom (struct socket *sock, void *ubuf, int size, int noblock, 
        !          1218:                   unsigned flags, struct sockaddr *sin, int *addr_len )
        !          1219: {
        !          1220:   volatile struct sock *sk;
        !          1221:   sk = sock->data;
        !          1222:    if (sk == NULL)
        !          1223:      {
        !          1224:        printk ("Warning: sock->data = NULL: %d\n" ,__LINE__);
        !          1225:        return (0);
        !          1226:      }
        !          1227:   if (sk->shutdown & RCV_SHUTDOWN)
        !          1228:     return (-EIO);
        !          1229:   if (sk->prot->recvfrom == NULL) return (-EOPNOTSUPP);
        !          1230:   return (sk->prot->recvfrom (sk, ubuf, size, noblock, flags,
        !          1231:                              (struct sockaddr_in*)sin, addr_len));
        !          1232: }
        !          1233: 
        !          1234: static int
        !          1235: ip_proto_shutdown (struct socket *sock, int how)
        !          1236: {
        !          1237:        volatile struct sock *sk;
        !          1238:        /* this should really check to make sure the socket is
        !          1239:           a tcp socket. */
        !          1240:        how++; /* maps 0->1 has the advantage of making bit 1 rcvs and
        !          1241:                       1->2 bit 2 snds.
        !          1242:                       2->3 */
        !          1243:        if (how & ~SHUTDOWN_MASK) return (-EINVAL);
        !          1244:        sk = sock->data;
        !          1245:        if (sk == NULL)
        !          1246:          {
        !          1247:             printk ("Warning: sock->data = NULL: %d\n" ,__LINE__);
        !          1248:             return (0);
        !          1249:          }
        !          1250:        if (sk->state != TCP_ESTABLISHED) return (-ENOTCONN);
        !          1251:        sk->shutdown |= how;
        !          1252:        return (0);
        !          1253: }
        !          1254: 
        !          1255: static int
        !          1256: ip_proto_select (struct socket *sock, int sel_type, select_table *wait )
        !          1257: {
        !          1258:   volatile struct sock *sk;
        !          1259:   sk = sock->data;
        !          1260:    if (sk == NULL)
        !          1261:      {
        !          1262:        printk ("Warning: sock->data = NULL: %d\n" ,__LINE__);
        !          1263:        return (0);
        !          1264:      }
        !          1265: 
        !          1266:   if (sk->prot->select == NULL)
        !          1267:     {
        !          1268:        PRINTK ("select on non-selectable socket. \n");
        !          1269:        return (0);
        !          1270:     }
        !          1271:   return (sk->prot->select(sk, sel_type, wait));
        !          1272: }
        !          1273: 
        !          1274: /* these should be distributed to the different protocol routines. */
        !          1275: static int
        !          1276: ip_proto_ioctl (struct socket *sock, unsigned int cmd, 
        !          1277:                unsigned long arg)
        !          1278: {
        !          1279:    volatile struct sock *sk;
        !          1280:    sk = sock->data;
        !          1281:    if (sk == NULL)
        !          1282:      {
        !          1283:        printk ("Warning: sock->data = NULL: %d\n" ,__LINE__);
        !          1284:        return (0);
        !          1285:      }
        !          1286: 
        !          1287:   PRINTK ("in ip_proto_ioctl\n");
        !          1288:   switch (cmd)
        !          1289:     {
        !          1290: 
        !          1291:       case IP_SET_DEV:
        !          1292:        if (!suser())
        !          1293:         return (-EPERM);
        !          1294:        return (ip_set_dev((struct ip_config *)arg));
        !          1295: #if 0
        !          1296:     case IP_ADD_ROUTE:
        !          1297:       ip_add_route ((struct rtable *) arg);
        !          1298:       return (0);
        !          1299: #endif
        !          1300:     default:
        !          1301:        if (!sk->prot->ioctl)
        !          1302:         return (-EINVAL);
        !          1303:        return (sk->prot->ioctl (sk, cmd, arg));
        !          1304:     }
        !          1305: }
        !          1306: 
        !          1307: #ifdef MEM_DEBUG
        !          1308: 
        !          1309: struct mem
        !          1310: {
        !          1311:    unsigned long check;
        !          1312:    struct mem *other;
        !          1313:    unsigned long len;
        !          1314:    unsigned short buff[10];
        !          1315: };
        !          1316: 
        !          1317: static void
        !          1318: print_mem (struct mem *m)
        !          1319: {
        !          1320:    int i;
        !          1321:    MPRINTK("mem:\n");
        !          1322:    MPRINTK("  check=%X, other = %X\n", m->check, m->other);
        !          1323:    MPRINTK("  len=%d buff:\n " , m->len);
        !          1324:    for (i = 0; i < 10; i++)
        !          1325:      {
        !          1326:        MPRINTK ("0x%02X ",m->buff[i]);
        !          1327:      }
        !          1328:    MPRINTK ("\n");
        !          1329: }
        !          1330: 
        !          1331: static void *
        !          1332: smalloc (unsigned long size)
        !          1333: {
        !          1334:    struct mem *head, *tail;
        !          1335:    static unsigned short count;
        !          1336:    int i;
        !          1337:    int sum;
        !          1338:    unsigned char *ptr;
        !          1339: 
        !          1340:    MPRINTK ("smalloc (size = %d)\n",size);
        !          1341:    head = malloc (size + 2*sizeof (*head));
        !          1342:    if (head == NULL) return (NULL);
        !          1343:    tail = (struct mem *)((unsigned char *)(head+1) + size); 
        !          1344: 
        !          1345:    head->other = tail;
        !          1346:    tail->other = head;
        !          1347: 
        !          1348:    tail->len = size;
        !          1349:    head->len = size;
        !          1350:    for (i = 0; i < 10; i++)
        !          1351:      {
        !          1352:        tail->buff[i]=count++;
        !          1353:        head->buff[i]=count;
        !          1354:      }
        !          1355: 
        !          1356:    ptr = (unsigned char *)head;
        !          1357:    head->check = 0;
        !          1358:    sum = 0;
        !          1359: 
        !          1360:    for (i = 0; i < sizeof (*head); i ++)
        !          1361:      {
        !          1362:        sum+= ptr[i]; 
        !          1363:      }
        !          1364: 
        !          1365:    head->check = ~sum;
        !          1366:    ptr = (unsigned char *)tail;
        !          1367:    tail->check = 0;
        !          1368:    sum = 0;
        !          1369: 
        !          1370:    for (i = 0; i < sizeof (*head); i ++)
        !          1371:      {
        !          1372:        sum+= ptr[i]; 
        !          1373:      }
        !          1374: 
        !          1375:    tail->check = ~sum;
        !          1376:    MPRINTK ("head = %X:\n", head);
        !          1377:    print_mem(head);
        !          1378:    MPRINTK ("tail = %X:\n", tail);
        !          1379:    print_mem(tail);
        !          1380:    return (head+1);
        !          1381: }
        !          1382: 
        !          1383: void
        !          1384: sfree (void *data, unsigned long len)
        !          1385: {
        !          1386:    int i;
        !          1387:    int sum;
        !          1388:    int csum;
        !          1389:    unsigned char *ptr;
        !          1390:    int bad = 0;
        !          1391:    struct mem *head, *tail;
        !          1392:    MPRINTK ("sfree(data=%X, len = %d)\n", data, len);
        !          1393:    head = data;
        !          1394:    head--;
        !          1395:    tail = (struct mem *)((unsigned char *)(head+1) + len);
        !          1396:    print_mem (head);
        !          1397:    print_mem (tail);
        !          1398:    if (head->other != tail)
        !          1399:      {
        !          1400:        MPRINTK ("sfree: head->other != tail:\n");
        !          1401:        bad = 1;
        !          1402:      }
        !          1403:    if (tail->other != head)
        !          1404:      {
        !          1405:        MPRINTK ("sfree: tail->other != head:\n");
        !          1406:        bad =1 ;
        !          1407:      }
        !          1408:    if (head ->len != len)
        !          1409:      {
        !          1410:        MPRINTK ("sfree: head->len != len");
        !          1411:        bad = 1;
        !          1412:      }
        !          1413:    if (tail ->len != len)
        !          1414:      {
        !          1415:        MPRINTK ("sfree: tail->len != len");
        !          1416:        bad = 1;
        !          1417:      }
        !          1418:    csum = head->check;
        !          1419:    ptr = (unsigned char *)head;
        !          1420:    head->check = 0;
        !          1421:    sum = 0;
        !          1422:    for (i = 0; i < sizeof (*head); i ++)
        !          1423:      {
        !          1424:        sum+= ptr[i]; 
        !          1425:      }
        !          1426:    if (csum != ~sum)
        !          1427:      {
        !          1428:        MPRINTK ("sfree: head failed checksum\n");
        !          1429:        bad = 1;
        !          1430:      }
        !          1431:    csum = tail->check;
        !          1432:    ptr = (unsigned char *)tail;
        !          1433:    tail->check = 0;
        !          1434:    sum = 0;
        !          1435:    for (i = 0; i < sizeof (*head); i ++)
        !          1436:      {
        !          1437:        sum+= ptr[i]; 
        !          1438:      }
        !          1439:    if (csum != ~sum)
        !          1440:      {
        !          1441:        MPRINTK ("sfree: tail failed checksum\n");
        !          1442:        bad = 1;
        !          1443:      }
        !          1444:    if (!bad)
        !          1445:      free_s (head, len+2*sizeof (*head));
        !          1446:    else
        !          1447:      schedule();
        !          1448: }
        !          1449: #else
        !          1450: static  void *
        !          1451: smalloc (unsigned long size)
        !          1452: {
        !          1453:    return (malloc (size));
        !          1454: }
        !          1455: static  void
        !          1456: sfree(void *data, unsigned long len)
        !          1457: {
        !          1458:    free_s(data,len);
        !          1459: }
        !          1460: #endif
        !          1461: 
        !          1462: void *
        !          1463: sock_wmalloc(volatile struct sock *sk, unsigned long size, int force)
        !          1464: {
        !          1465:   void *tmp;
        !          1466:   if (sk)
        !          1467:     {
        !          1468:        if (sk->wmem_alloc + size >= SK_WMEM_MAX && !force)
        !          1469:         {
        !          1470:            MPRINTK ("sock_wmalloc(%X,%d,%d) returning NULL\n",
        !          1471:                     sk, size, force);
        !          1472:            return (NULL);
        !          1473:         }
        !          1474:       cli();
        !          1475:       sk->wmem_alloc+= size;
        !          1476:       sti();
        !          1477:     }
        !          1478:    if (sk)
        !          1479:      tmp = smalloc (size);
        !          1480:    else
        !          1481:      tmp = malloc (size);
        !          1482: 
        !          1483:   MPRINTK ("sock_wmalloc(%X,%d,%d) returning %X\n",sk, size, force, tmp);
        !          1484:   return (tmp);
        !          1485: }
        !          1486: 
        !          1487: void *
        !          1488: sock_rmalloc(volatile struct sock *sk, unsigned long size, int force)
        !          1489: {
        !          1490:    struct mem *tmp;
        !          1491:    if (sk )
        !          1492:      {
        !          1493:        if (sk->rmem_alloc + size >= SK_RMEM_MAX && !force)
        !          1494:          {
        !          1495:             MPRINTK ("sock_rmalloc(%X,%d,%d) returning NULL\n",sk,size,force);
        !          1496:             return (NULL);
        !          1497:          }
        !          1498:        cli();
        !          1499:        sk->rmem_alloc+= size;
        !          1500:        sti();
        !          1501:      }
        !          1502:    if (sk)
        !          1503:      tmp = smalloc (size);
        !          1504:    else
        !          1505:      tmp = malloc (size);
        !          1506: 
        !          1507:    MPRINTK ("sock_rmalloc(%X,%d,%d) returning %X\n",sk, size, force, tmp);
        !          1508:    return (tmp);
        !          1509: }
        !          1510: 
        !          1511: 
        !          1512: unsigned long
        !          1513: sock_rspace (volatile struct sock *sk)
        !          1514: {
        !          1515:    int amt;
        !          1516:    if (sk != NULL)
        !          1517:      {
        !          1518:        if (sk->rmem_alloc >= SK_RMEM_MAX-2*MIN_WINDOW) return (0);
        !          1519:        amt = min ((SK_RMEM_MAX-sk->rmem_alloc)/2-MIN_WINDOW, MAX_WINDOW);
        !          1520:        if (amt < 0) return (0);
        !          1521:        return (amt);
        !          1522:      }
        !          1523:    return (0);
        !          1524: }
        !          1525: 
        !          1526: unsigned long
        !          1527: sock_wspace (volatile struct sock *sk)
        !          1528: {
        !          1529:   if (sk != NULL)
        !          1530:     {
        !          1531:        if (sk->shutdown & SEND_SHUTDOWN) return (0);
        !          1532:        if (sk->wmem_alloc >= SK_WMEM_MAX) return (0);
        !          1533:        return (SK_WMEM_MAX-sk->wmem_alloc );
        !          1534:     }
        !          1535:   return (0);
        !          1536: }
        !          1537: 
        !          1538: 
        !          1539: void
        !          1540: sock_wfree (volatile struct sock *sk, void *mem, unsigned long size)
        !          1541: {
        !          1542:    MPRINTK ("sock_wfree (sk=%X, mem=%X, size=%d)\n",sk, mem, size);
        !          1543:    if (sk)
        !          1544:      {
        !          1545:        sk->wmem_alloc -= size;
        !          1546:        sfree(mem,size);
        !          1547:        /* in case it might be waiting for more memory. */
        !          1548:        if (!sk->dead && sk->wmem_alloc > SK_WMEM_MAX/2) wake_up(sk->sleep);
        !          1549:        if (sk->destroy && sk->wmem_alloc == 0 && sk->rmem_alloc == 0)
        !          1550:          {
        !          1551:             MPRINTK ("recovered lost memory, destroying sock = %X\n",sk);
        !          1552:             delete_timer ((struct timer *)&sk->time_wait);
        !          1553:             free_s ((void *)sk, sizeof (*sk));
        !          1554:          }
        !          1555:      }
        !          1556:    else
        !          1557:      {
        !          1558:        free_s (mem, size);
        !          1559:      }
        !          1560: }
        !          1561: 
        !          1562: void
        !          1563: sock_rfree (volatile struct sock *sk, void *mem, unsigned long size)
        !          1564: {
        !          1565:    MPRINTK ("sock_rfree (sk=%X, mem=%X, size=%d)\n",sk, mem, size);
        !          1566:    if (sk)
        !          1567:      {
        !          1568:        sk->rmem_alloc -= size;
        !          1569:        sfree(mem,size);
        !          1570:        if (sk->destroy && sk->wmem_alloc == 0 && sk->rmem_alloc == 0)
        !          1571:          {
        !          1572:             delete_timer ((struct timer *)&sk->time_wait);
        !          1573:             free_s ((void *)sk, sizeof (*sk));
        !          1574:          }
        !          1575:      }
        !          1576:    else
        !          1577:      {
        !          1578:        free_s (mem, size);
        !          1579:      }
        !          1580: }
        !          1581: 
        !          1582: 
        !          1583: /* This routine must find a socket given a tcp header.  Everyhting
        !          1584:    is assumed to be in net order. */
        !          1585: 
        !          1586: volatile struct sock *get_sock (struct proto *prot, unsigned short num,
        !          1587:                                unsigned long raddr,
        !          1588:                                unsigned short rnum, unsigned long laddr)
        !          1589: {
        !          1590:   volatile struct sock *s;
        !          1591:   PRINTK ("get_sock (prot=%X, num=%d, raddr=%X, rnum=%d, laddr=%X)\n",
        !          1592:          prot, num, raddr, rnum, laddr);
        !          1593: 
        !          1594:   /* SOCK_ARRAY_SIZE must be a power of two.  This will work better
        !          1595:      than a prime unless 3 or more sockets end up using the same
        !          1596:      array entry.  This should not be a problem because most
        !          1597:      well known sockets don't overlap that much, and for
        !          1598:      the other ones, we can just be careful about picking our
        !          1599:      socket number when we choose an arbitrary one. */
        !          1600: 
        !          1601:   for (s=prot->sock_array[num&(SOCK_ARRAY_SIZE-1)]; s != NULL; s=s->next)
        !          1602:     {
        !          1603:       if (s->num == num)
        !          1604:        {
        !          1605:          /* we need to see if this is the socket that we want. */
        !          1606:          if (!ip_addr_match (s->daddr, raddr))
        !          1607:            continue;
        !          1608:          if (s->dummy_th.dest != rnum && s->dummy_th.dest != 0)
        !          1609:            continue;
        !          1610:          if (!ip_addr_match (s->saddr, laddr))
        !          1611:            continue;
        !          1612:          return (s);
        !          1613:        }
        !          1614:     }
        !          1615:   return (NULL);
        !          1616: }
        !          1617: 
        !          1618: void release_sock (volatile struct sock *sk)
        !          1619: {
        !          1620:   if (sk->blog) return;
        !          1621:   /* see if we have any packets built up. */
        !          1622: 
        !          1623:   cli();
        !          1624:   sk->inuse = 1;
        !          1625:   while (sk->back_log != NULL)
        !          1626:     {
        !          1627:       struct sk_buff *skb;
        !          1628:       sk->blog = 1;
        !          1629:       skb = sk->back_log;
        !          1630:       PRINTK ("release_sock: skb = %X:\n",skb);
        !          1631:       print_skb(skb);
        !          1632:       if (skb->next != skb)
        !          1633:        {
        !          1634:          sk->back_log = skb->next;
        !          1635:          skb->prev->next = skb->next;
        !          1636:          skb->next->prev = skb->prev;
        !          1637:        }
        !          1638:       else
        !          1639:        {
        !          1640:          sk->back_log = NULL;
        !          1641:        }
        !          1642:       sti();
        !          1643:       PRINTK ("sk->back_log = %X\n",sk->back_log);
        !          1644:       if (sk->prot->rcv)
        !          1645:        sk->prot->rcv(skb, skb->dev, sk->opt,
        !          1646:                      skb->saddr, skb->len, skb->daddr, 1,
        !          1647:                      /* only used for/by raw sockets. */
        !          1648:                      (struct ip_protocol *)sk->pair); 
        !          1649:       cli();
        !          1650:     }
        !          1651:   sk->blog = 0;
        !          1652:   sk->inuse = 0;
        !          1653:   sti();
        !          1654:   if (sk->dead && sk->state == TCP_CLOSE)
        !          1655:     {
        !          1656:         /* should be about 2 rtt's */
        !          1657:        sk->time_wait.len = min (sk->rtt * 2, TCP_DONE_TIME);
        !          1658:        sk->timeout = TIME_DONE;
        !          1659:        reset_timer ((struct timer *)&sk->time_wait);
        !          1660:     }
        !          1661: }

unix.superglobalmegacorp.com

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