root/net/inet/udp.c

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

DEFINITIONS

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

   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  *              The User Datagram Protocol (UDP).
   7  *
   8  * Version:     @(#)udp.c       1.0.13  06/02/93
   9  *
  10  * Authors:     Ross Biro, <bir7@leland.Stanford.Edu>
  11  *              Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
  12  *
  13  * Fixes:
  14  *              Alan Cox        :       verify_area() calls
  15  *              Alan Cox        :       stopped close while in use off icmp
  16  *                                      messages. Not a fix but a botch that
  17  *                                      for udp at least is 'valid'.
  18  *              Alan Cox        :       Fixed icmp handling properly
  19  *              Alan Cox        :       Correct error for oversized datagrams
  20  *              Alan Cox        :       Tidied select() semantics. 
  21  *              Alan Cox        :       udp_err() fixed properly, also now 
  22  *                                      select and read wake correctly on errors
  23  *              Alan Cox        :       udp_send verify_area moved to avoid mem leak
  24  *              Alan Cox        :       UDP can count its memory
  25  *              Alan Cox        :       send to an unknown connection causes
  26  *                                      an ECONNREFUSED off the icmp, but
  27  *                                      does NOT close.
  28  *              Alan Cox        :       Switched to new sk_buff handlers. No more backlog!
  29  *              Alan Cox        :       Using generic datagram code. Even smaller and the PEEK
  30  *                                      bug no longer crashes it.
  31  *              Fred Van Kempen :       Net2e support for sk->broadcast.
  32  *              Alan Cox        :       Uses skb_free_datagram
  33  *              Alan Cox        :       Added get/set sockopt support.
  34  *              Alan Cox        :       Broadcasting without option set returns EACCES.
  35  *              Alan Cox        :       No wakeup calls. Instead we now use the callbacks.
  36  *              Alan Cox        :       Use ip_tos and ip_ttl
  37  *              Alan Cox        :       SNMP Mibs
  38  *              Alan Cox        :       MSG_DONTROUTE, and 0.0.0.0 support.
  39  *              Matt Dillon     :       UDP length checks.
  40  *              Alan Cox        :       Smarter af_inet used properly.
  41  *              Alan Cox        :       Use new kernel side addressing.
  42  *              Alan Cox        :       Incorrect return on truncated datagram receive.
  43  *
  44  *
  45  *              This program is free software; you can redistribute it and/or
  46  *              modify it under the terms of the GNU General Public License
  47  *              as published by the Free Software Foundation; either version
  48  *              2 of the License, or (at your option) any later version.
  49  */
  50  
  51 #include <asm/system.h>
  52 #include <asm/segment.h>
  53 #include <linux/types.h>
  54 #include <linux/sched.h>
  55 #include <linux/fcntl.h>
  56 #include <linux/socket.h>
  57 #include <linux/sockios.h>
  58 #include <linux/in.h>
  59 #include <linux/errno.h>
  60 #include <linux/timer.h>
  61 #include <linux/termios.h>
  62 #include <linux/mm.h>
  63 #include <linux/config.h>
  64 #include <linux/inet.h>
  65 #include <linux/netdevice.h>
  66 #include "snmp.h"
  67 #include "ip.h"
  68 #include "protocol.h"
  69 #include "tcp.h"
  70 #include <linux/skbuff.h>
  71 #include "sock.h"
  72 #include "udp.h"
  73 #include "icmp.h"
  74 #include "route.h"
  75 
  76 /*
  77  *      SNMP MIB for the UDP layer
  78  */
  79 
  80 struct udp_mib          udp_statistics;
  81 
  82 
  83 static int udp_deliver(struct sock *sk, struct udphdr *uh, struct sk_buff *skb, struct device *dev, long saddr, long daddr, int len);
  84 
  85 #define min(a,b)        ((a)<(b)?(a):(b))
  86 
  87 
  88 /*
  89  * This routine is called by the ICMP module when it gets some
  90  * sort of error condition.  If err < 0 then the socket should
  91  * be closed and the error returned to the user.  If err > 0
  92  * it's just the icmp type << 8 | icmp code.  
  93  * Header points to the ip header of the error packet. We move
  94  * on past this. Then (as it used to claim before adjustment)
  95  * header points to the first 8 bytes of the udp header.  We need
  96  * to find the appropriate port.
  97  */
  98 
  99 void udp_err(int err, unsigned char *header, unsigned long daddr,
     /* [previous][next][first][last][top][bottom][index][help] */
 100         unsigned long saddr, struct inet_protocol *protocol)
 101 {
 102         struct udphdr *th;
 103         struct sock *sk;
 104         struct iphdr *ip=(struct iphdr *)header;
 105   
 106         header += 4*ip->ihl;
 107 
 108         /*
 109          *      Find the 8 bytes of post IP header ICMP included for us
 110          */  
 111         
 112         th = (struct udphdr *)header;  
 113    
 114         sk = get_sock(&udp_prot, th->source, daddr, th->dest, saddr);
 115 
 116         if (sk == NULL) 
 117                 return; /* No socket for error */
 118         
 119         if (err & 0xff00 ==(ICMP_SOURCE_QUENCH << 8)) 
 120         {       /* Slow down! */
 121                 if (sk->cong_window > 1) 
 122                         sk->cong_window = sk->cong_window/2;
 123                 return;
 124         }
 125 
 126         /*
 127          *      Various people wanted BSD UDP semantics. Well they've come 
 128          *      back out because they slow down response to stuff like dead
 129          *      or unreachable name servers and they screw term users something
 130          *      chronic. Oh and it violates RFC1122. So basically fix your 
 131          *      client code people.
 132          */
 133          
 134 #ifdef CONFIG_I_AM_A_BROKEN_BSD_WEENIE
 135         /*
 136          *      It's only fatal if we have connected to them. I'm not happy
 137          *      with this code. Some BSD comparisons need doing.
 138          */
 139          
 140         if (icmp_err_convert[err & 0xff].fatal && sk->state == TCP_ESTABLISHED) 
 141         {
 142                 sk->err = icmp_err_convert[err & 0xff].errno;
 143                 sk->error_report(sk);
 144         }
 145 #else
 146         if (icmp_err_convert[err & 0xff].fatal)
 147         {
 148                 sk->err = icmp_err_convert[err & 0xff].errno;
 149                 sk->error_report(sk);
 150         }
 151 #endif
 152 }
 153 
 154 
 155 static unsigned short udp_check(struct udphdr *uh, int len, unsigned long saddr, unsigned long daddr)
     /* [previous][next][first][last][top][bottom][index][help] */
 156 {
 157         unsigned long sum;
 158 
 159         __asm__(  "\t addl %%ecx,%%ebx\n"
 160                   "\t adcl %%edx,%%ebx\n"
 161                   "\t adcl $0, %%ebx\n"
 162                   : "=b"(sum)
 163                   : "0"(daddr), "c"(saddr), "d"((ntohs(len) << 16) + IPPROTO_UDP*256)
 164                   : "cx","bx","dx" );
 165 
 166         if (len > 3) 
 167         {
 168                 __asm__("\tclc\n"
 169                         "1:\n"
 170                         "\t lodsl\n"
 171                         "\t adcl %%eax, %%ebx\n"
 172                         "\t loop 1b\n"
 173                         "\t adcl $0, %%ebx\n"
 174                         : "=b"(sum) , "=S"(uh)
 175                         : "0"(sum), "c"(len/4) ,"1"(uh)
 176                         : "ax", "cx", "bx", "si" );
 177         }
 178 
 179         /*
 180          *      Convert from 32 bits to 16 bits. 
 181          */
 182 
 183         __asm__("\t movl %%ebx, %%ecx\n"
 184                 "\t shrl $16,%%ecx\n"
 185                 "\t addw %%cx, %%bx\n"
 186                 "\t adcw $0, %%bx\n"
 187                 : "=b"(sum)
 188                 : "0"(sum)
 189                 : "bx", "cx");
 190         
 191         /* 
 192          *      Check for an extra word. 
 193          */
 194          
 195         if ((len & 2) != 0) 
 196         {
 197                 __asm__("\t lodsw\n"
 198                         "\t addw %%ax,%%bx\n"
 199                         "\t adcw $0, %%bx\n"
 200                         : "=b"(sum), "=S"(uh)
 201                         : "0"(sum) ,"1"(uh)
 202                         : "si", "ax", "bx");
 203         }
 204 
 205         /*
 206          *      Now check for the extra byte. 
 207          */
 208          
 209         if ((len & 1) != 0) 
 210         {
 211                 __asm__("\t lodsb\n"
 212                         "\t movb $0,%%ah\n"
 213                         "\t addw %%ax,%%bx\n"
 214                         "\t adcw $0, %%bx\n"
 215                         : "=b"(sum)
 216                         : "0"(sum) ,"S"(uh)
 217                         : "si", "ax", "bx");
 218         }
 219 
 220         /* 
 221          *      We only want the bottom 16 bits, but we never cleared the top 16. 
 222          */
 223 
 224         return((~sum) & 0xffff);
 225 }
 226 
 227 /*
 228  *      Generate UDP checksums. These may be disabled, eg for fast NFS over ethernet
 229  *      We default them enabled.. if you turn them off you either know what you are
 230  *      doing or get burned...
 231  */
 232 
 233 static void udp_send_check(struct udphdr *uh, unsigned long saddr, 
     /* [previous][next][first][last][top][bottom][index][help] */
 234                unsigned long daddr, int len, struct sock *sk)
 235 {
 236         uh->check = 0;
 237         if (sk && sk->no_check) 
 238                 return;
 239         uh->check = udp_check(uh, len, saddr, daddr);
 240         
 241         /*
 242          *      FFFF and 0 are the same, pick the right one as 0 in the
 243          *      actual field means no checksum.
 244          */
 245          
 246         if (uh->check == 0)
 247                 uh->check = 0xffff;
 248 }
 249 
 250 
 251 static int udp_send(struct sock *sk, struct sockaddr_in *sin,
     /* [previous][next][first][last][top][bottom][index][help] */
 252          unsigned char *from, int len, int rt)
 253 {
 254         struct sk_buff *skb;
 255         struct device *dev;
 256         struct udphdr *uh;
 257         unsigned char *buff;
 258         unsigned long saddr;
 259         int size, tmp;
 260         int ttl;
 261   
 262         /* 
 263          *      Allocate an sk_buff copy of the packet.
 264          */
 265          
 266         size = sk->prot->max_header + len;
 267         skb = sock_alloc_send_skb(sk, size, 0, &tmp);
 268 
 269 
 270         if (skb == NULL) 
 271                 return tmp;
 272 
 273         skb->sk       = NULL;   /* to avoid changing sk->saddr */
 274         skb->free     = 1;
 275         skb->localroute = sk->localroute|(rt&MSG_DONTROUTE);
 276 
 277         /*
 278          *      Now build the IP and MAC header. 
 279          */
 280          
 281         buff = skb->data;
 282         saddr = sk->saddr;
 283         dev = NULL;
 284         ttl = sk->ip_ttl;
 285 #ifdef CONFIG_IP_MULTICAST
 286         if (MULTICAST(sin->sin_addr.s_addr))
 287                 ttl = sk->ip_mc_ttl;
 288 #endif
 289         tmp = sk->prot->build_header(skb, saddr, sin->sin_addr.s_addr,
 290                         &dev, IPPROTO_UDP, sk->opt, skb->mem_len,sk->ip_tos,ttl);
 291 
 292         skb->sk=sk;     /* So memory is freed correctly */
 293         
 294         /*
 295          *      Unable to put a header on the packet.
 296          */
 297                             
 298         if (tmp < 0 ) 
 299         {
 300                 sk->prot->wfree(sk, skb->mem_addr, skb->mem_len);
 301                 return(tmp);
 302         }
 303         
 304         buff += tmp;
 305         saddr = skb->saddr; /*dev->pa_addr;*/
 306         skb->len = tmp + sizeof(struct udphdr) + len;   /* len + UDP + IP + MAC */
 307         skb->dev = dev;
 308         
 309         /*
 310          *      Fill in the UDP header. 
 311          */
 312          
 313         uh = (struct udphdr *) buff;
 314         uh->len = htons(len + sizeof(struct udphdr));
 315         uh->source = sk->dummy_th.source;
 316         uh->dest = sin->sin_port;
 317         buff = (unsigned char *) (uh + 1);
 318 
 319         /*
 320          *      Copy the user data. 
 321          */
 322          
 323         memcpy_fromfs(buff, from, len);
 324 
 325         /*
 326          *      Set up the UDP checksum. 
 327          */
 328          
 329         udp_send_check(uh, saddr, sin->sin_addr.s_addr, skb->len - tmp, sk);
 330 
 331         /* 
 332          *      Send the datagram to the interface. 
 333          */
 334          
 335         udp_statistics.UdpOutDatagrams++;
 336          
 337         sk->prot->queue_xmit(sk, dev, skb, 1);
 338         return(len);
 339 }
 340 
 341 
 342 static int udp_sendto(struct sock *sk, unsigned char *from, int len, int noblock,
     /* [previous][next][first][last][top][bottom][index][help] */
 343            unsigned flags, struct sockaddr_in *usin, int addr_len)
 344 {
 345         struct sockaddr_in sin;
 346         int tmp;
 347 
 348         /* 
 349          *      Check the flags. We support no flags for UDP sending
 350          */
 351         if (flags&~MSG_DONTROUTE) 
 352                 return(-EINVAL);
 353         /*
 354          *      Get and verify the address. 
 355          */
 356          
 357         if (usin) 
 358         {
 359                 if (addr_len < sizeof(sin)) 
 360                         return(-EINVAL);
 361                 memcpy(&sin,usin,sizeof(sin));
 362                 if (sin.sin_family && sin.sin_family != AF_INET) 
 363                         return(-EINVAL);
 364                 if (sin.sin_port == 0) 
 365                         return(-EINVAL);
 366         } 
 367         else 
 368         {
 369                 if (sk->state != TCP_ESTABLISHED) 
 370                         return(-EINVAL);
 371                 sin.sin_family = AF_INET;
 372                 sin.sin_port = sk->dummy_th.dest;
 373                 sin.sin_addr.s_addr = sk->daddr;
 374         }
 375   
 376         /*
 377          *      BSD socket semantics. You must set SO_BROADCAST to permit
 378          *      broadcasting of data.
 379          */
 380          
 381         if(sin.sin_addr.s_addr==INADDR_ANY)
 382                 sin.sin_addr.s_addr=ip_my_addr();
 383                 
 384         if(!sk->broadcast && ip_chk_addr(sin.sin_addr.s_addr)==IS_BROADCAST)
 385                 return -EACCES;                 /* Must turn broadcast on first */
 386 
 387         sk->inuse = 1;
 388 
 389         /* Send the packet. */
 390         tmp = udp_send(sk, &sin, from, len, flags);
 391 
 392         /* The datagram has been sent off.  Release the socket. */
 393         release_sock(sk);
 394         return(tmp);
 395 }
 396 
 397 /*
 398  *      In BSD SOCK_DGRAM a write is just like a send.
 399  */
 400 
 401 static int udp_write(struct sock *sk, unsigned char *buff, int len, int noblock,
     /* [previous][next][first][last][top][bottom][index][help] */
 402           unsigned flags)
 403 {
 404         return(udp_sendto(sk, buff, len, noblock, flags, NULL, 0));
 405 }
 406 
 407 
 408 /*
 409  *      IOCTL requests applicable to the UDP protocol
 410  */
 411  
 412 int udp_ioctl(struct sock *sk, int cmd, unsigned long arg)
     /* [previous][next][first][last][top][bottom][index][help] */
 413 {
 414         int err;
 415         switch(cmd) 
 416         {
 417                 case TIOCOUTQ:
 418                 {
 419                         unsigned long amount;
 420 
 421                         if (sk->state == TCP_LISTEN) return(-EINVAL);
 422                         amount = sk->prot->wspace(sk)/*/2*/;
 423                         err=verify_area(VERIFY_WRITE,(void *)arg,
 424                                         sizeof(unsigned long));
 425                         if(err)
 426                                 return(err);
 427                         put_fs_long(amount,(unsigned long *)arg);
 428                         return(0);
 429                 }
 430 
 431                 case TIOCINQ:
 432                 {
 433                         struct sk_buff *skb;
 434                         unsigned long amount;
 435 
 436                         if (sk->state == TCP_LISTEN) return(-EINVAL);
 437                         amount = 0;
 438                         skb = skb_peek(&sk->receive_queue);
 439                         if (skb != NULL) {
 440                                 /*
 441                                  * We will only return the amount
 442                                  * of this packet since that is all
 443                                  * that will be read.
 444                                  */
 445                                 amount = skb->len;
 446                         }
 447                         err=verify_area(VERIFY_WRITE,(void *)arg,
 448                                                 sizeof(unsigned long));
 449                         if(err)
 450                                 return(err);
 451                         put_fs_long(amount,(unsigned long *)arg);
 452                         return(0);
 453                 }
 454 
 455                 default:
 456                         return(-EINVAL);
 457         }
 458         return(0);
 459 }
 460 
 461 
 462 /*
 463  *      This should be easy, if there is something there we\
 464  *      return it, otherwise we block.
 465  */
 466 
 467 int udp_recvfrom(struct sock *sk, unsigned char *to, int len,
     /* [previous][next][first][last][top][bottom][index][help] */
 468              int noblock, unsigned flags, struct sockaddr_in *sin,
 469              int *addr_len)
 470 {
 471         int copied = 0;
 472         int truesize;
 473         struct sk_buff *skb;
 474         int er;
 475 
 476         /*
 477          *      Check any passed addresses
 478          */
 479          
 480         if (addr_len) 
 481                 *addr_len=sizeof(*sin);
 482   
 483         /*
 484          *      From here the generic datagram does a lot of the work. Come
 485          *      the finished NET3, it will do _ALL_ the work!
 486          */
 487                 
 488         skb=skb_recv_datagram(sk,flags,noblock,&er);
 489         if(skb==NULL)
 490                 return er;
 491   
 492         truesize = skb->len;
 493         copied = min(len, truesize);
 494 
 495         /*
 496          *      FIXME : should use udp header size info value 
 497          */
 498          
 499         skb_copy_datagram(skb,sizeof(struct udphdr),to,copied);
 500         sk->stamp=skb->stamp;
 501 
 502         /* Copy the address. */
 503         if (sin) 
 504         {
 505                 sin->sin_family = AF_INET;
 506                 sin->sin_port = skb->h.uh->source;
 507                 sin->sin_addr.s_addr = skb->daddr;
 508         }
 509   
 510         skb_free_datagram(skb);
 511         release_sock(sk);
 512         return(truesize);
 513 }
 514 
 515 /*
 516  *      Read has the same semantics as recv in SOCK_DGRAM
 517  */
 518 
 519 int udp_read(struct sock *sk, unsigned char *buff, int len, int noblock,
     /* [previous][next][first][last][top][bottom][index][help] */
 520          unsigned flags)
 521 {
 522         return(udp_recvfrom(sk, buff, len, noblock, flags, NULL, NULL));
 523 }
 524 
 525 
 526 int udp_connect(struct sock *sk, struct sockaddr_in *usin, int addr_len)
     /* [previous][next][first][last][top][bottom][index][help] */
 527 {
 528         struct rtable *rt;
 529         unsigned long sa;
 530         if (addr_len < sizeof(*usin)) 
 531                 return(-EINVAL);
 532 
 533         if (usin->sin_family && usin->sin_family != AF_INET) 
 534                 return(-EAFNOSUPPORT);
 535         if (usin->sin_addr.s_addr==INADDR_ANY)
 536                 usin->sin_addr.s_addr=ip_my_addr();
 537 
 538         if(!sk->broadcast && ip_chk_addr(usin->sin_addr.s_addr)==IS_BROADCAST)
 539                 return -EACCES;                 /* Must turn broadcast on first */
 540         
 541         rt=ip_rt_route(usin->sin_addr.s_addr, NULL, &sa);
 542         if(rt==NULL)
 543                 return -ENETUNREACH;
 544         sk->saddr = sa;         /* Update source address */
 545         sk->daddr = usin->sin_addr.s_addr;
 546         sk->dummy_th.dest = usin->sin_port;
 547         sk->state = TCP_ESTABLISHED;
 548         return(0);
 549 }
 550 
 551 
 552 static void udp_close(struct sock *sk, int timeout)
     /* [previous][next][first][last][top][bottom][index][help] */
 553 {
 554         sk->inuse = 1;
 555         sk->state = TCP_CLOSE;
 556         if (sk->dead) 
 557                 destroy_sock(sk);
 558         else
 559                 release_sock(sk);
 560 }
 561 
 562 
 563 /*
 564  *      All we need to do is get the socket, and then do a checksum. 
 565  */
 566  
 567 int udp_rcv(struct sk_buff *skb, struct device *dev, struct options *opt,
     /* [previous][next][first][last][top][bottom][index][help] */
 568         unsigned long daddr, unsigned short len,
 569         unsigned long saddr, int redo, struct inet_protocol *protocol)
 570 {
 571         struct sock *sk;
 572         struct udphdr *uh;
 573         unsigned short ulen;
 574         int addr_type = IS_MYADDR;
 575         
 576         if(!dev || dev->pa_addr!=daddr)
 577                 addr_type=ip_chk_addr(daddr);
 578                 
 579         /*
 580          *      Get the header.
 581          */
 582         uh = (struct udphdr *) skb->h.uh;
 583         
 584         ip_statistics.IpInDelivers++;
 585 
 586         /*
 587          *      Validate the packet and the UDP length.
 588          */
 589          
 590         ulen = ntohs(uh->len);
 591 
 592         if (ulen > len || len < sizeof(*uh) || ulen < sizeof(*uh)) 
 593         {
 594                 printk("UDP: short packet: %d/%d\n", ulen, len);
 595                 udp_statistics.UdpInErrors++;
 596                 kfree_skb(skb, FREE_WRITE);
 597                 return(0);
 598         }
 599 
 600         if (uh->check && udp_check(uh, len, saddr, daddr)) 
 601         {
 602                 /* <mea@utu.fi> wants to know, who sent it, to
 603                    go and stomp on the garbage sender... */
 604                 printk("UDP: bad checksum. From %08lX:%d to %08lX:%d ulen %d\n",
 605                        ntohl(saddr),ntohs(uh->source),
 606                        ntohl(daddr),ntohs(uh->dest),
 607                        ulen);
 608                 udp_statistics.UdpInErrors++;
 609                 kfree_skb(skb, FREE_WRITE);
 610                 return(0);
 611         }
 612 
 613 
 614         len=ulen;
 615 
 616 #ifdef CONFIG_IP_MULTICAST
 617         if (addr_type!=IS_MYADDR)
 618         {
 619                 /*
 620                  *      Multicasts and broadcasts go to each listener.
 621                  */
 622                 struct sock *sknext=NULL;
 623                 sk=get_sock_mcast(udp_prot.sock_array[ntohs(uh->dest)&(SOCK_ARRAY_SIZE-1)], uh->dest,
 624                                 saddr, uh->source, daddr);
 625                 if(sk)
 626                 {               
 627                         do
 628                         {
 629                                 struct sk_buff *skb1;
 630 
 631                                 sknext=get_sock_mcast(sk->next, uh->dest, saddr, uh->source, daddr);
 632                                 if(sknext)
 633                                         skb1=skb_clone(skb,GFP_ATOMIC);
 634                                 else
 635                                         skb1=skb;
 636                                 if(skb1)
 637                                         udp_deliver(sk, uh, skb1, dev,saddr,daddr,len);
 638                                 sk=sknext;
 639                         }
 640                         while(sknext!=NULL);
 641                 }
 642                 else
 643                         kfree_skb(skb, FREE_READ);
 644                 return 0;
 645         }       
 646 #endif
 647         sk = get_sock(&udp_prot, uh->dest, saddr, uh->source, daddr);
 648         if (sk == NULL) 
 649         {
 650                 udp_statistics.UdpNoPorts++;
 651                 if (addr_type == IS_MYADDR) 
 652                 {
 653                         icmp_send(skb, ICMP_DEST_UNREACH, ICMP_PORT_UNREACH, 0, dev);
 654                 }
 655                 /*
 656                  * Hmm.  We got an UDP broadcast to a port to which we
 657                  * don't wanna listen.  Ignore it.
 658                  */
 659                 skb->sk = NULL;
 660                 kfree_skb(skb, FREE_WRITE);
 661                 return(0);
 662         }
 663 
 664         return udp_deliver(sk,uh,skb,dev, saddr, daddr, len);
 665 }
 666 
 667 static int udp_deliver(struct sock *sk, struct udphdr *uh, struct sk_buff *skb, struct device *dev, long saddr, long daddr, int len)
     /* [previous][next][first][last][top][bottom][index][help] */
 668 {
 669         skb->sk = sk;
 670         skb->dev = dev;
 671         skb->len = len;
 672 
 673         /*
 674          *      These are supposed to be switched. 
 675          */
 676          
 677         skb->daddr = saddr;
 678         skb->saddr = daddr;
 679 
 680 
 681         /*
 682          *      Charge it to the socket, dropping if the queue is full.
 683          */
 684 
 685         skb->len = len - sizeof(*uh);  
 686          
 687         if (sock_queue_rcv_skb(sk,skb)<0) 
 688         {
 689                 udp_statistics.UdpInErrors++;
 690                 ip_statistics.IpInDiscards++;
 691                 ip_statistics.IpInDelivers--;
 692                 skb->sk = NULL;
 693                 kfree_skb(skb, FREE_WRITE);
 694                 release_sock(sk);
 695                 return(0);
 696         }
 697         udp_statistics.UdpInDatagrams++;
 698         release_sock(sk);
 699         return(0);
 700 }
 701 
 702 
 703 struct proto udp_prot = {
 704         sock_wmalloc,
 705         sock_rmalloc,
 706         sock_wfree,
 707         sock_rfree,
 708         sock_rspace,
 709         sock_wspace,
 710         udp_close,
 711         udp_read,
 712         udp_write,
 713         udp_sendto,
 714         udp_recvfrom,
 715         ip_build_header,
 716         udp_connect,
 717         NULL,
 718         ip_queue_xmit,
 719         NULL,
 720         NULL,
 721         NULL,
 722         udp_rcv,
 723         datagram_select,
 724         udp_ioctl,
 725         NULL,
 726         NULL,
 727         ip_setsockopt,
 728         ip_getsockopt,
 729         128,
 730         0,
 731         {NULL,},
 732         "UDP",
 733         0, 0
 734 };
 735 

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