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         err &= 0xff;
 193         if (err < 13 && icmp_err_convert[err].fatal)
 194         {
 195                 sk->err = icmp_err_convert[err].errno;
 196                 sk->error_report(sk);
 197         }
 198 }
 199 
 200 
 201 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] */
 202 {
 203         return(csum_tcpudp_magic(saddr, daddr, len, IPPROTO_UDP, base));
 204 }
 205 
 206 struct udpfakehdr 
 207 {
 208         struct udphdr uh;
 209         int daddr;
 210         int other;
 211         const char *from;
 212         int wcheck;
 213 };
 214 
 215 /*
 216  *      Copy and checksum a UDP packet from user space into a buffer. We still have to do the planning to
 217  *      get ip_build_xmit to spot direct transfer to network card and provide an additional callback mode
 218  *      for direct user->board I/O transfers. That one will be fun.
 219  */
 220  
 221 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] */
 222 {
 223         struct udpfakehdr *ufh = (struct udpfakehdr *)p;
 224         const char *src;
 225         char *dst;
 226         unsigned int len;
 227 
 228         if (offset) 
 229         {
 230                 len = fraglen;
 231                 src = ufh->from+(offset-sizeof(struct udphdr));
 232                 dst = to;
 233         }
 234         else 
 235         {
 236                 len = fraglen-sizeof(struct udphdr);
 237                 src = ufh->from;
 238                 dst = to+sizeof(struct udphdr);
 239         }
 240         ufh->wcheck = csum_partial_copy_fromuser(src, dst, len, ufh->wcheck);
 241         if (offset == 0) 
 242         {
 243                 ufh->wcheck = csum_partial((char *)ufh, sizeof(struct udphdr),
 244                                    ufh->wcheck);
 245                 ufh->uh.check = csum_tcpudp_magic(saddr, ufh->daddr, 
 246                                           ntohs(ufh->uh.len),
 247                                           IPPROTO_UDP, ufh->wcheck);
 248                 if (ufh->uh.check == 0)
 249                         ufh->uh.check = -1;
 250                 memcpy(to, ufh, sizeof(struct udphdr));
 251         }
 252 }
 253 
 254 /*
 255  *      Uncheckummed UDP is sufficiently criticial to stuff like ATM video conferencing
 256  *      that we use two routines for this for speed. Probably we ought to have a CONFIG_FAST_NET
 257  *      set for >10Mb/second boards to activate this sort of coding. Timing needed to verify if
 258  *      this is a valid decision.
 259  */
 260  
 261 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] */
 262 {
 263         struct udpfakehdr *ufh = (struct udpfakehdr *)p;
 264         const char *src;
 265         char *dst;
 266         unsigned int len;
 267 
 268         if (offset) 
 269         {
 270                 len = fraglen;
 271                 src = ufh->from+(offset-sizeof(struct udphdr));
 272                 dst = to;
 273         }
 274         else 
 275         {
 276                 len = fraglen-sizeof(struct udphdr);
 277                 src = ufh->from;
 278                 dst = to+sizeof(struct udphdr);
 279         }
 280         memcpy_fromfs(dst,src,len);
 281         if (offset == 0) 
 282                 memcpy(to, ufh, sizeof(struct udphdr));
 283 }
 284 
 285 
 286 /*
 287  *      Send UDP frames.
 288  */
 289  
 290 static int udp_send(struct sock *sk, struct sockaddr_in *sin,
     /* [previous][next][first][last][top][bottom][index][help] */
 291                       const unsigned char *from, int len, int rt) 
 292 {
 293         int ulen = len + sizeof(struct udphdr);
 294         int a;
 295         struct udpfakehdr ufh;
 296 
 297         ufh.uh.source = sk->dummy_th.source;
 298         ufh.uh.dest = sin->sin_port;
 299         ufh.uh.len = htons(ulen);
 300         ufh.uh.check = 0;
 301         ufh.daddr = sin->sin_addr.s_addr;
 302         ufh.other = (htons(ulen) << 16) + IPPROTO_UDP*256;
 303         ufh.from = from;
 304         ufh.wcheck = 0;
 305 
 306         /* RFC1122 Violation: there is no provision for passing IP options */
 307         /* from the application layer to the IP one.  It's a MUST (4.1.3.2), */
 308         /* but it looks like it'd require some work on ip_build_xmit. */
 309         /* Alan says he's got a Cunning Plan. -- MS */
 310 
 311         /* RFC1122: OK.  Provides the checksumming facility (MUST) as per */
 312         /* 4.1.3.4. It's configurable by the application via setsockopt() */
 313         /* (MAY) and it defaults to on (MUST).  Almost makes up for the */
 314         /* violation above. -- MS */
 315 
 316         if(sk->no_check)
 317                 a = ip_build_xmit(sk, udp_getfrag_nosum, &ufh, ulen, 
 318                         sin->sin_addr.s_addr, rt, IPPROTO_UDP);
 319         else
 320                 a = ip_build_xmit(sk, udp_getfrag, &ufh, ulen, 
 321                         sin->sin_addr.s_addr, rt, IPPROTO_UDP);
 322         if(a<0)
 323                 return a;
 324         udp_statistics.UdpOutDatagrams++;
 325         return len;
 326 }
 327 
 328 
 329 static int udp_sendto(struct sock *sk, const unsigned char *from, int len, int noblock,
     /* [previous][next][first][last][top][bottom][index][help] */
 330            unsigned flags, struct sockaddr_in *usin, int addr_len)
 331 {
 332         struct sockaddr_in sin;
 333         int tmp;
 334 
 335         /* 
 336          *      Check the flags. We support no flags for UDP sending
 337          */
 338         if (flags&~MSG_DONTROUTE) 
 339                 return(-EINVAL);
 340         /*
 341          *      Get and verify the address. 
 342          */
 343          
 344         if (usin) 
 345         {
 346                 if (addr_len < sizeof(sin)) 
 347                         return(-EINVAL);
 348                 if (usin->sin_family && usin->sin_family != AF_INET) 
 349                         return(-EINVAL);
 350                 if (usin->sin_port == 0) 
 351                         return(-EINVAL);
 352         } 
 353         else 
 354         {
 355                 if (sk->state != TCP_ESTABLISHED) 
 356                         return(-EINVAL);
 357                 sin.sin_family = AF_INET;
 358                 sin.sin_port = sk->dummy_th.dest;
 359                 sin.sin_addr.s_addr = sk->daddr;
 360                 usin = &sin;
 361         }
 362   
 363         /*
 364          *      BSD socket semantics. You must set SO_BROADCAST to permit
 365          *      broadcasting of data.
 366          */
 367          
 368         /* RFC1122: OK.  Allows the application to select the specific */
 369         /* source address for an outgoing packet (MUST) as per 4.1.3.5. */
 370         /* Optional addition: a mechanism for telling the application what */
 371         /* address was used. (4.1.3.5, MAY) -- MS */
 372 
 373         /* RFC1122: MUST ensure that all outgoing packets have one */
 374         /* of this host's addresses as a source addr.(4.1.3.6) - bind in  */
 375         /* af_inet.c checks these. It does need work to allow BSD style */
 376         /* bind to multicast as is done by xntpd                */
 377 
 378         if(usin->sin_addr.s_addr==INADDR_ANY)
 379                 usin->sin_addr.s_addr=ip_my_addr();
 380                 
 381         if(!sk->broadcast && ip_chk_addr(usin->sin_addr.s_addr)==IS_BROADCAST)
 382                 return -EACCES;                 /* Must turn broadcast on first */
 383 
 384         sk->inuse = 1;
 385 
 386         /* Send the packet. */
 387         tmp = udp_send(sk, usin, from, len, flags);
 388 
 389         /* The datagram has been sent off.  Release the socket. */
 390         release_sock(sk);
 391         return(tmp);
 392 }
 393 
 394 /*
 395  *      In BSD SOCK_DGRAM a write is just like a send.
 396  */
 397 
 398 static int udp_write(struct sock *sk, const unsigned char *buff, int len, int noblock,
     /* [previous][next][first][last][top][bottom][index][help] */
 399           unsigned flags)
 400 {
 401         return(udp_sendto(sk, buff, len, noblock, flags, NULL, 0));
 402 }
 403 
 404 
 405 /*
 406  *      IOCTL requests applicable to the UDP protocol
 407  */
 408  
 409 int udp_ioctl(struct sock *sk, int cmd, unsigned long arg)
     /* [previous][next][first][last][top][bottom][index][help] */
 410 {
 411         int err;
 412         switch(cmd) 
 413         {
 414                 case TIOCOUTQ:
 415                 {
 416                         unsigned long amount;
 417 
 418                         if (sk->state == TCP_LISTEN) return(-EINVAL);
 419                         amount = sk->prot->wspace(sk)/*/2*/;
 420                         err=verify_area(VERIFY_WRITE,(void *)arg,
 421                                         sizeof(unsigned long));
 422                         if(err)
 423                                 return(err);
 424                         put_fs_long(amount,(unsigned long *)arg);
 425                         return(0);
 426                 }
 427 
 428                 case TIOCINQ:
 429                 {
 430                         struct sk_buff *skb;
 431                         unsigned long amount;
 432 
 433                         if (sk->state == TCP_LISTEN) return(-EINVAL);
 434                         amount = 0;
 435                         skb = skb_peek(&sk->receive_queue);
 436                         if (skb != NULL) {
 437                                 /*
 438                                  * We will only return the amount
 439                                  * of this packet since that is all
 440                                  * that will be read.
 441                                  */
 442                                 amount = skb->len;
 443                         }
 444                         err=verify_area(VERIFY_WRITE,(void *)arg,
 445                                                 sizeof(unsigned long));
 446                         if(err)
 447                                 return(err);
 448                         put_fs_long(amount,(unsigned long *)arg);
 449                         return(0);
 450                 }
 451 
 452                 default:
 453                         return(-EINVAL);
 454         }
 455         return(0);
 456 }
 457 
 458 
 459 /*
 460  *      This should be easy, if there is something there we\
 461  *      return it, otherwise we block.
 462  */
 463 
 464 int udp_recvfrom(struct sock *sk, unsigned char *to, int len,
     /* [previous][next][first][last][top][bottom][index][help] */
 465              int noblock, unsigned flags, struct sockaddr_in *sin,
 466              int *addr_len)
 467 {
 468         int copied = 0;
 469         int truesize;
 470         struct sk_buff *skb;
 471         int er;
 472 
 473         /*
 474          *      Check any passed addresses
 475          */
 476          
 477         if (addr_len) 
 478                 *addr_len=sizeof(*sin);
 479   
 480         /*
 481          *      From here the generic datagram does a lot of the work. Come
 482          *      the finished NET3, it will do _ALL_ the work!
 483          */
 484                 
 485         skb=skb_recv_datagram(sk,flags,noblock,&er);
 486         if(skb==NULL)
 487                 return er;
 488   
 489         truesize = skb->len - sizeof(struct udphdr);
 490         copied = min(len, truesize);
 491 
 492         /*
 493          *      FIXME : should use udp header size info value 
 494          */
 495          
 496         skb_copy_datagram(skb,sizeof(struct udphdr),to,copied);
 497         sk->stamp=skb->stamp;
 498 
 499         /* Copy the address. */
 500         if (sin) 
 501         {
 502                 sin->sin_family = AF_INET;
 503                 sin->sin_port = skb->h.uh->source;
 504                 sin->sin_addr.s_addr = skb->daddr;
 505         }
 506   
 507         skb_free_datagram(skb);
 508         release_sock(sk);
 509         return(copied);
 510 }
 511 
 512 /*
 513  *      Read has the same semantics as recv in SOCK_DGRAM
 514  */
 515 
 516 int udp_read(struct sock *sk, unsigned char *buff, int len, int noblock,
     /* [previous][next][first][last][top][bottom][index][help] */
 517          unsigned flags)
 518 {
 519         return(udp_recvfrom(sk, buff, len, noblock, flags, NULL, NULL));
 520 }
 521 
 522 
 523 int udp_connect(struct sock *sk, struct sockaddr_in *usin, int addr_len)
     /* [previous][next][first][last][top][bottom][index][help] */
 524 {
 525         struct rtable *rt;
 526         unsigned long sa;
 527         if (addr_len < sizeof(*usin)) 
 528                 return(-EINVAL);
 529 
 530         if (usin->sin_family && usin->sin_family != AF_INET) 
 531                 return(-EAFNOSUPPORT);
 532         if (usin->sin_addr.s_addr==INADDR_ANY)
 533                 usin->sin_addr.s_addr=ip_my_addr();
 534 
 535         if(!sk->broadcast && ip_chk_addr(usin->sin_addr.s_addr)==IS_BROADCAST)
 536                 return -EACCES;                 /* Must turn broadcast on first */
 537         
 538         rt=(sk->localroute?ip_rt_local:ip_rt_route)(usin->sin_addr.s_addr, NULL, &sa);
 539         if(rt==NULL)
 540                 return -ENETUNREACH;
 541         sk->saddr = sa;         /* Update source address */
 542         sk->daddr = usin->sin_addr.s_addr;
 543         sk->dummy_th.dest = usin->sin_port;
 544         sk->state = TCP_ESTABLISHED;
 545         udp_cache_zap();
 546         sk->ip_route_cache = rt;
 547         sk->ip_route_stamp = rt_stamp;
 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(uh_cache_sk==sk)
 557                 udp_cache_zap();
 558         if (sk->dead) 
 559                 destroy_sock(sk);
 560         else
 561                 release_sock(sk);
 562 }
 563 
 564 
 565 /*
 566  *      All we need to do is get the socket, and then do a checksum. 
 567  */
 568  
 569 int udp_rcv(struct sk_buff *skb, struct device *dev, struct options *opt,
     /* [previous][next][first][last][top][bottom][index][help] */
 570         unsigned long daddr, unsigned short len,
 571         unsigned long saddr, int redo, struct inet_protocol *protocol)
 572 {
 573         struct sock *sk;
 574         struct udphdr *uh;
 575         unsigned short ulen;
 576         int addr_type = IS_MYADDR;
 577         
 578         if(!dev || dev->pa_addr!=daddr)
 579                 addr_type=ip_chk_addr(daddr);
 580                 
 581         /*
 582          *      Get the header.
 583          */
 584          
 585         uh = (struct udphdr *) skb->h.uh;
 586         
 587         ip_statistics.IpInDelivers++;
 588 
 589         /*
 590          *      Validate the packet and the UDP length.
 591          */
 592          
 593         ulen = ntohs(uh->len);
 594         
 595         if (ulen > len || len < sizeof(*uh) || ulen < sizeof(*uh)) 
 596         {
 597                 NETDEBUG(printk("UDP: short packet: %d/%d\n", ulen, len));
 598                 udp_statistics.UdpInErrors++;
 599                 kfree_skb(skb, FREE_WRITE);
 600                 return(0);
 601         }
 602 
 603         /* RFC1122 warning: According to 4.1.3.6, we MUST discard any */
 604         /* datagram which has an invalid source address, either here or */
 605         /* in IP. */
 606         /* Right now, IP isn't doing it, and neither is UDP. It's on the */
 607         /* FIXME list for IP, though, so I wouldn't worry about it. */
 608         /* (That's the Right Place to do it, IMHO.) -- MS */
 609 
 610         if (uh->check && (
 611                 ( skb->ip_summed && udp_check(uh, len, saddr, daddr, skb->csum ) ) ||
 612                 ( !skb->ip_summed && udp_check(uh, len, saddr, daddr,csum_partial((char*)uh, len, 0)))
 613                          )
 614            )
 615         {
 616                 /* <mea@utu.fi> wants to know, who sent it, to
 617                    go and stomp on the garbage sender... */
 618 
 619           /* RFC1122: OK.  Discards the bad packet silently (as far as */
 620           /* the network is concered, anyway) as per 4.1.3.4 (MUST). */
 621 
 622                 NETDEBUG(printk("UDP: bad checksum. From %08lX:%d to %08lX:%d ulen %d\n",
 623                        ntohl(saddr),ntohs(uh->source),
 624                        ntohl(daddr),ntohs(uh->dest),
 625                        ulen));
 626                 udp_statistics.UdpInErrors++;
 627                 kfree_skb(skb, FREE_WRITE);
 628                 return(0);
 629         }
 630 
 631 
 632         len=ulen;
 633 
 634 #ifdef CONFIG_IP_MULTICAST
 635         if (addr_type!=IS_MYADDR)
 636         {
 637                 /*
 638                  *      Multicasts and broadcasts go to each listener.
 639                  */
 640                 struct sock *sknext=NULL;
 641                 sk=get_sock_mcast(udp_prot.sock_array[ntohs(uh->dest)&(SOCK_ARRAY_SIZE-1)], uh->dest,
 642                                 saddr, uh->source, daddr);
 643                 if(sk)
 644                 {               
 645                         do
 646                         {
 647                                 struct sk_buff *skb1;
 648 
 649                                 sknext=get_sock_mcast(sk->next, uh->dest, saddr, uh->source, daddr);
 650                                 if(sknext)
 651                                         skb1=skb_clone(skb,GFP_ATOMIC);
 652                                 else
 653                                         skb1=skb;
 654                                 if(skb1)
 655                                         udp_deliver(sk, uh, skb1, dev,saddr,daddr,len);
 656                                 sk=sknext;
 657                         }
 658                         while(sknext!=NULL);
 659                 }
 660                 else
 661                         kfree_skb(skb, FREE_READ);
 662                 return 0;
 663         }       
 664 #endif
 665         if(saddr==uh_cache_saddr && daddr==uh_cache_daddr && uh->dest==uh_cache_dport && uh->source==uh_cache_sport)
 666                 sk=(struct sock *)uh_cache_sk;
 667         else
 668         {
 669                 sk = get_sock(&udp_prot, uh->dest, saddr, uh->source, daddr);
 670                 uh_cache_saddr=saddr;
 671                 uh_cache_daddr=daddr;
 672                 uh_cache_dport=uh->dest;
 673                 uh_cache_sport=uh->source;
 674                 uh_cache_sk=sk;
 675         }
 676         
 677         if (sk == NULL) 
 678         {
 679                 udp_statistics.UdpNoPorts++;
 680                 if (addr_type == IS_MYADDR) 
 681                 {
 682                         icmp_send(skb, ICMP_DEST_UNREACH, ICMP_PORT_UNREACH, 0, dev);
 683                 }
 684                 /*
 685                  * Hmm.  We got an UDP broadcast to a port to which we
 686                  * don't wanna listen.  Ignore it.
 687                  */
 688                 skb->sk = NULL;
 689                 kfree_skb(skb, FREE_WRITE);
 690                 return(0);
 691         }
 692         return udp_deliver(sk,uh,skb,dev, saddr, daddr, len);
 693 }
 694 
 695 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] */
 696 {
 697         skb->sk = sk;
 698         skb->dev = dev;
 699         skb_trim(skb,len);
 700 
 701         /*
 702          *      These are supposed to be switched. 
 703          */
 704          
 705         skb->daddr = saddr;
 706         skb->saddr = daddr;
 707 
 708 
 709         /*
 710          *      Charge it to the socket, dropping if the queue is full.
 711          */
 712 
 713         /* I assume this includes the IP options, as per RFC1122 (4.1.3.2). */
 714         /* If not, please let me know. -- MS */
 715 
 716         if (sock_queue_rcv_skb(sk,skb)<0) 
 717         {
 718                 udp_statistics.UdpInErrors++;
 719                 ip_statistics.IpInDiscards++;
 720                 ip_statistics.IpInDelivers--;
 721                 skb->sk = NULL;
 722                 kfree_skb(skb, FREE_WRITE);
 723                 release_sock(sk);
 724                 return(0);
 725         }
 726         udp_statistics.UdpInDatagrams++;
 727         release_sock(sk);
 728         return(0);
 729 }
 730 
 731 
 732 struct proto udp_prot = {
 733         sock_wmalloc,
 734         sock_rmalloc,
 735         sock_wfree,
 736         sock_rfree,
 737         sock_rspace,
 738         sock_wspace,
 739         udp_close,
 740         udp_read,
 741         udp_write,
 742         udp_sendto,
 743         udp_recvfrom,
 744         ip_build_header,
 745         udp_connect,
 746         NULL,
 747         ip_queue_xmit,
 748         NULL,
 749         NULL,
 750         NULL,
 751         udp_rcv,
 752         datagram_select,
 753         udp_ioctl,
 754         NULL,
 755         NULL,
 756         ip_setsockopt,
 757         ip_getsockopt,
 758         128,
 759         0,
 760         "UDP",
 761         0, 0,
 762         {NULL,}
 763 };

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