root/net/tcp/udp.c

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

DEFINITIONS

This source file includes following definitions.
  1. print_uh
  2. udp_select
  3. udp_err
  4. udp_check
  5. udp_send_check
  6. udp_loopback
  7. udp_sendto
  8. udp_write
  9. udp_ioctl
  10. udp_recvfrom
  11. udp_read
  12. udp_connect
  13. udp_close
  14. udp_rcv

   1 /* udp.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 bir7@leland.stanford.edu or
  20     C/O Department of Mathematics; Stanford University; Stanford, CA 94305
  21 */
  22 /* $Id: udp.c,v 0.8.4.9 1992/12/12 19:25:04 bir7 Exp $ */
  23 /* $Log: udp.c,v $
  24  * Revision 0.8.4.9  1992/12/12  19:25:04  bir7
  25  * cleaned up Log messages.
  26  *
  27  * Revision 0.8.4.8  1992/12/12  01:50:49  bir7
  28  * Changed connect.
  29  *
  30  * Revision 0.8.4.7  1992/12/05  21:35:53  bir7
  31  * Added more debuggin code.
  32  *
  33  * Revision 0.8.4.6  1992/12/03  19:52:20  bir7
  34  * fixed problems in udp_error.
  35  *
  36  * Revision 0.8.4.5  1992/11/18  15:38:03  bir7
  37  * fixed minor problem in waiting for memory.
  38  *
  39  * Revision 0.8.4.3  1992/11/15  14:55:30  bir7
  40  * Fixed ctrl-h and added NULL checking to print_uh
  41  *
  42  * Revision 0.8.4.2  1992/11/10  10:38:48  bir7
  43  * Change free_s to kfree_s and accidently changed free_skb to kfree_skb.
  44  *
  45  * Revision 0.8.4.1  1992/11/10  00:17:18  bir7
  46  * version change only.
  47  *
  48  * Revision 0.8.3.5  1992/11/10  00:14:47  bir7
  49  * Changed malloc to kmalloc and added Id and Log
  50  * */
  51 
  52 #include <linux/types.h>
  53 #include <linux/sched.h>
  54 #include <linux/fcntl.h>
  55 #include <linux/socket.h>
  56 #include <netinet/in.h>
  57 #include "timer.h"
  58 #include "ip.h"
  59 #include "tcp.h"
  60 #include "sock.h"
  61 #include <linux/errno.h>
  62 #include <linux/timer.h>
  63 #include <linux/termios.h> /* for ioctl's */
  64 #include <asm/system.h>
  65 #include <asm/segment.h>
  66 #include <linux/mm.h>
  67 #include "../kern_sock.h" /* for PRINTK */
  68 #include "udp.h"
  69 #include "icmp.h"
  70 
  71 #undef UDP_DEBUG
  72 
  73 #ifdef PRINTK
  74 #undef PRINTK
  75 #endif
  76 
  77 #ifdef UDP_DEBUG
  78 #define PRINTK(x) printk x
  79 #else
  80 #define PRINTK(x) /**/
  81 #endif
  82 
  83 #define min(a,b) ((a)<(b)?(a):(b))
  84 
  85 
  86 
  87 static void
  88 print_uh(struct udp_header *uh)
     /* [previous][next][first][last][top][bottom][index][help] */
  89 {
  90   if (uh == NULL)
  91     {
  92       PRINTK (("(NULL)\n"));
  93       return;
  94     }
  95         PRINTK(("source = %d, dest = %d\n", net16(uh->source), net16(uh->dest)));
  96         PRINTK(("len = %d, check = %d\n", net16(uh->len), net16(uh->check)));
  97 }
  98 
  99 
 100 int
 101 udp_select (volatile struct sock *sk, int sel_type, select_table *wait)
     /* [previous][next][first][last][top][bottom][index][help] */
 102 {
 103    select_wait(sk->sleep, wait);
 104    switch (sel_type)
 105      {
 106        case SEL_IN:
 107         if (sk->rqueue != NULL) 
 108           {
 109              return (1);
 110           }
 111         return (0);
 112 
 113        case SEL_OUT:
 114         if (sk->prot->wspace(sk) >= MIN_WRITE_SPACE)
 115           {
 116              return (1);
 117           }
 118         return (0);
 119         
 120        case SEL_EX:
 121         if (sk->err) return (1); /* can this ever happen? */
 122         return (0);
 123      }
 124    return (0);
 125 }
 126 
 127 /* this routine is called by the icmp module when it gets some
 128    sort of error condition.  If err < 0 then the socket should
 129    be closed and the error returned to the user.  If err > 0
 130    it's just the icmp type << 8 | icmp code.  
 131    header points to the first 8 bytes of the tcp header.  We need
 132    to find the appropriate port. */
 133 
 134 void
 135 udp_err (int err, unsigned char *header, unsigned long daddr,
     /* [previous][next][first][last][top][bottom][index][help] */
 136          unsigned long saddr, struct ip_protocol *protocol)
 137 {
 138    struct udp_header *th;
 139    volatile struct sock *sk;
 140    
 141    PRINTK (("udp_err (err=%d, header=%X, daddr=%X, saddr=%X, ip_protocl=%X)\n"));
 142 
 143    th = (struct udp_header *)header;
 144    sk = get_sock (&udp_prot, net16(th->dest), saddr, th->source, daddr);
 145 
 146    if (sk == NULL) return;
 147    if (err & 0xff00 == (ICMP_SOURCE_QUENCH << 8))
 148      {
 149         if (sk->cong_window > 1)
 150           sk->cong_window = sk->cong_window/2;
 151         return;
 152      }
 153 
 154    sk->err = icmp_err_convert[err & 0xff].errno;
 155    /* it's only fatal if we have connected to them. */
 156    if (icmp_err_convert[err & 0xff].fatal && sk->state == TCP_ESTABLISHED)
 157      {
 158         sk->prot->close(sk, 0);
 159      }
 160 
 161    return;
 162 
 163 }
 164 
 165 static  unsigned short
 166 udp_check (struct udp_header *uh, int len,
     /* [previous][next][first][last][top][bottom][index][help] */
 167            unsigned long saddr, unsigned long daddr)
 168 {
 169    unsigned long sum;
 170    PRINTK (("udp_check (uh=%X, len = %d, saddr = %X, daddr = %X)\n",
 171            uh, len, saddr, daddr));
 172 
 173    print_uh (uh);
 174 
 175   __asm__("\t addl %%ecx,%%ebx\n"
 176           "\t adcl %%edx,%%ebx\n"
 177           "\t adcl $0, %%ebx\n"
 178           : "=b" (sum)
 179           : "0" (daddr), "c" (saddr), "d" ((net16(len) << 16) + IPPROTO_UDP*256)
 180           : "cx","bx","dx" );
 181 
 182   if (len > 3)
 183     {
 184       __asm__(
 185               "\tclc\n"
 186               "1:\n"
 187               "\t lodsl\n"
 188               "\t adcl %%eax, %%ebx\n"
 189               "\t loop 1b\n"
 190               "\t adcl $0, %%ebx\n"
 191               : "=b" (sum) , "=S" (uh)
 192               : "0" (sum), "c" (len/4) ,"1" (uh)
 193               : "ax", "cx", "bx", "si" );
 194     }
 195 
 196   /* convert from 32 bits to 16 bits. */
 197   __asm__(
 198           "\t movl %%ebx, %%ecx\n"
 199           "\t shrl $16,%%ecx\n"
 200           "\t addw %%cx, %%bx\n"
 201           "\t adcw $0, %%bx\n"
 202           : "=b" (sum)
 203           : "0" (sum)
 204           : "bx", "cx");
 205 
 206 
 207   /* check for an extra word. */
 208   if ((len & 2) != 0)
 209     {
 210       __asm__("\t lodsw\n"
 211               "\t addw %%ax,%%bx\n"
 212               "\t adcw $0, %%bx\n"
 213               : "=b" (sum), "=S" (uh)
 214               : "0" (sum) ,"1" (uh)
 215               : "si", "ax", "bx");
 216     }
 217 
 218   /* now check for the extra byte. */
 219   if ((len & 1) != 0)
 220     {
 221       __asm__("\t lodsb\n"
 222               "\t movb $0,%%ah\n"
 223               "\t addw %%ax,%%bx\n"
 224               "\t adcw $0, %%bx\n"
 225               : "=b" (sum)
 226               : "0" (sum) ,"S" (uh)
 227               : "si", "ax", "bx");
 228     }
 229   /* we only want the bottom 16 bits, but we never cleared
 230      the top 16. */
 231    return ((~sum) & 0xffff);
 232 }
 233 
 234 static  void
 235 udp_send_check (struct udp_header *uh, unsigned long saddr, 
     /* [previous][next][first][last][top][bottom][index][help] */
 236                 unsigned long daddr, int len, volatile struct sock *sk)
 237 {
 238   uh->check = 0;
 239   if (sk && sk->no_check) return;
 240   uh->check = udp_check (uh, len, saddr, daddr);
 241 }
 242 
 243 static  int
 244 udp_loopback (volatile struct sock *sk, unsigned short port,
     /* [previous][next][first][last][top][bottom][index][help] */
 245               unsigned char *from,
 246               int len, unsigned long daddr, unsigned long saddr)
 247 {
 248         struct udp_header *uh;
 249         struct sk_buff *skb;
 250         volatile struct sock *pair;
 251         sk->inuse = 1;
 252 
 253         PRINTK (("udp_loopback \n"));
 254 
 255         pair = get_sock (sk->prot, net16(port), saddr,
 256                          sk->dummy_th.source, daddr);
 257 
 258         if (pair == NULL) return (0);
 259 
 260         skb = pair->prot->rmalloc (pair,
 261                                    sizeof (*skb) + sizeof (*uh) + len + 4,
 262                                    0, GFP_KERNEL);
 263 
 264         /* if we didn't get the memory, just drop the packet. */
 265         if (skb == NULL) return (len);
 266         skb->lock = 0;
 267         skb->mem_addr = skb;
 268         skb->mem_len = sizeof (*skb) + len + sizeof (*uh) + 4;
 269 
 270         skb->daddr = saddr;
 271         skb->saddr = daddr;
 272 
 273         skb->len = len;
 274         skb->h.raw = (unsigned char *)(skb+1);
 275 
 276         uh = skb->h.uh;
 277         uh -> source = sk->dummy_th.source;
 278         uh -> dest = port;
 279         uh -> len = len + sizeof (*uh);
 280 /*      verify_area (from , len); */
 281         memcpy_fromfs(uh+1, from, len);
 282         pair->inuse = 1;
 283         if (pair->rqueue == NULL)
 284           {
 285                   pair->rqueue = skb;
 286                   skb->next = skb;
 287                   skb->prev = skb;
 288           }
 289         else
 290           {
 291                   skb->next = pair->rqueue;
 292                   skb->prev = pair->rqueue->prev;
 293                   skb->prev->next = skb;
 294                   skb->next->prev = skb;
 295           }
 296         wake_up (pair->sleep);
 297         release_sock (pair);
 298         release_sock (sk);
 299         return (len);
 300 
 301 }
 302 
 303 static int
 304 udp_sendto (volatile struct sock *sk, unsigned char *from, int len,
     /* [previous][next][first][last][top][bottom][index][help] */
 305             int noblock,
 306             unsigned flags, struct sockaddr_in *usin, int addr_len)
 307 {
 308         /* this should be easy, we just send the packet. */
 309         struct sk_buff *skb;
 310         struct udp_header *uh;
 311         unsigned char *buff;
 312         unsigned long saddr;
 313         int copied=0;
 314         int amt;
 315         struct device *dev=NULL;
 316         struct sockaddr_in sin;
 317 
 318         /* check the flags. */
 319         if (flags) return (-EINVAL);
 320         if (len < 0) return (-EINVAL);
 321         if (len == 0) return (0);
 322 
 323         PRINTK (("sendto len = %d\n", len));
 324 
 325         /* get and verify the address. */
 326         if (usin)
 327           {
 328                   if (addr_len < sizeof (sin))
 329                     return (-EINVAL);
 330 /*                verify_area (usin, sizeof (sin));*/
 331                   memcpy_fromfs (&sin, usin, sizeof(sin));
 332                   if (sin.sin_family &&
 333                       sin.sin_family != AF_INET)
 334                     return (-EINVAL);
 335                   if (sin.sin_port == 0)
 336                     return (-EINVAL);
 337           }
 338         else
 339           {
 340                   if (sk->state != TCP_ESTABLISHED)
 341                     return (-EINVAL);
 342                   sin.sin_family = AF_INET;
 343                   sin.sin_port = sk->dummy_th.dest;
 344                   sin.sin_addr.s_addr = sk->daddr;
 345           }
 346 
 347         /* check for a valid saddr. */
 348         saddr = sk->saddr;
 349         if ((saddr &  0xff000000) == 0)
 350           {
 351              saddr = MY_IP_ADDR;
 352           }
 353 
 354         /* if it's a broadcast, make sure we get it. */
 355         if ((sin.sin_addr.s_addr & 0xff000000) == 0)
 356           {
 357              int err;
 358              err = udp_loopback (sk, sin.sin_port, from, len,
 359                                  sin.sin_addr.s_addr, saddr);
 360              if (err < 0)
 361                return (err);
 362           }
 363 
 364         sk->inuse = 1;
 365 
 366         while (len > 0)
 367           {
 368                   int tmp;
 369                   skb = sk->prot->wmalloc (sk, len + sizeof (*skb)
 370                                                + sk->prot->max_header, 0,
 371                                            GFP_KERNEL);
 372                   /* this should never happen, but it is possible. */
 373 
 374                   if (skb == NULL)
 375                     {
 376                        printk ("udp_sendto: write buffer full?\n");
 377                        print_sk(sk);
 378                        tmp = sk->wmem_alloc;
 379                        release_sock (sk);
 380                        if (copied) return (copied);
 381                        if (noblock) return (-EAGAIN);
 382                        cli();
 383                        if (tmp <= sk->wmem_alloc)
 384                          {
 385                            interruptible_sleep_on (sk->sleep);
 386                            if (current->signal & ~current->blocked)
 387                              {
 388                                sti();
 389                                if (copied) return (copied);
 390                                return (-ERESTARTSYS);
 391                              }
 392                          }
 393                        sk->inuse = 1;
 394                        sti();
 395                        continue;
 396                     }
 397 
 398                   skb->lock = 0;
 399                   skb->mem_addr = skb;
 400                   skb->mem_len = len + sizeof (*skb) + sk->prot->max_header;
 401                   skb->sk = sk;
 402                   skb->free = 1;
 403                   skb->arp = 0;
 404 
 405                   /* now build the ip and dev header. */
 406                   buff = (unsigned char *)(skb+1);
 407                   tmp = sk->prot->build_header (skb, saddr,
 408                                                 sin.sin_addr.s_addr, &dev,
 409                                                 IPPROTO_UDP, sk->opt, skb->mem_len);
 410                   if (tmp < 0 )
 411                     {
 412                             sk->prot->wfree (sk, skb->mem_addr, skb->mem_len);
 413                             release_sock (sk);
 414                             return (tmp);
 415                     }
 416                   buff += tmp;
 417 
 418                   /* we shouldn't do this, instead we should just
 419                      let the ip protocol fragment the packet. */
 420                   amt = min (len + tmp + sizeof (*uh), dev->mtu);
 421 
 422                   PRINTK (("amt = %d, dev = %X, dev->mtu = %d\n",
 423                           amt, dev, dev->mtu));
 424 
 425                   skb->len = amt;
 426                   amt -= tmp; 
 427 
 428                   uh = (struct udp_header *)buff;
 429                   uh->len = net16(amt);
 430                   uh->source = sk->dummy_th.source;
 431                   uh->dest = sin.sin_port;
 432 
 433                   amt -= sizeof (*uh);
 434                   buff += sizeof (*uh);
 435                   if (amt < 0)
 436                     {
 437                       printk ("udp.c: amt = %d < 0\n",amt);
 438                       release_sock (sk);
 439                       return (copied);
 440                     }
 441 
 442 /*                verify_area (from, amt);*/
 443                   memcpy_fromfs( buff, from, amt);
 444 
 445                   len -= amt;
 446                   copied += amt;
 447                   from += amt;
 448                   udp_send_check (uh, saddr, sin.sin_addr.s_addr,
 449                                   amt+sizeof (*uh), sk);
 450                                   
 451                   sk->prot->queue_xmit (sk, dev, skb, 1);
 452           }
 453         release_sock (sk);
 454         return (copied);
 455 }
 456 
 457 static int
 458 udp_write (volatile struct sock *sk, unsigned char *buff, int len, int noblock,
     /* [previous][next][first][last][top][bottom][index][help] */
 459            unsigned flags)
 460 {
 461         return (udp_sendto (sk, buff, len, noblock, flags, NULL, 0));
 462 }
 463 
 464 
 465 static int
 466 udp_ioctl (volatile struct sock *sk, int cmd, unsigned long arg)
     /* [previous][next][first][last][top][bottom][index][help] */
 467 {
 468   switch (cmd)
 469     {
 470     default:
 471       return (-EINVAL);
 472 
 473       case TIOCOUTQ:
 474         {
 475           unsigned long amount;
 476           if (sk->state == TCP_LISTEN)
 477             return (-EINVAL);
 478           amount = sk->prot->wspace(sk)/2;
 479           verify_area ((void *)arg, sizeof (unsigned long));
 480           put_fs_long (amount, (unsigned long *)arg);
 481           return (0);
 482         }
 483 
 484 
 485       case TIOCINQ:
 486 /*      case FIONREAD:*/
 487         {
 488           struct sk_buff *skb;
 489           unsigned long amount;
 490           if (sk->state == TCP_LISTEN)
 491             return (-EINVAL);
 492           amount = 0;
 493           skb = sk->rqueue;
 494           if (skb != NULL)
 495             {
 496               /* we will only return the amount of this packet since that is all
 497                  that will be read. */
 498               amount = skb->len;
 499             }
 500 
 501           verify_area ((void *)arg, sizeof (unsigned long));
 502           put_fs_long (amount, (unsigned long *)arg);
 503           return (0);
 504         }
 505     }
 506 }
 507 
 508 int
 509 udp_recvfrom (volatile struct sock *sk, unsigned char *to, int len,
     /* [previous][next][first][last][top][bottom][index][help] */
 510               int noblock,
 511               unsigned flags, struct sockaddr_in *sin, int *addr_len)
 512 {
 513         /* this should be easy, if there is something there we
 514            return it, otherwise we block. */
 515         int copied=0;
 516         struct sk_buff *skb;
 517         if (len == 0) return (0);
 518         if (len < 0) return (-EINVAL);
 519 
 520         /* this will pick up errors that occured
 521            while the program was doing something
 522            else. */
 523         if (sk->err)
 524           {
 525             int err;
 526             err = -sk->err;
 527             sk->err = 0;
 528             return (err);
 529           }
 530         if (addr_len)
 531           {
 532                   verify_area (addr_len, sizeof(*addr_len));
 533                   put_fs_long (sizeof (*sin), addr_len);
 534           }
 535         sk->inuse = 1;
 536         while (sk->rqueue == NULL)
 537           {
 538             if (sk->shutdown & RCV_SHUTDOWN)
 539               {
 540                 return (0);
 541               }
 542 
 543             if (noblock)
 544                {
 545                   release_sock (sk);
 546                   return (-EAGAIN);
 547                }
 548              release_sock (sk);
 549              cli();
 550              if (sk->rqueue == NULL)
 551                {
 552                   interruptible_sleep_on (sk->sleep);
 553                   if (current->signal & ~current->blocked)
 554                     {
 555                        return (-ERESTARTSYS);
 556                     }
 557                }
 558              sti();
 559           }
 560         skb = sk->rqueue;
 561 
 562         if (!(flags & MSG_PEEK))
 563           {
 564                   if (skb->next == skb )
 565                     {
 566                             sk->rqueue = NULL;
 567                     }
 568                   else
 569                     {
 570                             sk->rqueue = sk->rqueue ->next;
 571                             skb->prev->next = skb->next;
 572                             skb->next->prev = skb->prev;
 573                     }
 574           }
 575         copied = min (len, skb->len);
 576         verify_area (to, copied);
 577         memcpy_tofs (to, skb->h.raw + sizeof (struct udp_header), copied);
 578         /* copy the address. */
 579         if (sin)
 580           {
 581                   struct sockaddr_in addr;
 582                   addr.sin_family = AF_INET;
 583                   addr.sin_port = skb->h.uh->source;
 584                   addr.sin_addr.s_addr = skb->daddr;
 585                   verify_area (sin, sizeof (*sin));
 586                   memcpy_tofs(sin, &addr, sizeof (*sin));
 587           }
 588 
 589         if (!(flags & MSG_PEEK))
 590           {
 591              kfree_skb (skb, FREE_READ);
 592           }
 593         release_sock (sk);
 594         return (copied);
 595 
 596 }
 597 
 598 
 599 int
 600 udp_read (volatile struct sock *sk, unsigned char *buff, int len, int noblock,
     /* [previous][next][first][last][top][bottom][index][help] */
 601           unsigned flags)
 602 {
 603         return (udp_recvfrom (sk, buff, len, noblock, flags, NULL, NULL));
 604 }
 605 
 606 int
 607 udp_connect (volatile struct sock *sk, struct sockaddr_in *usin, int addr_len)
     /* [previous][next][first][last][top][bottom][index][help] */
 608 {
 609         struct sockaddr_in sin;
 610         if (addr_len < sizeof (sin)) return (-EINVAL);
 611 /*      verify_area (usin, sizeof (sin)); */
 612         memcpy_fromfs (&sin, usin, sizeof (sin));
 613         if (sin.sin_family && sin.sin_family != AF_INET)
 614           return (-EAFNOSUPPORT);
 615         sk->daddr = sin.sin_addr.s_addr;
 616         sk->dummy_th.dest = sin.sin_port;
 617         sk->state = TCP_ESTABLISHED;
 618         return(0);
 619 }
 620 
 621 static void
 622 udp_close(volatile struct sock *sk, int timeout)
     /* [previous][next][first][last][top][bottom][index][help] */
 623 {
 624         sk->inuse = 1;
 625         sk->state = TCP_CLOSE;
 626         if (sk->dead)
 627           destroy_sock (sk);
 628         else
 629           release_sock (sk);
 630 }
 631 
 632 int
 633 udp_rcv(struct sk_buff *skb, struct device *dev, struct options *opt,
     /* [previous][next][first][last][top][bottom][index][help] */
 634         unsigned long daddr, unsigned short len,
 635         unsigned long saddr, int redo, struct ip_protocol *protocol)
 636 {
 637         /* all we need to do is get the socket, and then do a checksum. */
 638         struct proto *prot=&udp_prot;
 639         volatile struct sock *sk;
 640         struct udp_header *uh;
 641 
 642         uh = (struct udp_header *) skb->h.uh;
 643 
 644         if (dev->add_arp) dev->add_arp (saddr, skb, dev);
 645 
 646         sk = get_sock (prot, net16(uh->dest), saddr, uh->source, daddr);
 647 
 648         /* if we don't know about the socket, forget about it. */
 649         if (sk == NULL)
 650           {
 651             if ((daddr & 0xff000000 != 0) &&
 652                 (daddr & 0xff000000 != 0xff000000))
 653               {
 654                 icmp_reply (skb, ICMP_DEST_UNREACH, ICMP_PORT_UNREACH, dev);
 655               }
 656             skb->sk = NULL;
 657             kfree_skb (skb, 0);
 658             return (0);
 659           }
 660 
 661 
 662         if (!redo)
 663           {
 664              if (uh->check && udp_check (uh, len, saddr, daddr))
 665                {
 666                   PRINTK (("bad udp checksum\n"));
 667                   skb->sk = NULL;
 668                   kfree_skb (skb, 0);
 669                   return (0);
 670                }
 671 
 672              skb->sk = sk;
 673              skb->dev = dev;
 674              skb->len = len;
 675 
 676              /* these are supposed to be switched. */
 677              skb->daddr = saddr;
 678              skb->saddr = daddr;
 679 
 680              /* Now deal with the in use. */
 681              cli();
 682              if (sk->inuse)
 683                {
 684                   if (sk->back_log == NULL)
 685                     {
 686                        sk->back_log = skb;
 687                        skb->next = skb;
 688                        skb->prev = skb;
 689                     }
 690                   else
 691                     {
 692                        skb->next = sk->back_log;
 693                        skb->prev = sk->back_log->prev;
 694                        skb->prev->next = skb;
 695                        skb->next->prev = skb;
 696                     }
 697                   sti();
 698                   return (0);
 699                }
 700              sk->inuse = 1;
 701              sti();
 702           }
 703 
 704         /* charge it too the socket. */
 705         if (sk->rmem_alloc + skb->mem_len >= SK_RMEM_MAX)
 706           {
 707              skb->sk = NULL;
 708              kfree_skb (skb, 0);
 709              release_sock (sk);
 710              return (0);
 711           }
 712              
 713         sk->rmem_alloc += skb->mem_len;
 714 
 715         /* At this point we should print the thing out. */
 716         PRINTK (("<< \n"));
 717         print_sk (sk);
 718 
 719         /* now add it to the data chain and wake things up. */
 720         if (sk->rqueue == NULL)
 721           {
 722                   sk->rqueue = skb;
 723                   skb->next = skb;
 724                   skb->prev = skb;
 725           }
 726         else
 727           {
 728                   skb->next = sk->rqueue;
 729                   skb->prev = sk->rqueue->prev;
 730                   skb->prev->next = skb;
 731                   skb->next->prev = skb;
 732           }
 733 
 734         skb->len = len - sizeof (*uh);
 735 
 736         if (!sk->dead)
 737           wake_up (sk->sleep);
 738 
 739         release_sock (sk);
 740         return (0);
 741 }
 742 
 743 
 744 
 745 struct proto udp_prot =
 746 {
 747   sock_wmalloc,
 748   sock_rmalloc,
 749   sock_wfree,
 750   sock_rfree,
 751   sock_rspace,
 752   sock_wspace,
 753   udp_close,
 754   udp_read,
 755   udp_write,
 756   udp_sendto,
 757   udp_recvfrom,
 758   ip_build_header,
 759   udp_connect,
 760   NULL,
 761   ip_queue_xmit,
 762   ip_retransmit,
 763   NULL,
 764   NULL,
 765   udp_rcv,
 766   udp_select,
 767   udp_ioctl,
 768   NULL,
 769   NULL,
 770   128,
 771   0,
 772   {NULL,}
 773 };
 774 

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