root/net/ipv4/udp.c

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

DEFINITIONS

This source file includes following definitions.
  1. udp_cache_zap
  2. udp_err
  3. udp_check
  4. udp_getfrag
  5. udp_getfrag_nosum
  6. udp_send
  7. udp_sendto
  8. udp_write
  9. udp_ioctl
  10. udp_recvfrom
  11. udp_read
  12. udp_connect
  13. udp_close
  14. udp_rcv
  15. 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  *              Arnt Gulbrandsen, <agulbra@nvg.unit.no>
  13  *              Alan Cox, <Alan.Cox@linux.org>
  14  *
  15  * Fixes:
  16  *              Alan Cox        :       verify_area() calls
  17  *              Alan Cox        :       stopped close while in use off icmp
  18  *                                      messages. Not a fix but a botch that
  19  *                                      for udp at least is 'valid'.
  20  *              Alan Cox        :       Fixed icmp handling properly
  21  *              Alan Cox        :       Correct error for oversized datagrams
  22  *              Alan Cox        :       Tidied select() semantics. 
  23  *              Alan Cox        :       udp_err() fixed properly, also now 
  24  *                                      select and read wake correctly on errors
  25  *              Alan Cox        :       udp_send verify_area moved to avoid mem leak
  26  *              Alan Cox        :       UDP can count its memory
  27  *              Alan Cox        :       send to an unknown connection causes
  28  *                                      an ECONNREFUSED off the icmp, but
  29  *                                      does NOT close.
  30  *              Alan Cox        :       Switched to new sk_buff handlers. No more backlog!
  31  *              Alan Cox        :       Using generic datagram code. Even smaller and the PEEK
  32  *                                      bug no longer crashes it.
  33  *              Fred Van Kempen :       Net2e support for sk->broadcast.
  34  *              Alan Cox        :       Uses skb_free_datagram
  35  *              Alan Cox        :       Added get/set sockopt support.
  36  *              Alan Cox        :       Broadcasting without option set returns EACCES.
  37  *              Alan Cox        :       No wakeup calls. Instead we now use the callbacks.
  38  *              Alan Cox        :       Use ip_tos and ip_ttl
  39  *              Alan Cox        :       SNMP Mibs
  40  *              Alan Cox        :       MSG_DONTROUTE, and 0.0.0.0 support.
  41  *              Matt Dillon     :       UDP length checks.
  42  *              Alan Cox        :       Smarter af_inet used properly.
  43  *              Alan Cox        :       Use new kernel side addressing.
  44  *              Alan Cox        :       Incorrect return on truncated datagram receive.
  45  *      Arnt Gulbrandsen        :       New udp_send and stuff
  46  *              Alan Cox        :       Cache last socket
  47  *              Alan Cox        :       Route cache
  48  *              Jon Peatfield   :       Minor efficientcy fix to sendto().
  49  *              Mike Shaver     :       RFC1122 checks.
  50  *
  51  *
  52  *              This program is free software; you can redistribute it and/or
  53  *              modify it under the terms of the GNU General Public License
  54  *              as published by the Free Software Foundation; either version
  55  *              2 of the License, or (at your option) any later version.
  56  */
  57  
  58 /* RFC1122 Status:
  59    4.1.3.1 (Ports):
  60      SHOULD send ICMP_PORT_UNREACHABLE in reponse to datagrams to 
  61        an un-listened port. (OK)
  62    4.1.3.2 (IP Options)
  63      MUST pass IP options from IP -> application (OK)
  64      MUST allow application to specify IP options (OK)
  65    4.1.3.3 (ICMP Messages)
  66      MUST pass ICMP error messages to application (OK)
  67    4.1.3.4 (UDP Checksums)
  68      MUST provide facility for checksumming (OK)
  69      MAY allow application to control checksumming (OK)
  70      MUST default to checksumming on (OK)
  71      MUST discard silently datagrams with bad csums (OK)
  72    4.1.3.5 (UDP Multihoming)
  73      MUST allow application to specify source address (OK)
  74      SHOULD be able to communicate the chosen src addr up to application
  75        when application doesn't choose (NOT YET - doesnt seem to be in the BSD API)
  76        [Does opening a SOCK_PACKET and snooping your output count 8)]
  77    4.1.3.6 (Invalid Addresses)
  78      MUST discard invalid source addresses (NOT YET -- will be implemented
  79        in IP, so UDP will eventually be OK.  Right now it's a violation.)
  80      MUST only send datagrams with one of our addresses (NOT YET - ought to be OK )
  81    950728 -- MS
  82 */
  83 
  84 #include <asm/system.h>
  85 #include <asm/segment.h>
  86 #include <linux/types.h>
  87 #include <linux/sched.h>
  88 #include <linux/fcntl.h>
  89 #include <linux/socket.h>
  90 #include <linux/sockios.h>
  91 #include <linux/in.h>
  92 #include <linux/errno.h>
  93 #include <linux/timer.h>
  94 #include <linux/termios.h>
  95 #include <linux/mm.h>
  96 #include <linux/config.h>
  97 #include <linux/inet.h>
  98 #include <linux/netdevice.h>
  99 #include <net/snmp.h>
 100 #include <net/ip.h>
 101 #include <net/protocol.h>
 102 #include <net/tcp.h>
 103 #include <linux/skbuff.h>
 104 #include <net/sock.h>
 105 #include <net/udp.h>
 106 #include <net/icmp.h>
 107 #include <net/route.h>
 108 #include <net/checksum.h>
 109 
 110 /*
 111  *      Snmp MIB for the UDP layer
 112  */
 113 
 114 struct udp_mib          udp_statistics;
 115 
 116 /*
 117  *      Cached last hit socket
 118  */
 119  
 120 volatile unsigned long  uh_cache_saddr,uh_cache_daddr;
 121 volatile unsigned short  uh_cache_dport, uh_cache_sport;
 122 volatile struct sock *uh_cache_sk;
 123 
 124 void udp_cache_zap(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 125 {
 126         unsigned long flags;
 127         save_flags(flags);
 128         cli();
 129         uh_cache_saddr=0;
 130         uh_cache_daddr=0;
 131         uh_cache_dport=0;
 132         uh_cache_sport=0;
 133         uh_cache_sk=NULL;
 134         restore_flags(flags);
 135 }
 136 
 137 static int udp_deliver(struct sock *sk, struct udphdr *uh, struct sk_buff *skb, struct device *dev, long saddr, long daddr, int len);
 138 
 139 #define min(a,b)        ((a)<(b)?(a):(b))
 140 
 141 
 142 /*
 143  * This routine is called by the ICMP module when it gets some
 144  * sort of error condition.  If err < 0 then the socket should
 145  * be closed and the error returned to the user.  If err > 0
 146  * it's just the icmp type << 8 | icmp code.  
 147  * Header points to the ip header of the error packet. We move
 148  * on past this. Then (as it used to claim before adjustment)
 149  * header points to the first 8 bytes of the udp header.  We need
 150  * to find the appropriate port.
 151  */
 152 
 153 void udp_err(int err, unsigned char *header, unsigned long daddr,
     /* [previous][next][first][last][top][bottom][index][help] */
 154         unsigned long saddr, struct inet_protocol *protocol)
 155 {
 156         struct udphdr *th;
 157         struct sock *sk;
 158         struct iphdr *ip=(struct iphdr *)header;
 159   
 160         header += 4*ip->ihl;
 161 
 162         /*
 163          *      Find the 8 bytes of post IP header ICMP included for us
 164          */  
 165         
 166         th = (struct udphdr *)header;  
 167    
 168         sk = get_sock(&udp_prot, th->source, daddr, th->dest, saddr);
 169 
 170         if (sk == NULL) 
 171                 return; /* No socket for error */
 172         
 173         if ((err & 0xff00) == (ICMP_SOURCE_QUENCH << 8)) 
 174         {       /* Slow down! */
 175                 if (sk->cong_window > 1) 
 176                         sk->cong_window = sk->cong_window/2;
 177                 return;
 178         }
 179 
 180         /*
 181          *      Various people wanted BSD UDP semantics. Well they've come 
 182          *      back out because they slow down response to stuff like dead
 183          *      or unreachable name servers and they screw term users something
 184          *      chronic. Oh and it violates RFC1122. So basically fix your 
 185          *      client code people.
 186          */
 187          
 188         /* RFC1122: OK.  Passes ICMP errors back to application, as per */
 189         /* 4.1.3.3. */
 190         /* After the comment above, that should be no surprise. */
 191 
 192         if (icmp_err_convert[err & 0xff].fatal)
 193         {
 194                 sk->err = icmp_err_convert[err & 0xff].errno;
 195                 sk->error_report(sk);
 196         }
 197 }
 198 
 199 
 200 static unsigned short udp_check(struct udphdr *uh, int len, unsigned long saddr, unsigned long daddr, unsigned long base)
     /* [previous][next][first][last][top][bottom][index][help] */
 201 {
 202         return(csum_tcpudp_magic(saddr, daddr, len, IPPROTO_UDP, base));
 203 }
 204 
 205 struct udpfakehdr 
 206 {
 207         struct udphdr uh;
 208         int daddr;
 209         int other;
 210         const char *from;
 211         int wcheck;
 212 };
 213 
 214 /*
 215  *      Copy and checksum a UDP packet from user space into a buffer. We still have to do the planning to
 216  *      get ip_build_xmit to spot direct transfer to network card and provide an additional callback mode
 217  *      for direct user->board I/O transfers. That one will be fun.
 218  */
 219  
 220 static void udp_getfrag(const void *p, int saddr, char * to, unsigned int offset, unsigned int fraglen) 
     /* [previous][next][first][last][top][bottom][index][help] */
 221 {
 222         struct udpfakehdr *ufh = (struct udpfakehdr *)p;
 223         const char *src;
 224         char *dst;
 225         unsigned int len;
 226 
 227         if (offset) 
 228         {
 229                 len = fraglen;
 230                 src = ufh->from+(offset-sizeof(struct udphdr));
 231                 dst = to;
 232         }
 233         else 
 234         {
 235                 len = fraglen-sizeof(struct udphdr);
 236                 src = ufh->from;
 237                 dst = to+sizeof(struct udphdr);
 238         }
 239         ufh->wcheck = csum_partial_copy_fromuser(src, dst, len, ufh->wcheck);
 240         if (offset == 0) 
 241         {
 242                 ufh->wcheck = csum_partial((char *)ufh, sizeof(struct udphdr),
 243                                    ufh->wcheck);
 244                 ufh->uh.check = csum_tcpudp_magic(saddr, ufh->daddr, 
 245                                           ntohs(ufh->uh.len),
 246                                           IPPROTO_UDP, ufh->wcheck);
 247                 if (ufh->uh.check == 0)
 248                         ufh->uh.check = -1;
 249                 memcpy(to, ufh, sizeof(struct udphdr));
 250         }
 251 }
 252 
 253 /*
 254  *      Uncheckummed UDP is sufficiently criticial to stuff like ATM video conferencing
 255  *      that we use two routines for this for speed. Probably we ought to have a CONFIG_FAST_NET
 256  *      set for >10Mb/second boards to activate this sort of coding. Timing needed to verify if
 257  *      this is a valid decision.
 258  */
 259  
 260 static void udp_getfrag_nosum(const void *p, int saddr, char * to, unsigned int offset, unsigned int fraglen) 
     /* [previous][next][first][last][top][bottom][index][help] */
 261 {
 262         struct udpfakehdr *ufh = (struct udpfakehdr *)p;
 263         const char *src;
 264         char *dst;
 265         unsigned int len;
 266 
 267         if (offset) 
 268         {
 269                 len = fraglen;
 270                 src = ufh->from+(offset-sizeof(struct udphdr));
 271                 dst = to;
 272         }
 273         else 
 274         {
 275                 len = fraglen-sizeof(struct udphdr);
 276                 src = ufh->from;
 277                 dst = to+sizeof(struct udphdr);
 278         }
 279         memcpy_fromfs(dst,src,len);
 280         if (offset == 0) 
 281                 memcpy(to, ufh, sizeof(struct udphdr));
 282 }
 283 
 284 
 285 /*
 286  *      Send UDP frames.
 287  */
 288  
 289 static int udp_send(struct sock *sk, struct sockaddr_in *sin,
     /* [previous][next][first][last][top][bottom][index][help] */
 290                       const unsigned char *from, int len, int rt) 
 291 {
 292         int ulen = len + sizeof(struct udphdr);
 293         int a;
 294         struct udpfakehdr ufh;
 295 
 296         ufh.uh.source = sk->dummy_th.source;
 297         ufh.uh.dest = sin->sin_port;
 298         ufh.uh.len = htons(ulen);
 299         ufh.uh.check = 0;
 300         ufh.daddr = sin->sin_addr.s_addr;
 301         ufh.other = (htons(ulen) << 16) + IPPROTO_UDP*256;
 302         ufh.from = from;
 303         ufh.wcheck = 0;
 304 
 305         /* RFC1122 Violation: there is no provision for passing IP options */
 306         /* from the application layer to the IP one.  It's a MUST (4.1.3.2), */
 307         /* but it looks like it'd require some work on ip_build_xmit. */
 308         /* Alan says he's got a Cunning Plan. -- MS */
 309 
 310         /* RFC1122: OK.  Provides the checksumming facility (MUST) as per */
 311         /* 4.1.3.4. It's configurable by the application via setsockopt() */
 312         /* (MAY) and it defaults to on (MUST).  Almost makes up for the */
 313         /* violation above. -- MS */
 314 
 315         if(sk->no_check)
 316                 a = ip_build_xmit(sk, udp_getfrag_nosum, &ufh, ulen, 
 317                         sin->sin_addr.s_addr, rt, IPPROTO_UDP);
 318         else
 319                 a = ip_build_xmit(sk, udp_getfrag, &ufh, ulen, 
 320                         sin->sin_addr.s_addr, rt, IPPROTO_UDP);
 321         if(a<0)
 322                 return a;
 323         udp_statistics.UdpOutDatagrams++;
 324         return len;
 325 }
 326 
 327 
 328 static int udp_sendto(struct sock *sk, const unsigned char *from, int len, int noblock,
     /* [previous][next][first][last][top][bottom][index][help] */
 329            unsigned flags, struct sockaddr_in *usin, int addr_len)
 330 {
 331         struct sockaddr_in sin;
 332         int tmp;
 333 
 334         /* 
 335          *      Check the flags. We support no flags for UDP sending
 336          */
 337         if (flags&~MSG_DONTROUTE) 
 338                 return(-EINVAL);
 339         /*
 340          *      Get and verify the address. 
 341          */
 342          
 343         if (usin) 
 344         {
 345                 if (addr_len < sizeof(sin)) 
 346                         return(-EINVAL);
 347                 if (usin->sin_family && usin->sin_family != AF_INET) 
 348                         return(-EINVAL);
 349                 if (usin->sin_port == 0) 
 350                         return(-EINVAL);
 351         } 
 352         else 
 353         {
 354                 if (sk->state != TCP_ESTABLISHED) 
 355                         return(-EINVAL);
 356                 sin.sin_family = AF_INET;
 357                 sin.sin_port = sk->dummy_th.dest;
 358                 sin.sin_addr.s_addr = sk->daddr;
 359                 usin = &sin;
 360         }
 361   
 362         /*
 363          *      BSD socket semantics. You must set SO_BROADCAST to permit
 364          *      broadcasting of data.
 365          */
 366          
 367         /* RFC1122: OK.  Allows the application to select the specific */
 368         /* source address for an outgoing packet (MUST) as per 4.1.3.5. */
 369         /* Optional addition: a mechanism for telling the application what */
 370         /* address was used. (4.1.3.5, MAY) -- MS */
 371 
 372         /* RFC1122: MUST ensure that all outgoing packets have one */
 373         /* of this host's addresses as a source addr.(4.1.3.6) - bind in  */
 374         /* af_inet.c checks these. It does need work to allow BSD style */
 375         /* bind to multicast as is done by xntpd                */
 376 
 377         if(usin->sin_addr.s_addr==INADDR_ANY)
 378                 usin->sin_addr.s_addr=ip_my_addr();
 379                 
 380         if(!sk->broadcast && ip_chk_addr(usin->sin_addr.s_addr)==IS_BROADCAST)
 381                 return -EACCES;                 /* Must turn broadcast on first */
 382 
 383         sk->inuse = 1;
 384 
 385         /* Send the packet. */
 386         tmp = udp_send(sk, usin, from, len, flags);
 387 
 388         /* The datagram has been sent off.  Release the socket. */
 389         release_sock(sk);
 390         return(tmp);
 391 }
 392 
 393 /*
 394  *      In BSD SOCK_DGRAM a write is just like a send.
 395  */
 396 
 397 static int udp_write(struct sock *sk, const unsigned char *buff, int len, int noblock,
     /* [previous][next][first][last][top][bottom][index][help] */
 398           unsigned flags)
 399 {
 400         return(udp_sendto(sk, buff, len, noblock, flags, NULL, 0));
 401 }
 402 
 403 
 404 /*
 405  *      IOCTL requests applicable to the UDP protocol
 406  */
 407  
 408 int udp_ioctl(struct sock *sk, int cmd, unsigned long arg)
     /* [previous][next][first][last][top][bottom][index][help] */
 409 {
 410         int err;
 411         switch(cmd) 
 412         {
 413                 case TIOCOUTQ:
 414                 {
 415                         unsigned long amount;
 416 
 417                         if (sk->state == TCP_LISTEN) return(-EINVAL);
 418                         amount = sk->prot->wspace(sk)/*/2*/;
 419                         err=verify_area(VERIFY_WRITE,(void *)arg,
 420                                         sizeof(unsigned long));
 421                         if(err)
 422                                 return(err);
 423                         put_fs_long(amount,(unsigned long *)arg);
 424                         return(0);
 425                 }
 426 
 427                 case TIOCINQ:
 428                 {
 429                         struct sk_buff *skb;
 430                         unsigned long amount;
 431 
 432                         if (sk->state == TCP_LISTEN) return(-EINVAL);
 433                         amount = 0;
 434                         skb = skb_peek(&sk->receive_queue);
 435                         if (skb != NULL) {
 436                                 /*
 437                                  * We will only return the amount
 438                                  * of this packet since that is all
 439                                  * that will be read.
 440                                  */
 441                                 amount = skb->len;
 442                         }
 443                         err=verify_area(VERIFY_WRITE,(void *)arg,
 444                                                 sizeof(unsigned long));
 445                         if(err)
 446                                 return(err);
 447                         put_fs_long(amount,(unsigned long *)arg);
 448                         return(0);
 449                 }
 450 
 451                 default:
 452                         return(-EINVAL);
 453         }
 454         return(0);
 455 }
 456 
 457 
 458 /*
 459  *      This should be easy, if there is something there we\
 460  *      return it, otherwise we block.
 461  */
 462 
 463 int udp_recvfrom(struct sock *sk, unsigned char *to, int len,
     /* [previous][next][first][last][top][bottom][index][help] */
 464              int noblock, unsigned flags, struct sockaddr_in *sin,
 465              int *addr_len)
 466 {
 467         int copied = 0;
 468         int truesize;
 469         struct sk_buff *skb;
 470         int er;
 471 
 472         /*
 473          *      Check any passed addresses
 474          */
 475          
 476         if (addr_len) 
 477                 *addr_len=sizeof(*sin);
 478   
 479         /*
 480          *      From here the generic datagram does a lot of the work. Come
 481          *      the finished NET3, it will do _ALL_ the work!
 482          */
 483                 
 484         skb=skb_recv_datagram(sk,flags,noblock,&er);
 485         if(skb==NULL)
 486                 return er;
 487   
 488         truesize = skb->len - sizeof(struct udphdr);
 489         copied = min(len, truesize);
 490 
 491         /*
 492          *      FIXME : should use udp header size info value 
 493          */
 494          
 495         skb_copy_datagram(skb,sizeof(struct udphdr),to,copied);
 496         sk->stamp=skb->stamp;
 497 
 498         /* Copy the address. */
 499         if (sin) 
 500         {
 501                 sin->sin_family = AF_INET;
 502                 sin->sin_port = skb->h.uh->source;
 503                 sin->sin_addr.s_addr = skb->daddr;
 504         }
 505   
 506         skb_free_datagram(skb);
 507         release_sock(sk);
 508         return(copied);
 509 }
 510 
 511 /*
 512  *      Read has the same semantics as recv in SOCK_DGRAM
 513  */
 514 
 515 int udp_read(struct sock *sk, unsigned char *buff, int len, int noblock,
     /* [previous][next][first][last][top][bottom][index][help] */
 516          unsigned flags)
 517 {
 518         return(udp_recvfrom(sk, buff, len, noblock, flags, NULL, NULL));
 519 }
 520 
 521 
 522 int udp_connect(struct sock *sk, struct sockaddr_in *usin, int addr_len)
     /* [previous][next][first][last][top][bottom][index][help] */
 523 {
 524         struct rtable *rt;
 525         unsigned long sa;
 526         if (addr_len < sizeof(*usin)) 
 527                 return(-EINVAL);
 528 
 529         if (usin->sin_family && usin->sin_family != AF_INET) 
 530                 return(-EAFNOSUPPORT);
 531         if (usin->sin_addr.s_addr==INADDR_ANY)
 532                 usin->sin_addr.s_addr=ip_my_addr();
 533 
 534         if(!sk->broadcast && ip_chk_addr(usin->sin_addr.s_addr)==IS_BROADCAST)
 535                 return -EACCES;                 /* Must turn broadcast on first */
 536         
 537         rt=(sk->localroute?ip_rt_local:ip_rt_route)(usin->sin_addr.s_addr, NULL, &sa);
 538         if(rt==NULL)
 539                 return -ENETUNREACH;
 540         sk->saddr = sa;         /* Update source address */
 541         sk->daddr = usin->sin_addr.s_addr;
 542         sk->dummy_th.dest = usin->sin_port;
 543         sk->state = TCP_ESTABLISHED;
 544         udp_cache_zap();
 545         sk->ip_route_cache = rt;
 546         sk->ip_route_stamp = rt_stamp;
 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(uh_cache_sk==sk)
 556                 udp_cache_zap();
 557         if (sk->dead) 
 558                 destroy_sock(sk);
 559         else
 560                 release_sock(sk);
 561 }
 562 
 563 
 564 /*
 565  *      All we need to do is get the socket, and then do a checksum. 
 566  */
 567  
 568 int udp_rcv(struct sk_buff *skb, struct device *dev, struct options *opt,
     /* [previous][next][first][last][top][bottom][index][help] */
 569         unsigned long daddr, unsigned short len,
 570         unsigned long saddr, int redo, struct inet_protocol *protocol)
 571 {
 572         struct sock *sk;
 573         struct udphdr *uh;
 574         unsigned short ulen;
 575         int addr_type = IS_MYADDR;
 576         
 577         if(!dev || dev->pa_addr!=daddr)
 578                 addr_type=ip_chk_addr(daddr);
 579                 
 580         /*
 581          *      Get the header.
 582          */
 583          
 584         uh = (struct udphdr *) skb->h.uh;
 585         
 586         ip_statistics.IpInDelivers++;
 587 
 588         /*
 589          *      Validate the packet and the UDP length.
 590          */
 591          
 592         ulen = ntohs(uh->len);
 593         
 594         if (ulen > len || len < sizeof(*uh) || ulen < sizeof(*uh)) 
 595         {
 596                 NETDEBUG(printk("UDP: short packet: %d/%d\n", ulen, len));
 597                 udp_statistics.UdpInErrors++;
 598                 kfree_skb(skb, FREE_WRITE);
 599                 return(0);
 600         }
 601 
 602         /* RFC1122 warning: According to 4.1.3.6, we MUST discard any */
 603         /* datagram which has an invalid source address, either here or */
 604         /* in IP. */
 605         /* Right now, IP isn't doing it, and neither is UDP. It's on the */
 606         /* FIXME list for IP, though, so I wouldn't worry about it. */
 607         /* (That's the Right Place to do it, IMHO.) -- MS */
 608 
 609         if (uh->check && (
 610                 ( skb->ip_summed && udp_check(uh, len, saddr, daddr, skb->csum ) ) ||
 611                 ( !skb->ip_summed && udp_check(uh, len, saddr, daddr,csum_partial((char*)uh, len, 0)))
 612                          )
 613            )
 614         {
 615                 /* <mea@utu.fi> wants to know, who sent it, to
 616                    go and stomp on the garbage sender... */
 617 
 618           /* RFC1122: OK.  Discards the bad packet silently (as far as */
 619           /* the network is concered, anyway) as per 4.1.3.4 (MUST). */
 620 
 621                 NETDEBUG(printk("UDP: bad checksum. From %08lX:%d to %08lX:%d ulen %d\n",
 622                        ntohl(saddr),ntohs(uh->source),
 623                        ntohl(daddr),ntohs(uh->dest),
 624                        ulen));
 625                 udp_statistics.UdpInErrors++;
 626                 kfree_skb(skb, FREE_WRITE);
 627                 return(0);
 628         }
 629 
 630 
 631         len=ulen;
 632 
 633 #ifdef CONFIG_IP_MULTICAST
 634         if (addr_type!=IS_MYADDR)
 635         {
 636                 /*
 637                  *      Multicasts and broadcasts go to each listener.
 638                  */
 639                 struct sock *sknext=NULL;
 640                 sk=get_sock_mcast(udp_prot.sock_array[ntohs(uh->dest)&(SOCK_ARRAY_SIZE-1)], uh->dest,
 641                                 saddr, uh->source, daddr);
 642                 if(sk)
 643                 {               
 644                         do
 645                         {
 646                                 struct sk_buff *skb1;
 647 
 648                                 sknext=get_sock_mcast(sk->next, uh->dest, saddr, uh->source, daddr);
 649                                 if(sknext)
 650                                         skb1=skb_clone(skb,GFP_ATOMIC);
 651                                 else
 652                                         skb1=skb;
 653                                 if(skb1)
 654                                         udp_deliver(sk, uh, skb1, dev,saddr,daddr,len);
 655                                 sk=sknext;
 656                         }
 657                         while(sknext!=NULL);
 658                 }
 659                 else
 660                         kfree_skb(skb, FREE_READ);
 661                 return 0;
 662         }       
 663 #endif
 664         if(saddr==uh_cache_saddr && daddr==uh_cache_daddr && uh->dest==uh_cache_dport && uh->source==uh_cache_sport)
 665                 sk=(struct sock *)uh_cache_sk;
 666         else
 667         {
 668                 sk = get_sock(&udp_prot, uh->dest, saddr, uh->source, daddr);
 669                 uh_cache_saddr=saddr;
 670                 uh_cache_daddr=daddr;
 671                 uh_cache_dport=uh->dest;
 672                 uh_cache_sport=uh->source;
 673                 uh_cache_sk=sk;
 674         }
 675         
 676         if (sk == NULL) 
 677         {
 678                 udp_statistics.UdpNoPorts++;
 679                 if (addr_type == IS_MYADDR) 
 680                 {
 681                         icmp_send(skb, ICMP_DEST_UNREACH, ICMP_PORT_UNREACH, 0, dev);
 682                 }
 683                 /*
 684                  * Hmm.  We got an UDP broadcast to a port to which we
 685                  * don't wanna listen.  Ignore it.
 686                  */
 687                 skb->sk = NULL;
 688                 kfree_skb(skb, FREE_WRITE);
 689                 return(0);
 690         }
 691         return udp_deliver(sk,uh,skb,dev, saddr, daddr, len);
 692 }
 693 
 694 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] */
 695 {
 696         skb->sk = sk;
 697         skb->dev = dev;
 698         skb_trim(skb,len);
 699 
 700         /*
 701          *      These are supposed to be switched. 
 702          */
 703          
 704         skb->daddr = saddr;
 705         skb->saddr = daddr;
 706 
 707 
 708         /*
 709          *      Charge it to the socket, dropping if the queue is full.
 710          */
 711 
 712         /* I assume this includes the IP options, as per RFC1122 (4.1.3.2). */
 713         /* If not, please let me know. -- MS */
 714 
 715         if (sock_queue_rcv_skb(sk,skb)<0) 
 716         {
 717                 udp_statistics.UdpInErrors++;
 718                 ip_statistics.IpInDiscards++;
 719                 ip_statistics.IpInDelivers--;
 720                 skb->sk = NULL;
 721                 kfree_skb(skb, FREE_WRITE);
 722                 release_sock(sk);
 723                 return(0);
 724         }
 725         udp_statistics.UdpInDatagrams++;
 726         release_sock(sk);
 727         return(0);
 728 }
 729 
 730 
 731 struct proto udp_prot = {
 732         sock_wmalloc,
 733         sock_rmalloc,
 734         sock_wfree,
 735         sock_rfree,
 736         sock_rspace,
 737         sock_wspace,
 738         udp_close,
 739         udp_read,
 740         udp_write,
 741         udp_sendto,
 742         udp_recvfrom,
 743         ip_build_header,
 744         udp_connect,
 745         NULL,
 746         ip_queue_xmit,
 747         NULL,
 748         NULL,
 749         NULL,
 750         udp_rcv,
 751         datagram_select,
 752         udp_ioctl,
 753         NULL,
 754         NULL,
 755         ip_setsockopt,
 756         ip_getsockopt,
 757         128,
 758         0,
 759         "UDP",
 760         0, 0,
 761         {NULL,}
 762 };

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