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

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