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

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