root/net/socket/sock.c

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

DEFINITIONS

This source file includes following definitions.
  1. min
  2. print_sk
  3. print_skb
  4. sock_setsockopt
  5. sock_getsockopt
  6. sock_wmalloc
  7. sock_rmalloc
  8. sock_rspace
  9. sock_wspace
  10. sock_wfree
  11. sock_rfree

   1 /*
   2  *      NET2Debugged, generic socket properties.
   3  *
   4  *      This module provides the generic option control and memory handling
   5  *      for a socket of any kind.
   6  *
   7  * Version:     @(#)sock.c      1.28    26/12/93
   8  *
   9  * Authors:     Alan Cox <iiitac@pyr.swan.ac.uk>
  10  *
  11  */
  12  
  13 #include <linux/config.h>
  14 #include <linux/errno.h>
  15 #include <linux/types.h>
  16 #include <linux/socket.h>
  17 #include <linux/in.h>
  18 #include <linux/kernel.h>
  19 #include <linux/major.h>
  20 #include <linux/sched.h>
  21 #include <linux/timer.h>
  22 #include <linux/string.h>
  23 #include <linux/sockios.h>
  24 #include <linux/net.h>
  25 #include <linux/fcntl.h>
  26 #include <linux/mm.h>
  27 #include <linux/interrupt.h>
  28 
  29 #include <asm/segment.h>
  30 #include <asm/system.h>
  31 
  32 #include "inet.h"
  33 #include "dev.h"
  34 #include "ip.h"
  35 #include "protocol.h"
  36 #include "arp.h"
  37 #include "route.h"
  38 #include "tcp.h"
  39 #include "udp.h"
  40 #include "skbuff.h"
  41 #include "sock.h"
  42 #include "raw.h"
  43 #include "icmp.h"
  44 
  45 static __inline__ int 
  46 min(unsigned int a, unsigned int b)
     /* [previous][next][first][last][top][bottom][index][help] */
  47 {
  48         if (a < b) 
  49                 return(a);
  50         return(b);
  51 }
  52 
  53 #ifdef SOCK_DEBUG
  54 
  55 void print_sk(struct sock *sk)
     /* [previous][next][first][last][top][bottom][index][help] */
  56 {
  57         if (!sk) 
  58         {
  59                 printk("  print_sk(NULL)\n");
  60                 return;
  61         }
  62         printk("  wmem_alloc = %lu\n", sk->wmem_alloc);
  63         printk("  rmem_alloc = %lu\n", sk->rmem_alloc);
  64         printk("  send_head = %p\n", sk->send_head);
  65         printk("  state = %d\n",sk->state);
  66         printk("  wback = %p, rqueue = %p\n", sk->wback, sk->rqueue);
  67         printk("  wfront = %p\n", sk->wfront);
  68         printk("  daddr = %lX, saddr = %lX\n", sk->daddr,sk->saddr);
  69         printk("  num = %d", sk->num);
  70         printk(" next = %p\n", sk->next);
  71         printk("  send_seq = %ld, acked_seq = %ld, copied_seq = %ld\n",
  72                   sk->send_seq, sk->acked_seq, sk->copied_seq);
  73         printk("  rcv_ack_seq = %ld, window_seq = %ld, fin_seq = %ld\n",
  74                   sk->rcv_ack_seq, sk->window_seq, sk->fin_seq);
  75         printk("  prot = %p\n", sk->prot);
  76         printk("  pair = %p, back_log = %p\n", sk->pair,sk->back_log);
  77         printk("  inuse = %d , blog = %d\n", sk->inuse, sk->blog);
  78         printk("  dead = %d delay_acks=%d\n", sk->dead, sk->delay_acks);
  79         printk("  retransmits = %ld, timeout = %d\n", sk->retransmits, sk->timeout);
  80         printk("  cong_window = %d, packets_out = %d\n", sk->cong_window,
  81                   sk->packets_out);
  82         printk("  urg = %d shutdown=%d\n", sk->urg, sk->shutdown);
  83 }
  84 
  85 
  86 void print_skb(struct sk_buff *skb)
     /* [previous][next][first][last][top][bottom][index][help] */
  87 {
  88         if (!skb) 
  89         {
  90                 printk("  print_skb(NULL)\n");
  91                 return;
  92         }
  93         printk("  prev = %p, next = %p\n", skb->prev, skb->next);
  94         printk("  sk = %p link3 = %p\n", skb->sk, skb->link3);
  95         printk("  mem_addr = %p, mem_len = %lu\n", skb->mem_addr, skb->mem_len);
  96         printk("  used = %d free = %d\n", skb->used,skb->free);
  97 }
  98 
  99 
 100 #endif
 101 
 102 /*
 103  *      This is meant for all protocols to use and covers goings on
 104  *      at the socket level. Everything here is generic.
 105  */
 106 
 107 int sock_setsockopt(struct sock *sk, int level, int optname,
     /* [previous][next][first][last][top][bottom][index][help] */
 108                 char *optval, int optlen)
 109 {
 110         int val;
 111         int err;
 112         struct linger ling;
 113 
 114         if (optval == NULL) 
 115                 return(-EINVAL);
 116 
 117         err=verify_area(VERIFY_READ, optval, sizeof(int));
 118         if(err)
 119                 return err;
 120         
 121         val = get_fs_long((unsigned long *)optval);
 122         switch(optname) 
 123         {
 124                 case SO_TYPE:
 125                 case SO_ERROR:
 126                         return(-ENOPROTOOPT);
 127 
 128                 case SO_DEBUG:  
 129                         sk->debug=val?1:0;
 130                 case SO_DONTROUTE:      /* Still to be implemented */
 131                         return(0);
 132                 case SO_BROADCAST:
 133                         sk->broadcast=val?1:0;
 134                         return 0;
 135                 case SO_SNDBUF:
 136                         if(val>32767)
 137                                 val=32767;
 138                         if(val<256)
 139                                 val=256;
 140                         sk->sndbuf=val;
 141                         return 0;
 142                 case SO_LINGER:
 143                         err=verify_area(VERIFY_READ,optval,sizeof(ling));
 144                         if(err)
 145                                 return err;
 146                         memcpy_fromfs(&ling,optval,sizeof(ling));
 147                         if(ling.l_onoff==0)
 148                                 sk->linger=0;
 149                         else
 150                         {
 151                                 sk->lingertime=ling.l_linger;
 152                                 sk->linger=1;
 153                         }
 154                         return 0;
 155                 case SO_RCVBUF:
 156                         if(val>32767)
 157                                 val=32767;
 158                         if(val<256)
 159                                 val=256;
 160                         sk->rcvbuf=val;
 161                         return(0);
 162 
 163                 case SO_REUSEADDR:
 164                         if (val) 
 165                                 sk->reuse = 1;
 166                         else 
 167                                 sk->reuse = 0;
 168                         return(0);
 169 
 170                 case SO_KEEPALIVE:
 171                         if (val)
 172                                 sk->keepopen = 1;
 173                         else 
 174                                 sk->keepopen = 0;
 175                         return(0);
 176 
 177                 case SO_OOBINLINE:
 178                         if (val) 
 179                                 sk->urginline = 1;
 180                         else 
 181                                 sk->urginline = 0;
 182                         return(0);
 183 
 184                 case SO_NO_CHECK:
 185                         if (val) 
 186                                 sk->no_check = 1;
 187                         else 
 188                                 sk->no_check = 0;
 189                         return(0);
 190 
 191                  case SO_PRIORITY:
 192                         if (val >= 0 && val < DEV_NUMBUFFS) 
 193                         {
 194                                 sk->priority = val;
 195                         } 
 196                         else 
 197                         {
 198                                 return(-EINVAL);
 199                         }
 200                         return(0);
 201 
 202                 default:
 203                         return(-ENOPROTOOPT);
 204         }
 205 }
 206 
 207 
 208 int sock_getsockopt(struct sock *sk, int level, int optname,
     /* [previous][next][first][last][top][bottom][index][help] */
 209                    char *optval, int *optlen)
 210 {               
 211         int val;
 212         int err;
 213         struct linger ling;
 214 
 215         switch(optname) 
 216         {
 217                 case SO_DEBUG:          
 218                         val = sk->debug;
 219                         break;
 220                 
 221                 case SO_DONTROUTE:      /* One last option to implement */
 222                         val = 0;
 223                         break;
 224                 
 225                 case SO_BROADCAST:
 226                         val= sk->broadcast;
 227                         break;
 228                 
 229                 case SO_LINGER: 
 230                         err=verify_area(VERIFY_WRITE,optval,sizeof(ling));
 231                         if(err)
 232                                 return err;
 233                         err=verify_area(VERIFY_WRITE,optlen,sizeof(int));
 234                         if(err)
 235                                 return err;
 236                         put_fs_long(sizeof(ling),(unsigned long *)optlen);
 237                         ling.l_onoff=sk->linger;
 238                         ling.l_linger=sk->lingertime;
 239                         memcpy_tofs(optval,&ling,sizeof(ling));
 240                         return 0;
 241                 
 242                 case SO_SNDBUF:
 243                         val=sk->sndbuf;
 244                         break;
 245                 
 246                 case SO_RCVBUF:
 247                         val =sk->rcvbuf;
 248                         break;
 249 
 250                 case SO_REUSEADDR:
 251                         val = sk->reuse;
 252                         break;
 253 
 254                 case SO_KEEPALIVE:
 255                         val = sk->keepopen;
 256                         break;
 257 
 258                 case SO_TYPE:
 259                         if (sk->prot == &tcp_prot) 
 260                                 val = SOCK_STREAM;
 261                         else 
 262                                 val = SOCK_DGRAM;
 263                         break;
 264 
 265                 case SO_ERROR:
 266                         val = sk->err;
 267                         sk->err = 0;
 268                         break;
 269 
 270                 case SO_OOBINLINE:
 271                         val = sk->urginline;
 272                         break;
 273         
 274                 case SO_NO_CHECK:
 275                         val = sk->no_check;
 276                         break;
 277 
 278                 case SO_PRIORITY:
 279                         val = sk->priority;
 280                         break;
 281 
 282                 default:
 283                         return(-ENOPROTOOPT);
 284         }
 285         err=verify_area(VERIFY_WRITE, optlen, sizeof(int));
 286         if(err)
 287                 return err;
 288         put_fs_long(sizeof(int),(unsigned long *) optlen);
 289 
 290         err=verify_area(VERIFY_WRITE, optval, sizeof(int));
 291         if(err)
 292                 return err;
 293         put_fs_long(val,(unsigned long *)optval);
 294 
 295         return(0);
 296 }
 297 
 298 
 299 void *sock_wmalloc(struct sock *sk, unsigned long size, int force,
     /* [previous][next][first][last][top][bottom][index][help] */
 300              int priority)
 301 {
 302         if (sk) 
 303         {
 304                 if (sk->wmem_alloc + size < sk->sndbuf || force) 
 305                 {
 306                         cli();
 307                         sk->wmem_alloc+= size;
 308                         sti();
 309                         return(alloc_skb(size, priority));
 310                 }
 311                 DPRINTF((DBG_INET, "sock_wmalloc(%X,%d,%d,%d) returning NULL\n",
 312                                                 sk, size, force, priority));
 313                 return(NULL);
 314         }
 315         return(alloc_skb(size, priority));
 316 }
 317 
 318 
 319 void *sock_rmalloc(struct sock *sk, unsigned long size, int force, int priority)
     /* [previous][next][first][last][top][bottom][index][help] */
 320 {
 321         if (sk) 
 322         {
 323                 if (sk->rmem_alloc + size < sk->rcvbuf || force) 
 324                 {
 325                         void *c = alloc_skb(size, priority);
 326                         cli();
 327                         if (c) 
 328                                 sk->rmem_alloc += size;
 329                         sti();
 330                         return(c);
 331                 }
 332                 DPRINTF((DBG_INET, "sock_rmalloc(%X,%d,%d,%d) returning NULL\n",
 333                                                 sk,size,force, priority));
 334                 return(NULL);
 335           }
 336           return(alloc_skb(size, priority));
 337 }
 338 
 339 
 340 unsigned long sock_rspace(struct sock *sk)
     /* [previous][next][first][last][top][bottom][index][help] */
 341 {
 342         int amt;
 343 
 344         if (sk != NULL) 
 345         {
 346                 if (sk->rmem_alloc >= sk->rcvbuf-2*MIN_WINDOW) 
 347                         return(0);
 348                 amt = min((sk->rcvbuf-sk->rmem_alloc)/2-MIN_WINDOW, MAX_WINDOW);
 349                 if (amt < 0) 
 350                         return(0);
 351                 return(amt);
 352         }
 353         return(0);
 354 }
 355 
 356 
 357 unsigned long sock_wspace(struct sock *sk)
     /* [previous][next][first][last][top][bottom][index][help] */
 358 {
 359         if (sk != NULL) 
 360         {
 361                 if (sk->shutdown & SEND_SHUTDOWN) 
 362                         return(0);
 363                 if (sk->wmem_alloc >= sk->sndbuf)
 364                         return(0);
 365                 return(sk->sndbuf-sk->wmem_alloc );
 366         }
 367         return(0);
 368 }
 369 
 370 
 371 void sock_wfree(struct sock *sk, void *mem, unsigned long size)
     /* [previous][next][first][last][top][bottom][index][help] */
 372 {
 373         struct sk_buff *skb;
 374         DPRINTF((DBG_INET, "sock_wfree(sk=%X, mem=%X, size=%d)\n", sk, mem, size));
 375 
 376         IS_SKB(mem);
 377         
 378         skb=mem;
 379         
 380         kfree_skbmem(mem, size);
 381         if (sk) 
 382         {
 383                 sk->wmem_alloc -= size;
 384 
 385                 /* In case it might be waiting for more memory. */
 386                 if (!sk->dead) 
 387                         sk->write_space(sk);
 388                 if (sk->destroy && sk->wmem_alloc == 0 && sk->rmem_alloc == 0) 
 389                 {
 390                         DPRINTF((DBG_INET,
 391                                 "recovered lost memory, sock = %X\n", sk));
 392                 }
 393                 return;
 394         }
 395 }
 396 
 397 
 398 void sock_rfree(struct sock *sk, void *mem, unsigned long size)
     /* [previous][next][first][last][top][bottom][index][help] */
 399 {
 400         struct sk_buff *skb;
 401         
 402         DPRINTF((DBG_INET, "sock_rfree(sk=%X, mem=%X, size=%d)\n", sk, mem, size));
 403 
 404         IS_SKB(mem);
 405         skb=mem;
 406         
 407         kfree_skbmem(mem, size);
 408         
 409         if (sk) 
 410         {
 411                 sk->rmem_alloc -= size;
 412                 if (sk->destroy && sk->wmem_alloc == 0 && sk->rmem_alloc == 0) 
 413                 {
 414                         DPRINTF((DBG_INET,"recovered lot memory, sock = %X\n", sk));
 415                 }
 416         }
 417 }
 418 

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