root/net/inet/skbuff.c

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

DEFINITIONS

This source file includes following definitions.
  1. skb_check
  2. skb_queue_head_init
  3. skb_queue_head
  4. skb_queue_tail
  5. skb_dequeue
  6. skb_insert
  7. skb_append
  8. skb_unlink
  9. skb_peek_copy
  10. kfree_skb
  11. alloc_skb
  12. kfree_skbmem
  13. skb_clone
  14. skb_kept_by_device
  15. skb_device_release
  16. skb_device_locked

   1 /*
   2  *      Routines having to do with the 'struct sk_buff' memory handlers.
   3  *
   4  *      Authors:        Alan Cox <iiitac@pyr.swan.ac.uk>
   5  *                      Florian La Roche <rzsfl@rz.uni-sb.de>
   6  *
   7  *      This program is free software; you can redistribute it and/or
   8  *      modify it under the terms of the GNU General Public License
   9  *      as published by the Free Software Foundation; either version
  10  *      2 of the License, or (at your option) any later version.
  11  */
  12  
  13 #include <linux/config.h>
  14 #include <linux/types.h>
  15 #include <linux/kernel.h>
  16 #include <linux/sched.h>
  17 #include <asm/segment.h>
  18 #include <asm/system.h>
  19 #include <linux/mm.h>
  20 #include <linux/interrupt.h>
  21 #include <linux/in.h>
  22 #include <linux/inet.h>
  23 #include <linux/netdevice.h>
  24 #include "ip.h"
  25 #include "protocol.h"
  26 #include <linux/string.h>
  27 #include "route.h"
  28 #include "tcp.h"
  29 #include "udp.h"
  30 #include <linux/skbuff.h>
  31 #include "sock.h"
  32 
  33 
  34 /*
  35  *      Resource tracking variables
  36  */
  37  
  38 volatile unsigned long net_memory = 0;
  39 volatile unsigned long net_skbcount = 0;
  40 
  41 
  42 #if CONFIG_SKB_CHECK
  43 
  44 /*
  45  *      Debugging paranoia. Can go later when this crud stack works
  46  */ 
  47 
  48 int skb_check(struct sk_buff *skb, int head, int line, char *file)
     /* [previous][next][first][last][top][bottom][index][help] */
  49 {
  50         if (head) {
  51                 if (skb->magic_debug_cookie != SK_HEAD_SKB) {
  52                         printk("File: %s Line %d, found a bad skb-head\n",
  53                                 file,line);
  54                         return -1;
  55                 }
  56                 if (!skb->next || !skb->prev) {
  57                         printk("skb_check: head without next or prev\n");
  58                         return -1;
  59                 }
  60                 if (skb->next->magic_debug_cookie != SK_HEAD_SKB
  61                         && skb->next->magic_debug_cookie != SK_GOOD_SKB) {
  62                         printk("File: %s Line %d, bad next head-skb member\n",
  63                                 file,line);
  64                         return -1;
  65                 }
  66                 if (skb->prev->magic_debug_cookie != SK_HEAD_SKB
  67                         && skb->prev->magic_debug_cookie != SK_GOOD_SKB) {
  68                         printk("File: %s Line %d, bad prev head-skb member\n",
  69                                 file,line);
  70                         return -1;
  71                 }
  72 #if 0
  73                 {
  74                 struct sk_buff *skb2 = skb->next;
  75                 int i = 0;
  76                 while (skb2 != skb && i < 5) {
  77                         if (skb_check(skb2, 0, line, file) < 0) {
  78                                 printk("bad queue element in whole queue\n");
  79                                 return -1;
  80                         }
  81                         i++;
  82                         skb2 = skb2->next;
  83                 }
  84                 }
  85 #endif
  86                 return 0;
  87         }
  88         if (skb->next != NULL && skb->next->magic_debug_cookie != SK_HEAD_SKB
  89                 && skb->next->magic_debug_cookie != SK_GOOD_SKB) {
  90                 printk("File: %s Line %d, bad next skb member\n",
  91                         file,line);
  92                 return -1;
  93         }
  94         if (skb->prev != NULL && skb->prev->magic_debug_cookie != SK_HEAD_SKB
  95                 && skb->prev->magic_debug_cookie != SK_GOOD_SKB) {
  96                 printk("File: %s Line %d, bad prev skb member\n",
  97                         file,line);
  98                 return -1;
  99         }
 100 
 101 
 102         if(skb->magic_debug_cookie==SK_FREED_SKB)
 103         {
 104                 printk("File: %s Line %d, found a freed skb lurking in the undergrowth!\n",
 105                         file,line);
 106                 printk("skb=%p, real size=%ld, claimed size=%ld, free=%d\n",
 107                         skb,skb->truesize,skb->mem_len,skb->free);
 108                 return -1;
 109         }
 110         if(skb->magic_debug_cookie!=SK_GOOD_SKB)
 111         {
 112                 printk("File: %s Line %d, passed a non skb!\n", file,line);
 113                 printk("skb=%p, real size=%ld, claimed size=%ld, free=%d\n",
 114                         skb,skb->truesize,skb->mem_len,skb->free);
 115                 return -1;
 116         }
 117         if(skb->mem_len!=skb->truesize)
 118         {
 119                 printk("File: %s Line %d, Dubious size setting!\n",file,line);
 120                 printk("skb=%p, real size=%ld, claimed size=%ld\n",
 121                         skb,skb->truesize,skb->mem_len);
 122                 return -1;
 123         }
 124         /* Guess it might be acceptable then */
 125         return 0;
 126 }
 127 #endif
 128 
 129 
 130 void skb_queue_head_init(struct sk_buff_head *list)
     /* [previous][next][first][last][top][bottom][index][help] */
 131 {
 132         list->prev = (struct sk_buff *)list;
 133         list->next = (struct sk_buff *)list;
 134 #if CONFIG_SKB_CHECK
 135         list->magic_debug_cookie = SK_HEAD_SKB;
 136 #endif
 137 }
 138 
 139 
 140 /*
 141  *      Insert an sk_buff at the start of a list.
 142  */
 143     
 144 void skb_queue_head(struct sk_buff_head *list_,struct sk_buff *newsk)
     /* [previous][next][first][last][top][bottom][index][help] */
 145 {
 146         unsigned long flags;
 147         struct sk_buff *list = (struct sk_buff *)list_;
 148 
 149         save_flags(flags);
 150         cli();
 151 
 152 #if CONFIG_SKB_CHECK
 153         IS_SKB(newsk);
 154         IS_SKB_HEAD(list);
 155         if (newsk->next || newsk->prev)
 156                 printk("Suspicious queue head: sk_buff on list!\n");
 157 #endif
 158 
 159         newsk->next = list->next;
 160         newsk->prev = list;
 161 
 162         newsk->next->prev = newsk;
 163         newsk->prev->next = newsk;
 164         
 165         restore_flags(flags);
 166 }
 167 
 168 /*
 169  *      Insert an sk_buff at the end of a list.
 170  */
 171  
 172 void skb_queue_tail(struct sk_buff_head *list_, struct sk_buff *newsk)
     /* [previous][next][first][last][top][bottom][index][help] */
 173 {
 174         unsigned long flags;
 175         struct sk_buff *list = (struct sk_buff *)list_;
 176 
 177         save_flags(flags);
 178         cli();
 179 
 180 #if CONFIG_SKB_CHECK
 181         if (newsk->next || newsk->prev)
 182                 printk("Suspicious queue tail: sk_buff on list!\n");
 183         IS_SKB(newsk);
 184         IS_SKB_HEAD(list);
 185 #endif
 186 
 187         newsk->next = list;
 188         newsk->prev = list->prev;
 189 
 190         newsk->next->prev = newsk;
 191         newsk->prev->next = newsk;
 192 
 193         restore_flags(flags);
 194 }
 195 
 196 /*
 197  *      Remove an sk_buff from a list. This routine is also interrupt safe
 198  *      so you can grab read and free buffers as another process adds them.
 199  */
 200 
 201 struct sk_buff *skb_dequeue(struct sk_buff_head *list_)
     /* [previous][next][first][last][top][bottom][index][help] */
 202 {
 203         long flags;
 204         struct sk_buff *result;
 205         struct sk_buff *list = (struct sk_buff *)list_;
 206 
 207         save_flags(flags);
 208         cli();
 209 
 210         IS_SKB_HEAD(list);
 211         
 212         result = list->next;
 213         if (result == list) {
 214                 restore_flags(flags);
 215                 return NULL;
 216         }
 217         
 218         result->next->prev = list;
 219         list->next = result->next;
 220 
 221         result->next = NULL;
 222         result->prev = NULL;
 223 
 224         restore_flags(flags);
 225         
 226         return result;
 227 }
 228 
 229 /*
 230  *      Insert a packet before another one in a list.
 231  */
 232  
 233 void skb_insert(struct sk_buff *old, struct sk_buff *newsk)
     /* [previous][next][first][last][top][bottom][index][help] */
 234 {
 235         unsigned long flags;
 236 
 237 #if CONFIG_SKB_CHECK
 238         IS_SKB(old);
 239         IS_SKB(newsk);
 240 
 241         if(!old->next || !old->prev)
 242                 printk("insert before unlisted item!\n");
 243         if(newsk->next || newsk->prev)
 244                 printk("inserted item is already on a list.\n");
 245 #endif
 246 
 247         save_flags(flags);
 248         cli();
 249         newsk->next = old;
 250         newsk->prev = old->prev;
 251         old->prev = newsk;
 252         newsk->prev->next = newsk;
 253         
 254         restore_flags(flags);
 255 }
 256 
 257 /*
 258  *      Place a packet after a given packet in a list.
 259  */
 260  
 261 void skb_append(struct sk_buff *old, struct sk_buff *newsk)
     /* [previous][next][first][last][top][bottom][index][help] */
 262 {
 263         unsigned long flags;
 264 
 265 #if CONFIG_SKB_CHECK
 266         IS_SKB(old);
 267         IS_SKB(newsk);
 268 
 269         if(!old->next || !old->prev)
 270                 printk("append before unlisted item!\n");
 271         if(newsk->next || newsk->prev)
 272                 printk("append item is already on a list.\n");
 273 #endif
 274 
 275         save_flags(flags);
 276         cli();
 277 
 278         newsk->prev = old;
 279         newsk->next = old->next;
 280         newsk->next->prev = newsk;
 281         old->next = newsk;
 282 
 283         restore_flags(flags);
 284 }
 285 
 286 /*
 287  *      Remove an sk_buff from its list. Works even without knowing the list it
 288  *      is sitting on, which can be handy at times. It also means that THE LIST
 289  *      MUST EXIST when you unlink. Thus a list must have its contents unlinked
 290  *      _FIRST_.
 291  */
 292  
 293 void skb_unlink(struct sk_buff *skb)
     /* [previous][next][first][last][top][bottom][index][help] */
 294 {
 295         unsigned long flags;
 296 
 297         save_flags(flags);
 298         cli();
 299 
 300         IS_SKB(skb);
 301 
 302         if(skb->prev && skb->next)
 303         {
 304                 skb->next->prev = skb->prev;
 305                 skb->prev->next = skb->next;
 306                 skb->next = NULL;
 307                 skb->prev = NULL;
 308         }
 309 #ifdef PARANOID_BUGHUNT_MODE    /* This is legal but we sometimes want to watch it */
 310         else
 311                 printk("skb_unlink: not a linked element\n");
 312 #endif          
 313         restore_flags(flags);
 314 }
 315 
 316 /*
 317  *      Get a clone of an sk_buff. This is the safe way to peek at
 318  *      a socket queue without accidents. Its a bit long but most
 319  *      of it acutally ends up as tiny bits of inline assembler
 320  *      anyway. Only the memcpy of upto 4K with ints off is not
 321  *      as nice as I'd like.
 322  */
 323  
 324 struct sk_buff *skb_peek_copy(struct sk_buff_head *list_)
     /* [previous][next][first][last][top][bottom][index][help] */
 325 {
 326         struct sk_buff *list = (struct sk_buff *)list_;
 327         struct sk_buff *orig,*newsk;
 328         unsigned long flags;
 329         unsigned int len;
 330         /* Now for some games to avoid races */
 331 
 332         IS_SKB_HEAD(list);
 333         do
 334         {
 335                 save_flags(flags);
 336                 cli();
 337                 orig = list->next;
 338                 if (orig == list) {
 339                         restore_flags(flags);
 340                         return NULL;
 341                 }
 342                 IS_SKB(orig);
 343                 len = orig->truesize;
 344                 restore_flags(flags);
 345 
 346                 newsk = alloc_skb(len,GFP_KERNEL);      /* May sleep */
 347 
 348                 if (newsk == NULL)              /* Oh dear... not to worry */
 349                         return NULL;
 350         
 351                 save_flags(flags);
 352                 cli();
 353                 if (list->next != orig) /* List changed go around another time */
 354                 {
 355                         restore_flags(flags);
 356                         newsk->sk = NULL;
 357                         newsk->free = 1;
 358                         newsk->mem_addr = newsk;
 359                         newsk->mem_len = len;
 360                         kfree_skb(newsk, FREE_WRITE);
 361                         continue;
 362                 }
 363                 
 364                 IS_SKB(orig);
 365                 IS_SKB(newsk);
 366                 memcpy(newsk,orig,len);
 367                 newsk->next = NULL;
 368                 newsk->prev = NULL;
 369                 newsk->mem_addr = newsk;
 370                 newsk->h.raw += ((char *)newsk - (char *)orig);
 371                 newsk->link3 = NULL;
 372                 newsk->sk = NULL;
 373                 newsk->free = 1;
 374         }
 375         while(0);
 376         
 377         restore_flags(flags);
 378         return newsk;
 379 }       
 380 
 381 /*
 382  *      Free an sk_buff. This still knows about things it should
 383  *      not need to like protocols and sockets.
 384  */
 385 
 386 void kfree_skb(struct sk_buff *skb, int rw)
     /* [previous][next][first][last][top][bottom][index][help] */
 387 {
 388         if (skb == NULL) 
 389         {
 390                 printk("kfree_skb: skb = NULL (from %08lx)\n",
 391                         ((unsigned long *) &skb)[-1]);
 392                 return;
 393         }
 394         IS_SKB(skb);
 395         if (skb->lock) 
 396         {
 397                 skb->free = 1;    /* Free when unlocked */
 398                 return;
 399         }
 400         if (skb->free == 2)
 401                 printk("Warning: kfree_skb passed an skb that nobody set the free flag on! (from %08lx)\n",
 402                         ((unsigned long *) &skb)[-1]);
 403         if (skb->next)
 404                 printk("Warning: kfree_skb passed an skb still on a list (from %08lx).\n",
 405                         ((unsigned long *) &skb)[-1]);
 406         if (skb->sk) 
 407         {
 408                 if(skb->sk->prot!=NULL)
 409                 {
 410                         if (rw)
 411                                 skb->sk->prot->rfree(skb->sk, skb->mem_addr, skb->mem_len);
 412                         else
 413                                 skb->sk->prot->wfree(skb->sk, skb->mem_addr, skb->mem_len);
 414 
 415                 }
 416                 else
 417                 {
 418                         /* Non INET - default wmalloc/rmalloc handler */
 419                         if (rw)
 420                                 skb->sk->rmem_alloc-=skb->mem_len;
 421                         else
 422                                 skb->sk->wmem_alloc-=skb->mem_len;
 423                         if(!skb->sk->dead)
 424                                 wake_up_interruptible(skb->sk->sleep);
 425                         kfree_skbmem(skb->mem_addr,skb->mem_len);
 426                 }
 427         } 
 428         else 
 429                 kfree_skbmem(skb->mem_addr, skb->mem_len);
 430 }
 431 
 432 /*
 433  *      Allocate a new skbuff. We do this ourselves so we can fill in a few 'private'
 434  *      fields and also do memory statistics to find all the [BEEP] leaks.
 435  */
 436  
 437  struct sk_buff *alloc_skb(unsigned int size,int priority)
     /* [previous][next][first][last][top][bottom][index][help] */
 438  {
 439         struct sk_buff *skb;
 440                 
 441         if (intr_count && priority!=GFP_ATOMIC) {
 442                 static int count = 0;
 443                 if (++count < 5) {
 444                         printk("alloc_skb called nonatomically from interrupt %08lx\n",
 445                                 ((unsigned long *)&size)[-1]);
 446                         priority = GFP_ATOMIC;
 447                 }
 448         }
 449         
 450         size+=sizeof(struct sk_buff);
 451         skb=(struct sk_buff *)kmalloc(size,priority);
 452         if (skb == NULL)
 453                 return NULL;
 454 
 455         skb->free = 2;  /* Invalid so we pick up forgetful users */
 456         skb->lock = 0;
 457         skb->truesize = size;
 458         skb->mem_len = size;
 459         skb->mem_addr = skb;
 460         skb->fraglist = NULL;
 461         skb->prev = skb->next = NULL;
 462         skb->link3 = NULL;
 463         skb->sk = NULL;
 464         skb->stamp.tv_sec=0;    /* No idea about time */
 465         net_memory += size;
 466         net_skbcount++;
 467 #if CONFIG_SKB_CHECK
 468         skb->magic_debug_cookie = SK_GOOD_SKB;
 469 #endif
 470         skb->users = 0;
 471         return skb;
 472 }
 473 
 474 /*
 475  *      Free an skbuff by memory
 476  */     
 477 
 478 void kfree_skbmem(void *mem,unsigned size)
     /* [previous][next][first][last][top][bottom][index][help] */
 479 {
 480 #if CONFIG_SKB_CHECK
 481         struct sk_buff *x = mem;
 482         IS_SKB(x);
 483         if(x->magic_debug_cookie == SK_GOOD_SKB)
 484         {
 485                 x->magic_debug_cookie = SK_FREED_SKB;
 486                 kfree_s(mem,size);
 487                 net_skbcount--;
 488                 net_memory -= size;
 489         }
 490         else
 491                 printk("kfree_skbmem: bad magic cookie\n");
 492 #else
 493         kfree_s(mem, size);
 494 #endif
 495 }
 496 
 497 /*
 498  *      Duplicate an sk_buff. The new one is not owned by a socket or locked
 499  *      and will be freed on deletion.
 500  */
 501 
 502 struct sk_buff *skb_clone(struct sk_buff *skb, int priority)
     /* [previous][next][first][last][top][bottom][index][help] */
 503 {
 504         struct sk_buff *n;
 505         unsigned long offset;
 506         
 507         n=alloc_skb(skb->mem_len-sizeof(struct sk_buff),priority);
 508         if(n==NULL)
 509                 return NULL;
 510                 
 511         offset=((char *)n)-((char *)skb);
 512                 
 513         memcpy(n->data,skb->data,skb->mem_len-sizeof(struct sk_buff));
 514         n->len=skb->len;
 515         n->link3=NULL;
 516         n->sk=NULL;
 517         n->when=skb->when;
 518         n->dev=skb->dev;
 519         n->h.raw=skb->h.raw+offset;
 520         n->ip_hdr=(struct iphdr *)(((char *)skb->ip_hdr)+offset);
 521         n->fraglen=skb->fraglen;
 522         n->fraglist=skb->fraglist;
 523         n->saddr=skb->saddr;
 524         n->daddr=skb->daddr;
 525         n->raddr=skb->raddr;
 526         n->acked=skb->acked;
 527         n->used=skb->used;
 528         n->free=1;
 529         n->arp=skb->arp;
 530         n->tries=0;
 531         n->lock=0;
 532         n->users=0;
 533         return n;
 534 }
 535         
 536         
 537 /*
 538  *     Skbuff device locking
 539  */
 540 
 541 void skb_kept_by_device(struct sk_buff *skb)
     /* [previous][next][first][last][top][bottom][index][help] */
 542 {
 543         skb->lock++;
 544 }
 545 
 546 void skb_device_release(struct sk_buff *skb, int mode)
     /* [previous][next][first][last][top][bottom][index][help] */
 547 {
 548         unsigned long flags;
 549 
 550         save_flags(flags);
 551         cli();
 552         if (!--skb->lock && skb->free == 1)
 553                 kfree_skb(skb,mode);
 554         restore_flags(flags);
 555 }
 556 
 557 int skb_device_locked(struct sk_buff *skb)
     /* [previous][next][first][last][top][bottom][index][help] */
 558 {
 559         return skb->lock? 1 : 0;
 560 }
 561 

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