home *** CD-ROM | disk | FTP | other *** search
/ Il CD di internet / CD.iso / SOURCE / KERNEL-S / V1.2 / LINUX-1.2 / LINUX-1 / linux / net / inet / sock.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-02-02  |  11.9 KB  |  575 lines

  1. /*
  2.  * INET        An implementation of the TCP/IP protocol suite for the LINUX
  3.  *        operating system.  INET is implemented using the  BSD Socket
  4.  *        interface as the means of communication with the user level.
  5.  *
  6.  *        Generic socket support routines. Memory allocators, sk->inuse/release
  7.  *        handler for protocols to use and generic option handler.
  8.  *
  9.  *
  10.  * Version:    @(#)sock.c    1.0.17    06/02/93
  11.  *
  12.  * Authors:    Ross Biro, <bir7@leland.Stanford.Edu>
  13.  *        Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
  14.  *        Florian La Roche, <flla@stud.uni-sb.de>
  15.  *        Alan Cox, <A.Cox@swansea.ac.uk>
  16.  *
  17.  * Fixes:
  18.  *        Alan Cox    :     Numerous verify_area() problems
  19.  *        Alan Cox    :    Connecting on a connecting socket
  20.  *                    now returns an error for tcp.
  21.  *        Alan Cox    :    sock->protocol is set correctly.
  22.  *                    and is not sometimes left as 0.
  23.  *        Alan Cox    :    connect handles icmp errors on a
  24.  *                    connect properly. Unfortunately there
  25.  *                    is a restart syscall nasty there. I
  26.  *                    can't match BSD without hacking the C
  27.  *                    library. Ideas urgently sought!
  28.  *        Alan Cox    :    Disallow bind() to addresses that are
  29.  *                    not ours - especially broadcast ones!!
  30.  *        Alan Cox    :    Socket 1024 _IS_ ok for users. (fencepost)
  31.  *        Alan Cox    :    sock_wfree/sock_rfree don't destroy sockets,
  32.  *                    instead they leave that for the DESTROY timer.
  33.  *        Alan Cox    :    Clean up error flag in accept
  34.  *        Alan Cox    :    TCP ack handling is buggy, the DESTROY timer
  35.  *                    was buggy. Put a remove_sock() in the handler
  36.  *                    for memory when we hit 0. Also altered the timer
  37.  *                    code. The ACK stuff can wait and needs major 
  38.  *                    TCP layer surgery.
  39.  *        Alan Cox    :    Fixed TCP ack bug, removed remove sock
  40.  *                    and fixed timer/inet_bh race.
  41.  *        Alan Cox    :    Added zapped flag for TCP
  42.  *        Alan Cox    :    Move kfree_skb into skbuff.c and tidied up surplus code
  43.  *        Alan Cox    :    for new sk_buff allocations wmalloc/rmalloc now call alloc_skb
  44.  *        Alan Cox    :    kfree_s calls now are kfree_skbmem so we can track skb resources
  45.  *        Alan Cox    :    Supports socket option broadcast now as does udp. Packet and raw need fixing.
  46.  *        Alan Cox    :    Added RCVBUF,SNDBUF size setting. It suddenly occurred to me how easy it was so...
  47.  *        Rick Sladkey    :    Relaxed UDP rules for matching packets.
  48.  *        C.E.Hawkins    :    IFF_PROMISC/SIOCGHWADDR support
  49.  *    Pauline Middelink    :    identd support
  50.  *        Alan Cox    :    Fixed connect() taking signals I think.
  51.  *        Alan Cox    :    SO_LINGER supported
  52.  *        Alan Cox    :    Error reporting fixes
  53.  *        Anonymous    :    inet_create tidied up (sk->reuse setting)
  54.  *        Alan Cox    :    inet sockets don't set sk->type!
  55.  *        Alan Cox    :    Split socket option code
  56.  *        Alan Cox    :    Callbacks
  57.  *        Alan Cox    :    Nagle flag for Charles & Johannes stuff
  58.  *        Alex        :    Removed restriction on inet fioctl
  59.  *        Alan Cox    :    Splitting INET from NET core
  60.  *        Alan Cox    :    Fixed bogus SO_TYPE handling in getsockopt()
  61.  *        Adam Caldwell    :    Missing return in SO_DONTROUTE/SO_DEBUG code
  62.  *        Alan Cox    :    Split IP from generic code
  63.  *        Alan Cox    :    New kfree_skbmem()
  64.  *        Alan Cox    :    Make SO_DEBUG superuser only.
  65.  *        Alan Cox    :    Allow anyone to clear SO_DEBUG
  66.  *                    (compatibility fix)
  67.  *
  68.  * To Fix:
  69.  *
  70.  *
  71.  *        This program is free software; you can redistribute it and/or
  72.  *        modify it under the terms of the GNU General Public License
  73.  *        as published by the Free Software Foundation; either version
  74.  *        2 of the License, or (at your option) any later version.
  75.  */
  76.  
  77. #include <linux/config.h>
  78. #include <linux/errno.h>
  79. #include <linux/types.h>
  80. #include <linux/socket.h>
  81. #include <linux/in.h>
  82. #include <linux/kernel.h>
  83. #include <linux/major.h>
  84. #include <linux/sched.h>
  85. #include <linux/timer.h>
  86. #include <linux/string.h>
  87. #include <linux/sockios.h>
  88. #include <linux/net.h>
  89. #include <linux/fcntl.h>
  90. #include <linux/mm.h>
  91. #include <linux/interrupt.h>
  92.  
  93. #include <asm/segment.h>
  94. #include <asm/system.h>
  95.  
  96. #include <linux/inet.h>
  97. #include <linux/netdevice.h>
  98. #include "ip.h"
  99. #include "protocol.h"
  100. #include "arp.h"
  101. #include "rarp.h"
  102. #include "route.h"
  103. #include "tcp.h"
  104. #include "udp.h"
  105. #include <linux/skbuff.h>
  106. #include "sock.h"
  107. #include "raw.h"
  108. #include "icmp.h"
  109.  
  110. #define min(a,b)    ((a)<(b)?(a):(b))
  111.  
  112. /*
  113.  *    This is meant for all protocols to use and covers goings on
  114.  *    at the socket level. Everything here is generic.
  115.  */
  116.  
  117. int sock_setsockopt(struct sock *sk, int level, int optname,
  118.         char *optval, int optlen)
  119. {
  120.     int val;
  121.     int err;
  122.     struct linger ling;
  123.  
  124.       if (optval == NULL) 
  125.           return(-EINVAL);
  126.  
  127.       err=verify_area(VERIFY_READ, optval, sizeof(int));
  128.       if(err)
  129.           return err;
  130.       
  131.       val = get_fs_long((unsigned long *)optval);
  132.       switch(optname) 
  133.       {
  134.         case SO_TYPE:
  135.         case SO_ERROR:
  136.               return(-ENOPROTOOPT);
  137.  
  138.         case SO_DEBUG:    
  139.             if(val && !suser())
  140.                 return(-EPERM);
  141.             sk->debug=val?1:0;
  142.             return 0;
  143.         case SO_DONTROUTE:
  144.             sk->localroute=val?1:0;
  145.             return 0;
  146.         case SO_BROADCAST:
  147.             sk->broadcast=val?1:0;
  148.             return 0;
  149.         case SO_SNDBUF:
  150.             if(val>32767)
  151.                 val=32767;
  152.             if(val<256)
  153.                 val=256;
  154.             sk->sndbuf=val;
  155.             return 0;
  156.         case SO_LINGER:
  157.             err=verify_area(VERIFY_READ,optval,sizeof(ling));
  158.             if(err)
  159.                 return err;
  160.             memcpy_fromfs(&ling,optval,sizeof(ling));
  161.             if(ling.l_onoff==0)
  162.                 sk->linger=0;
  163.             else
  164.             {
  165.                 sk->lingertime=ling.l_linger;
  166.                 sk->linger=1;
  167.             }
  168.             return 0;
  169.         case SO_RCVBUF:
  170.             if(val>32767)
  171.                 val=32767;
  172.             if(val<256)
  173.                 val=256;
  174.             sk->rcvbuf=val;
  175.             return(0);
  176.  
  177.         case SO_REUSEADDR:
  178.             if (val) 
  179.                 sk->reuse = 1;
  180.             else 
  181.                 sk->reuse = 0;
  182.             return(0);
  183.  
  184.         case SO_KEEPALIVE:
  185.             if (val)
  186.                 sk->keepopen = 1;
  187.             else 
  188.                 sk->keepopen = 0;
  189.             return(0);
  190.  
  191.          case SO_OOBINLINE:
  192.             if (val) 
  193.                 sk->urginline = 1;
  194.             else 
  195.                 sk->urginline = 0;
  196.             return(0);
  197.  
  198.          case SO_NO_CHECK:
  199.             if (val) 
  200.                 sk->no_check = 1;
  201.             else 
  202.                 sk->no_check = 0;
  203.             return(0);
  204.  
  205.          case SO_PRIORITY:
  206.             if (val >= 0 && val < DEV_NUMBUFFS) 
  207.             {
  208.                 sk->priority = val;
  209.             } 
  210.             else 
  211.             {
  212.                 return(-EINVAL);
  213.             }
  214.             return(0);
  215.  
  216.         default:
  217.               return(-ENOPROTOOPT);
  218.       }
  219. }
  220.  
  221.  
  222. int sock_getsockopt(struct sock *sk, int level, int optname,
  223.            char *optval, int *optlen)
  224. {        
  225.       int val;
  226.       int err;
  227.       struct linger ling;
  228.  
  229.       switch(optname) 
  230.       {
  231.         case SO_DEBUG:        
  232.             val = sk->debug;
  233.             break;
  234.         
  235.         case SO_DONTROUTE:
  236.             val = sk->localroute;
  237.             break;
  238.         
  239.         case SO_BROADCAST:
  240.             val= sk->broadcast;
  241.             break;
  242.         
  243.         case SO_LINGER:    
  244.             err=verify_area(VERIFY_WRITE,optval,sizeof(ling));
  245.             if(err)
  246.                 return err;
  247.             err=verify_area(VERIFY_WRITE,optlen,sizeof(int));
  248.             if(err)
  249.                 return err;
  250.             put_fs_long(sizeof(ling),(unsigned long *)optlen);
  251.             ling.l_onoff=sk->linger;
  252.             ling.l_linger=sk->lingertime;
  253.             memcpy_tofs(optval,&ling,sizeof(ling));
  254.             return 0;
  255.         
  256.         case SO_SNDBUF:
  257.             val=sk->sndbuf;
  258.             break;
  259.         
  260.         case SO_RCVBUF:
  261.             val =sk->rcvbuf;
  262.             break;
  263.  
  264.         case SO_REUSEADDR:
  265.             val = sk->reuse;
  266.             break;
  267.  
  268.         case SO_KEEPALIVE:
  269.             val = sk->keepopen;
  270.             break;
  271.  
  272.         case SO_TYPE:
  273. #if 0        
  274.             if (sk->prot == &tcp_prot) 
  275.                 val = SOCK_STREAM;
  276.               else 
  277.                   val = SOCK_DGRAM;
  278. #endif
  279.             val = sk->type;                  
  280.             break;
  281.  
  282.         case SO_ERROR:
  283.             val = sk->err;
  284.             sk->err = 0;
  285.             break;
  286.  
  287.         case SO_OOBINLINE:
  288.             val = sk->urginline;
  289.             break;
  290.     
  291.         case SO_NO_CHECK:
  292.             val = sk->no_check;
  293.             break;
  294.  
  295.         case SO_PRIORITY:
  296.             val = sk->priority;
  297.             break;
  298.  
  299.         default:
  300.             return(-ENOPROTOOPT);
  301.     }
  302.     err=verify_area(VERIFY_WRITE, optlen, sizeof(int));
  303.     if(err)
  304.           return err;
  305.       put_fs_long(sizeof(int),(unsigned long *) optlen);
  306.  
  307.       err=verify_area(VERIFY_WRITE, optval, sizeof(int));
  308.       if(err)
  309.           return err;
  310.       put_fs_long(val,(unsigned long *)optval);
  311.  
  312.       return(0);
  313. }
  314.  
  315.  
  316. struct sk_buff *sock_wmalloc(struct sock *sk, unsigned long size, int force, int priority)
  317. {
  318.     if (sk) 
  319.     {
  320.         if (sk->wmem_alloc + size < sk->sndbuf || force) 
  321.         {
  322.             struct sk_buff * c = alloc_skb(size, priority);
  323.             if (c) 
  324.             {
  325.                 unsigned long flags;
  326.                 save_flags(flags);
  327.                 cli();
  328.                 sk->wmem_alloc+= c->mem_len;
  329.                 restore_flags(flags); /* was sti(); */
  330.             }
  331.             return c;
  332.         }
  333.         return(NULL);
  334.     }
  335.     return(alloc_skb(size, priority));
  336. }
  337.  
  338.  
  339. struct sk_buff *sock_rmalloc(struct sock *sk, unsigned long size, int force, int priority)
  340. {
  341.     if (sk) 
  342.     {
  343.         if (sk->rmem_alloc + size < sk->rcvbuf || force) 
  344.         {
  345.             struct sk_buff *c = alloc_skb(size, priority);
  346.             if (c) 
  347.             {
  348.                 unsigned long flags;
  349.                 save_flags(flags);
  350.                 cli();
  351.                 sk->rmem_alloc += c->mem_len;
  352.                 restore_flags(flags); /* was sti(); */
  353.             }
  354.             return(c);
  355.         }
  356.         return(NULL);
  357.     }
  358.     return(alloc_skb(size, priority));
  359. }
  360.  
  361.  
  362. unsigned long sock_rspace(struct sock *sk)
  363. {
  364.     int amt;
  365.  
  366.     if (sk != NULL) 
  367.     {
  368.         if (sk->rmem_alloc >= sk->rcvbuf-2*MIN_WINDOW) 
  369.             return(0);
  370.         amt = min((sk->rcvbuf-sk->rmem_alloc)/2-MIN_WINDOW, MAX_WINDOW);
  371.         if (amt < 0) 
  372.             return(0);
  373.         return(amt);
  374.     }
  375.     return(0);
  376. }
  377.  
  378.  
  379. unsigned long sock_wspace(struct sock *sk)
  380. {
  381.     if (sk != NULL) 
  382.     {
  383.         if (sk->shutdown & SEND_SHUTDOWN)
  384.             return(0);
  385.         if (sk->wmem_alloc >= sk->sndbuf)
  386.             return(0);
  387.         return(sk->sndbuf-sk->wmem_alloc );
  388.     }
  389.     return(0);
  390. }
  391.  
  392.  
  393. void sock_wfree(struct sock *sk, struct sk_buff *skb, unsigned long size)
  394. {
  395. #ifdef CONFIG_SKB_CHECK
  396.     IS_SKB(skb);
  397. #endif
  398.     kfree_skbmem(skb, size);
  399.     if (sk) 
  400.     {
  401.         unsigned long flags;
  402.         save_flags(flags);
  403.         cli();
  404.         sk->wmem_alloc -= size;
  405.         restore_flags(flags);
  406.         /* In case it might be waiting for more memory. */
  407.         if (!sk->dead)
  408.             sk->write_space(sk);
  409.         return;
  410.     }
  411. }
  412.  
  413.  
  414. void sock_rfree(struct sock *sk, struct sk_buff *skb, unsigned long size)
  415. {
  416. #ifdef CONFIG_SKB_CHECK
  417.     IS_SKB(skb);
  418. #endif    
  419.     kfree_skbmem(skb, size);
  420.     if (sk) 
  421.     {
  422.         unsigned long flags;
  423.         save_flags(flags);
  424.         cli();
  425.         sk->rmem_alloc -= size;
  426.         restore_flags(flags);
  427.     }
  428. }
  429.  
  430. /*
  431.  *    Generic send/receive buffer handlers
  432.  */
  433.  
  434. struct sk_buff *sock_alloc_send_skb(struct sock *sk, unsigned long size, int noblock, int *errcode)
  435. {
  436.     struct sk_buff *skb;
  437.     int err;
  438.  
  439.     sk->inuse=1;
  440.         
  441.     do
  442.     {
  443.         if(sk->err!=0)
  444.         {
  445.             cli();
  446.             err= -sk->err;
  447.             sk->err=0;
  448.             sti();
  449.             *errcode=err;
  450.             return NULL;
  451.         }
  452.         
  453.         if(sk->shutdown&SEND_SHUTDOWN)
  454.         {
  455.             *errcode=-EPIPE;
  456.             return NULL;
  457.         }
  458.         
  459.         skb = sock_wmalloc(sk, size, 0, GFP_KERNEL);
  460.         
  461.         if(skb==NULL)
  462.         {
  463.             unsigned long tmp;
  464.  
  465.             sk->socket->flags |= SO_NOSPACE;
  466.             if(noblock)
  467.             {
  468.                 *errcode=-EAGAIN;
  469.                 return NULL;
  470.             }
  471.             if(sk->shutdown&SEND_SHUTDOWN)
  472.             {
  473.                 *errcode=-EPIPE;
  474.                 return NULL;
  475.             }
  476.             tmp = sk->wmem_alloc;
  477.             cli();
  478.             if(sk->shutdown&SEND_SHUTDOWN)
  479.             {
  480.                 sti();
  481.                 *errcode=-EPIPE;
  482.                 return NULL;
  483.             }
  484.             
  485.             if( tmp <= sk->wmem_alloc)
  486.             {
  487.                 sk->socket->flags &= ~SO_NOSPACE;
  488.                 interruptible_sleep_on(sk->sleep);
  489.                 if (current->signal & ~current->blocked) 
  490.                 {
  491.                     sti();
  492.                     *errcode = -ERESTARTSYS;
  493.                     return NULL;
  494.                 }
  495.             }
  496.             sti();
  497.         }
  498.     }
  499.     while(skb==NULL);
  500.         
  501.     return skb;
  502. }
  503.  
  504. /*
  505.  *    Queue a received datagram if it will fit. Stream and sequenced protocols
  506.  *    can't normally use this as they need to fit buffers in and play with them.
  507.  */
  508.  
  509. int sock_queue_rcv_skb(struct sock *sk, struct sk_buff *skb)
  510. {
  511.     unsigned long flags;
  512.     if(sk->rmem_alloc + skb->mem_len >= sk->rcvbuf)
  513.         return -ENOMEM;
  514.     save_flags(flags);
  515.     cli();
  516.     sk->rmem_alloc+=skb->mem_len;
  517.     skb->sk=sk;
  518.     restore_flags(flags);
  519.     skb_queue_tail(&sk->receive_queue,skb);
  520.     if(!sk->dead)
  521.         sk->data_ready(sk,skb->len);
  522.     return 0;
  523. }
  524.  
  525. void release_sock(struct sock *sk)
  526. {
  527.     unsigned long flags;
  528. #ifdef CONFIG_INET
  529.     struct sk_buff *skb;
  530. #endif
  531.  
  532.     if (!sk->prot)
  533.         return;
  534.     /*
  535.      *    Make the backlog atomic. If we don't do this there is a tiny
  536.      *    window where a packet may arrive between the sk->blog being 
  537.      *    tested and then set with sk->inuse still 0 causing an extra 
  538.      *    unwanted re-entry into release_sock().
  539.      */
  540.  
  541.     save_flags(flags);
  542.     cli();
  543.     if (sk->blog) 
  544.     {
  545.         restore_flags(flags);
  546.         return;
  547.     }
  548.     sk->blog=1;
  549.     sk->inuse = 1;
  550.     restore_flags(flags);
  551. #ifdef CONFIG_INET
  552.     /* See if we have any packets built up. */
  553.     while((skb = skb_dequeue(&sk->back_log)) != NULL) 
  554.     {
  555.         sk->blog = 1;
  556.         if (sk->prot->rcv) 
  557.             sk->prot->rcv(skb, skb->dev, sk->opt,
  558.                  skb->saddr, skb->len, skb->daddr, 1,
  559.                 /* Only used for/by raw sockets. */
  560.                 (struct inet_protocol *)sk->pair); 
  561.     }
  562. #endif  
  563.     sk->blog = 0;
  564.     sk->inuse = 0;
  565. #ifdef CONFIG_INET  
  566.     if (sk->dead && sk->state == TCP_CLOSE) 
  567.     {
  568.         /* Should be about 2 rtt's */
  569.         reset_timer(sk, TIME_DONE, min(sk->rtt * 2, TCP_DONE_TIME));
  570.     }
  571. #endif  
  572. }
  573.  
  574.  
  575.