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 type, int code, unsigned char *header, __u32 daddr,
     /* [previous][next][first][last][top][bottom][index][help] */
 154         __u32 saddr, struct inet_protocol *protocol)
 155 {
 156         struct udphdr *uh;
 157         struct sock *sk;
 158 
 159         /*
 160          *      Find the 8 bytes of post IP header ICMP included for us
 161          */  
 162         
 163         uh = (struct udphdr *)header;  
 164    
 165         sk = get_sock(&udp_prot, uh->source, daddr, uh->dest, saddr);
 166 
 167         if (sk == NULL) 
 168                 return; /* No socket for error */
 169         
 170         if (type == ICMP_SOURCE_QUENCH) 
 171         {       /* Slow down! */
 172                 if (sk->cong_window > 1) 
 173                         sk->cong_window = sk->cong_window/2;
 174                 return;
 175         }
 176 
 177         if (type == ICMP_PARAMETERPROB)
 178         {
 179                 sk->err = EPROTO;
 180                 sk->error_report(sk);
 181                 return;
 182         }
 183                         
 184         /*
 185          *      Various people wanted BSD UDP semantics. Well they've come 
 186          *      back out because they slow down response to stuff like dead
 187          *      or unreachable name servers and they screw term users something
 188          *      chronic. Oh and it violates RFC1122. So basically fix your 
 189          *      client code people.
 190          */
 191          
 192         /* RFC1122: OK.  Passes ICMP errors back to application, as per */
 193         /* 4.1.3.3. */
 194         /* After the comment above, that should be no surprise. */
 195 
 196         if (code < 13 && icmp_err_convert[code].fatal)
 197         {
 198                 sk->err = icmp_err_convert[code].errno;
 199                 sk->error_report(sk);
 200         }
 201 }
 202 
 203 
 204 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] */
 205 {
 206         return(csum_tcpudp_magic(saddr, daddr, len, IPPROTO_UDP, base));
 207 }
 208 
 209 struct udpfakehdr 
 210 {
 211         struct udphdr uh;
 212         int daddr;
 213         int other;
 214         const char *from;
 215         int wcheck;
 216 };
 217 
 218 /*
 219  *      Copy and checksum a UDP packet from user space into a buffer. We still have to do the planning to
 220  *      get ip_build_xmit to spot direct transfer to network card and provide an additional callback mode
 221  *      for direct user->board I/O transfers. That one will be fun.
 222  */
 223  
 224 static void udp_getfrag(const void *p, __u32 saddr, char * to, unsigned int offset, unsigned int fraglen) 
     /* [previous][next][first][last][top][bottom][index][help] */
 225 {
 226         struct udpfakehdr *ufh = (struct udpfakehdr *)p;
 227         const char *src;
 228         char *dst;
 229         unsigned int len;
 230 
 231         if (offset) 
 232         {
 233                 len = fraglen;
 234                 src = ufh->from+(offset-sizeof(struct udphdr));
 235                 dst = to;
 236         }
 237         else 
 238         {
 239                 len = fraglen-sizeof(struct udphdr);
 240                 src = ufh->from;
 241                 dst = to+sizeof(struct udphdr);
 242         }
 243         ufh->wcheck = csum_partial_copy_fromuser(src, dst, len, ufh->wcheck);
 244         if (offset == 0) 
 245         {
 246                 ufh->wcheck = csum_partial((char *)ufh, sizeof(struct udphdr),
 247                                    ufh->wcheck);
 248                 ufh->uh.check = csum_tcpudp_magic(saddr, ufh->daddr, 
 249                                           ntohs(ufh->uh.len),
 250                                           IPPROTO_UDP, ufh->wcheck);
 251                 if (ufh->uh.check == 0)
 252                         ufh->uh.check = -1;
 253                 memcpy(to, ufh, sizeof(struct udphdr));
 254         }
 255 }
 256 
 257 /*
 258  *      Uncheckummed UDP is sufficiently criticial to stuff like ATM video conferencing
 259  *      that we use two routines for this for speed. Probably we ought to have a CONFIG_FAST_NET
 260  *      set for >10Mb/second boards to activate this sort of coding. Timing needed to verify if
 261  *      this is a valid decision.
 262  */
 263  
 264 static void udp_getfrag_nosum(const void *p, __u32 saddr, char * to, unsigned int offset, unsigned int fraglen) 
     /* [previous][next][first][last][top][bottom][index][help] */
 265 {
 266         struct udpfakehdr *ufh = (struct udpfakehdr *)p;
 267         const char *src;
 268         char *dst;
 269         unsigned int len;
 270 
 271         if (offset) 
 272         {
 273                 len = fraglen;
 274                 src = ufh->from+(offset-sizeof(struct udphdr));
 275                 dst = to;
 276         }
 277         else 
 278         {
 279                 len = fraglen-sizeof(struct udphdr);
 280                 src = ufh->from;
 281                 dst = to+sizeof(struct udphdr);
 282         }
 283         memcpy_fromfs(dst,src,len);
 284         if (offset == 0) 
 285                 memcpy(to, ufh, sizeof(struct udphdr));
 286 }
 287 
 288 
 289 /*
 290  *      Send UDP frames.
 291  */
 292  
 293 static int udp_send(struct sock *sk, struct sockaddr_in *sin,
     /* [previous][next][first][last][top][bottom][index][help] */
 294                       const unsigned char *from, int len, int rt) 
 295 {
 296         int ulen = len + sizeof(struct udphdr);
 297         int a;
 298         struct udpfakehdr ufh;
 299 
 300         ufh.uh.source = sk->dummy_th.source;
 301         ufh.uh.dest = sin->sin_port;
 302         ufh.uh.len = htons(ulen);
 303         ufh.uh.check = 0;
 304         ufh.daddr = sin->sin_addr.s_addr;
 305         ufh.other = (htons(ulen) << 16) + IPPROTO_UDP*256;
 306         ufh.from = from;
 307         ufh.wcheck = 0;
 308 
 309         /* RFC1122 Violation: there is no provision for passing IP options */
 310         /* from the application layer to the IP one.  It's a MUST (4.1.3.2), */
 311         /* but it looks like it'd require some work on ip_build_xmit. */
 312         /* Alan says he's got a Cunning Plan. -- MS */
 313 
 314         /* RFC1122: OK.  Provides the checksumming facility (MUST) as per */
 315         /* 4.1.3.4. It's configurable by the application via setsockopt() */
 316         /* (MAY) and it defaults to on (MUST).  Almost makes up for the */
 317         /* violation above. -- MS */
 318 
 319         if(sk->no_check)
 320                 a = ip_build_xmit(sk, udp_getfrag_nosum, &ufh, ulen, 
 321                         sin->sin_addr.s_addr, rt, IPPROTO_UDP);
 322         else
 323                 a = ip_build_xmit(sk, udp_getfrag, &ufh, ulen, 
 324                         sin->sin_addr.s_addr, rt, IPPROTO_UDP);
 325         if(a<0)
 326                 return a;
 327         udp_statistics.UdpOutDatagrams++;
 328         return len;
 329 }
 330 
 331 
 332 static int udp_sendto(struct sock *sk, const unsigned char *from, int len, int noblock,
     /* [previous][next][first][last][top][bottom][index][help] */
 333            unsigned flags, struct sockaddr_in *usin, int addr_len)
 334 {
 335         struct sockaddr_in sin;
 336         int tmp;
 337 
 338         /* 
 339          *      Check the flags. We support no flags for UDP sending
 340          */
 341         if (flags&~MSG_DONTROUTE) 
 342                 return(-EINVAL);
 343         /*
 344          *      Get and verify the address. 
 345          */
 346          
 347         if (usin) 
 348         {
 349                 if (addr_len < sizeof(sin)) 
 350                         return(-EINVAL);
 351                 if (usin->sin_family && usin->sin_family != AF_INET) 
 352                         return(-EINVAL);
 353                 if (usin->sin_port == 0) 
 354                         return(-EINVAL);
 355         } 
 356         else 
 357         {
 358                 if (sk->state != TCP_ESTABLISHED) 
 359                         return(-EINVAL);
 360                 sin.sin_family = AF_INET;
 361                 sin.sin_port = sk->dummy_th.dest;
 362                 sin.sin_addr.s_addr = sk->daddr;
 363                 usin = &sin;
 364         }
 365   
 366         /*
 367          *      BSD socket semantics. You must set SO_BROADCAST to permit
 368          *      broadcasting of data.
 369          */
 370          
 371         /* RFC1122: OK.  Allows the application to select the specific */
 372         /* source address for an outgoing packet (MUST) as per 4.1.3.5. */
 373         /* Optional addition: a mechanism for telling the application what */
 374         /* address was used. (4.1.3.5, MAY) -- MS */
 375 
 376         /* RFC1122: MUST ensure that all outgoing packets have one */
 377         /* of this host's addresses as a source addr.(4.1.3.6) - bind in  */
 378         /* af_inet.c checks these. It does need work to allow BSD style */
 379         /* bind to multicast as is done by xntpd                */
 380 
 381         if(usin->sin_addr.s_addr==INADDR_ANY)
 382                 usin->sin_addr.s_addr=ip_my_addr();
 383                 
 384         if(!sk->broadcast && ip_chk_addr(usin->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, usin, 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, const 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 - sizeof(struct udphdr);
 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(copied);
 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         __u32 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=(sk->localroute?ip_rt_local:ip_rt_route)((__u32)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         udp_cache_zap();
 549         sk->ip_route_cache = rt;
 550         sk->ip_route_stamp = rt_stamp;
 551         return(0);
 552 }
 553 
 554 
 555 static void udp_close(struct sock *sk, int timeout)
     /* [previous][next][first][last][top][bottom][index][help] */
 556 {
 557         sk->inuse = 1;
 558         sk->state = TCP_CLOSE;
 559         if(uh_cache_sk==sk)
 560                 udp_cache_zap();
 561         if (sk->dead) 
 562                 destroy_sock(sk);
 563         else
 564                 release_sock(sk);
 565 }
 566 
 567 
 568 /*
 569  *      All we need to do is get the socket, and then do a checksum. 
 570  */
 571  
 572 int udp_rcv(struct sk_buff *skb, struct device *dev, struct options *opt,
     /* [previous][next][first][last][top][bottom][index][help] */
 573         __u32 daddr, unsigned short len,
 574         __u32 saddr, int redo, struct inet_protocol *protocol)
 575 {
 576         struct sock *sk;
 577         struct udphdr *uh;
 578         unsigned short ulen;
 579         int addr_type = IS_MYADDR;
 580         
 581         if(!dev || dev->pa_addr!=daddr)
 582                 addr_type=ip_chk_addr(daddr);
 583                 
 584         /*
 585          *      Get the header.
 586          */
 587          
 588         uh = (struct udphdr *) skb->h.uh;
 589         
 590         ip_statistics.IpInDelivers++;
 591 
 592         /*
 593          *      Validate the packet and the UDP length.
 594          */
 595          
 596         ulen = ntohs(uh->len);
 597         
 598         if (ulen > len || len < sizeof(*uh) || ulen < sizeof(*uh)) 
 599         {
 600                 NETDEBUG(printk("UDP: short packet: %d/%d\n", ulen, len));
 601                 udp_statistics.UdpInErrors++;
 602                 kfree_skb(skb, FREE_WRITE);
 603                 return(0);
 604         }
 605 
 606         /* RFC1122 warning: According to 4.1.3.6, we MUST discard any */
 607         /* datagram which has an invalid source address, either here or */
 608         /* in IP. */
 609         /* Right now, IP isn't doing it, and neither is UDP. It's on the */
 610         /* FIXME list for IP, though, so I wouldn't worry about it. */
 611         /* (That's the Right Place to do it, IMHO.) -- MS */
 612 
 613         if (uh->check && (
 614                 ( skb->ip_summed && udp_check(uh, len, saddr, daddr, skb->csum ) ) ||
 615                 ( !skb->ip_summed && udp_check(uh, len, saddr, daddr,csum_partial((char*)uh, len, 0)))
 616                          )
 617            )
 618         {
 619                 /* <mea@utu.fi> wants to know, who sent it, to
 620                    go and stomp on the garbage sender... */
 621 
 622           /* RFC1122: OK.  Discards the bad packet silently (as far as */
 623           /* the network is concered, anyway) as per 4.1.3.4 (MUST). */
 624 
 625                 NETDEBUG(printk("UDP: bad checksum. From %08lX:%d to %08lX:%d ulen %d\n",
 626                        ntohl(saddr),ntohs(uh->source),
 627                        ntohl(daddr),ntohs(uh->dest),
 628                        ulen));
 629                 udp_statistics.UdpInErrors++;
 630                 kfree_skb(skb, FREE_WRITE);
 631                 return(0);
 632         }
 633 
 634 
 635         len=ulen;
 636 
 637 #ifdef CONFIG_IP_MULTICAST
 638         if (addr_type!=IS_MYADDR)
 639         {
 640                 /*
 641                  *      Multicasts and broadcasts go to each listener.
 642                  */
 643                 struct sock *sknext=NULL;
 644                 sk=get_sock_mcast(udp_prot.sock_array[ntohs(uh->dest)&(SOCK_ARRAY_SIZE-1)], uh->dest,
 645                                 saddr, uh->source, daddr);
 646                 if(sk)
 647                 {               
 648                         do
 649                         {
 650                                 struct sk_buff *skb1;
 651 
 652                                 sknext=get_sock_mcast(sk->next, uh->dest, saddr, uh->source, daddr);
 653                                 if(sknext)
 654                                         skb1=skb_clone(skb,GFP_ATOMIC);
 655                                 else
 656                                         skb1=skb;
 657                                 if(skb1)
 658                                         udp_deliver(sk, uh, skb1, dev,saddr,daddr,len);
 659                                 sk=sknext;
 660                         }
 661                         while(sknext!=NULL);
 662                 }
 663                 else
 664                         kfree_skb(skb, FREE_READ);
 665                 return 0;
 666         }       
 667 #endif
 668         if(saddr==uh_cache_saddr && daddr==uh_cache_daddr && uh->dest==uh_cache_dport && uh->source==uh_cache_sport)
 669                 sk=(struct sock *)uh_cache_sk;
 670         else
 671         {
 672                 sk = get_sock(&udp_prot, uh->dest, saddr, uh->source, daddr);
 673                 uh_cache_saddr=saddr;
 674                 uh_cache_daddr=daddr;
 675                 uh_cache_dport=uh->dest;
 676                 uh_cache_sport=uh->source;
 677                 uh_cache_sk=sk;
 678         }
 679         
 680         if (sk == NULL) 
 681         {
 682                 udp_statistics.UdpNoPorts++;
 683                 if (addr_type == IS_MYADDR) 
 684                 {
 685                         icmp_send(skb, ICMP_DEST_UNREACH, ICMP_PORT_UNREACH, 0, dev);
 686                 }
 687                 /*
 688                  * Hmm.  We got an UDP broadcast to a port to which we
 689                  * don't wanna listen.  Ignore it.
 690                  */
 691                 skb->sk = NULL;
 692                 kfree_skb(skb, FREE_WRITE);
 693                 return(0);
 694         }
 695         return udp_deliver(sk,uh,skb,dev, saddr, daddr, len);
 696 }
 697 
 698 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] */
 699 {
 700         skb->sk = sk;
 701         skb->dev = dev;
 702         skb_trim(skb,len);
 703 
 704         /*
 705          *      These are supposed to be switched. 
 706          */
 707          
 708         skb->daddr = saddr;
 709         skb->saddr = daddr;
 710 
 711 
 712         /*
 713          *      Charge it to the socket, dropping if the queue is full.
 714          */
 715 
 716         /* I assume this includes the IP options, as per RFC1122 (4.1.3.2). */
 717         /* If not, please let me know. -- MS */
 718 
 719         if (sock_queue_rcv_skb(sk,skb)<0) 
 720         {
 721                 udp_statistics.UdpInErrors++;
 722                 ip_statistics.IpInDiscards++;
 723                 ip_statistics.IpInDelivers--;
 724                 skb->sk = NULL;
 725                 kfree_skb(skb, FREE_WRITE);
 726                 release_sock(sk);
 727                 return(0);
 728         }
 729         udp_statistics.UdpInDatagrams++;
 730         release_sock(sk);
 731         return(0);
 732 }
 733 
 734 
 735 struct proto udp_prot = {
 736         sock_wmalloc,
 737         sock_rmalloc,
 738         sock_wfree,
 739         sock_rfree,
 740         sock_rspace,
 741         sock_wspace,
 742         udp_close,
 743         udp_read,
 744         udp_write,
 745         udp_sendto,
 746         udp_recvfrom,
 747         ip_build_header,
 748         udp_connect,
 749         NULL,
 750         ip_queue_xmit,
 751         NULL,
 752         NULL,
 753         NULL,
 754         udp_rcv,
 755         datagram_select,
 756         udp_ioctl,
 757         NULL,
 758         NULL,
 759         ip_setsockopt,
 760         ip_getsockopt,
 761         128,
 762         0,
 763         "UDP",
 764         0, 0,
 765         {NULL,}
 766 };

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