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  *
  49  *
  50  *              This program is free software; you can redistribute it and/or
  51  *              modify it under the terms of the GNU General Public License
  52  *              as published by the Free Software Foundation; either version
  53  *              2 of the License, or (at your option) any later version.
  54  */
  55  
  56 #include <asm/system.h>
  57 #include <asm/segment.h>
  58 #include <linux/types.h>
  59 #include <linux/sched.h>
  60 #include <linux/fcntl.h>
  61 #include <linux/socket.h>
  62 #include <linux/sockios.h>
  63 #include <linux/in.h>
  64 #include <linux/errno.h>
  65 #include <linux/timer.h>
  66 #include <linux/termios.h>
  67 #include <linux/mm.h>
  68 #include <linux/config.h>
  69 #include <linux/inet.h>
  70 #include <linux/netdevice.h>
  71 #include <net/snmp.h>
  72 #include <net/ip.h>
  73 #include <net/protocol.h>
  74 #include <net/tcp.h>
  75 #include <linux/skbuff.h>
  76 #include <net/sock.h>
  77 #include <net/udp.h>
  78 #include <net/icmp.h>
  79 #include <net/route.h>
  80 #include <net/checksum.h>
  81 
  82 /*
  83  *      SNMP MIB for the UDP layer
  84  */
  85 
  86 struct udp_mib          udp_statistics;
  87 
  88 /*
  89  *      Cached last hit socket
  90  */
  91  
  92 volatile unsigned long  uh_cache_saddr,uh_cache_daddr;
  93 volatile unsigned short  uh_cache_dport, uh_cache_sport;
  94 volatile struct sock *uh_cache_sk;
  95 
  96 void udp_cache_zap(void)
     /* [previous][next][first][last][top][bottom][index][help] */
  97 {
  98         unsigned long flags;
  99         save_flags(flags);
 100         cli();
 101         uh_cache_saddr=0;
 102         uh_cache_daddr=0;
 103         uh_cache_dport=0;
 104         uh_cache_sport=0;
 105         uh_cache_sk=NULL;
 106         restore_flags(flags);
 107 }
 108 
 109 static int udp_deliver(struct sock *sk, struct udphdr *uh, struct sk_buff *skb, struct device *dev, long saddr, long daddr, int len);
 110 
 111 #define min(a,b)        ((a)<(b)?(a):(b))
 112 
 113 
 114 /*
 115  * This routine is called by the ICMP module when it gets some
 116  * sort of error condition.  If err < 0 then the socket should
 117  * be closed and the error returned to the user.  If err > 0
 118  * it's just the icmp type << 8 | icmp code.  
 119  * Header points to the ip header of the error packet. We move
 120  * on past this. Then (as it used to claim before adjustment)
 121  * header points to the first 8 bytes of the udp header.  We need
 122  * to find the appropriate port.
 123  */
 124 
 125 void udp_err(int err, unsigned char *header, unsigned long daddr,
     /* [previous][next][first][last][top][bottom][index][help] */
 126         unsigned long saddr, struct inet_protocol *protocol)
 127 {
 128         struct udphdr *th;
 129         struct sock *sk;
 130         struct iphdr *ip=(struct iphdr *)header;
 131   
 132         header += 4*ip->ihl;
 133 
 134         /*
 135          *      Find the 8 bytes of post IP header ICMP included for us
 136          */  
 137         
 138         th = (struct udphdr *)header;  
 139    
 140         sk = get_sock(&udp_prot, th->source, daddr, th->dest, saddr);
 141 
 142         if (sk == NULL) 
 143                 return; /* No socket for error */
 144         
 145         if (err & 0xff00 ==(ICMP_SOURCE_QUENCH << 8)) 
 146         {       /* Slow down! */
 147                 if (sk->cong_window > 1) 
 148                         sk->cong_window = sk->cong_window/2;
 149                 return;
 150         }
 151 
 152         /*
 153          *      Various people wanted BSD UDP semantics. Well they've come 
 154          *      back out because they slow down response to stuff like dead
 155          *      or unreachable name servers and they screw term users something
 156          *      chronic. Oh and it violates RFC1122. So basically fix your 
 157          *      client code people.
 158          */
 159          
 160         if (icmp_err_convert[err & 0xff].fatal)
 161         {
 162                 sk->err = icmp_err_convert[err & 0xff].errno;
 163                 sk->error_report(sk);
 164         }
 165 }
 166 
 167 
 168 static unsigned short udp_check(struct udphdr *uh, int len, unsigned long saddr, unsigned long daddr)
     /* [previous][next][first][last][top][bottom][index][help] */
 169 {
 170         return(csum_tcpudp_magic(saddr, daddr, len, IPPROTO_UDP,
 171                                  csum_partial((char*)uh, len, 0)));
 172 }
 173 
 174 struct udpfakehdr 
 175 {
 176         struct udphdr uh;
 177         int daddr;
 178         int other;
 179         char *from;
 180         int wcheck;
 181 };
 182 
 183 /*
 184  *      Copy and checksum a UDP packet from user space into a buffer. We still have to do the planning to
 185  *      get ip_build_xmit to spot direct transfer to network card and provide an additional callback mode
 186  *      for direct user->board I/O transfers. That one will be fun.
 187  */
 188  
 189 static void udp_getfrag(void *p, int saddr, char * to, unsigned int offset, unsigned int fraglen) 
     /* [previous][next][first][last][top][bottom][index][help] */
 190 {
 191         struct udpfakehdr *ufh = (struct udpfakehdr *)p;
 192         char *src, *dst;
 193         unsigned int len;
 194 
 195         if (offset) 
 196         {
 197                 len = fraglen;
 198                 src = ufh->from+(offset-sizeof(struct udphdr));
 199                 dst = to;
 200         }
 201         else 
 202         {
 203                 len = fraglen-sizeof(struct udphdr);
 204                 src = ufh->from;
 205                 dst = to+sizeof(struct udphdr);
 206         }
 207         ufh->wcheck = csum_partial_copyffs(src, dst, len, ufh->wcheck);
 208         if (offset == 0) 
 209         {
 210                 ufh->wcheck = csum_partial((char *)ufh, sizeof(struct udphdr),
 211                                    ufh->wcheck);
 212                 ufh->uh.check = csum_tcpudp_magic(saddr, ufh->daddr, 
 213                                           ntohs(ufh->uh.len),
 214                                           IPPROTO_UDP, ufh->wcheck);
 215                 if (ufh->uh.check == 0)
 216                         ufh->uh.check = -1;
 217                 memcpy(to, ufh, sizeof(struct udphdr));
 218         }
 219 }
 220 
 221 /*
 222  *      Uncheckummed UDP is sufficiently criticial to stuff like ATM video conferencing
 223  *      that we use two routines for this for speed. Probably we ought to have a CONFIG_FAST_NET
 224  *      set for >10Mb/second boards to activate this sort of coding. Timing needed to verify if
 225  *      this is a valid decision.
 226  */
 227  
 228 static void udp_getfrag_nosum(void *p, int saddr, char * to, unsigned int offset, unsigned int fraglen) 
     /* [previous][next][first][last][top][bottom][index][help] */
 229 {
 230         struct udpfakehdr *ufh = (struct udpfakehdr *)p;
 231         char *src, *dst;
 232         unsigned int len;
 233 
 234         if (offset) 
 235         {
 236                 len = fraglen;
 237                 src = ufh->from+(offset-sizeof(struct udphdr));
 238                 dst = to;
 239         }
 240         else 
 241         {
 242                 len = fraglen-sizeof(struct udphdr);
 243                 src = ufh->from;
 244                 dst = to+sizeof(struct udphdr);
 245         }
 246         memcpy_fromfs(src,dst,len);
 247         if (offset == 0) 
 248                 memcpy(to, ufh, sizeof(struct udphdr));
 249 }
 250 
 251 
 252 /*
 253  *      Send UDP frames.
 254  */
 255  
 256 static int udp_send(struct sock *sk, struct sockaddr_in *sin,
     /* [previous][next][first][last][top][bottom][index][help] */
 257                       unsigned char *from, int len, int rt) 
 258 {
 259         int ulen = len + sizeof(struct udphdr);
 260         int a;
 261         struct udpfakehdr ufh;
 262 
 263         ufh.uh.source = sk->dummy_th.source;
 264         ufh.uh.dest = sin->sin_port;
 265         ufh.uh.len = htons(ulen);
 266         ufh.uh.check = 0;
 267         ufh.daddr = sin->sin_addr.s_addr;
 268         ufh.other = (htons(ulen) << 16) + IPPROTO_UDP*256;
 269         ufh.from = from;
 270         ufh.wcheck = 0;
 271         if(sk->no_check)
 272                 a = ip_build_xmit(sk, udp_getfrag_nosum, &ufh, ulen, 
 273                         sin->sin_addr.s_addr, rt, IPPROTO_UDP);
 274         else
 275                 a = ip_build_xmit(sk, udp_getfrag, &ufh, ulen, 
 276                         sin->sin_addr.s_addr, rt, IPPROTO_UDP);
 277         return(a<0 ? a : len);
 278 }
 279 
 280 
 281 static int udp_sendto(struct sock *sk, unsigned char *from, int len, int noblock,
     /* [previous][next][first][last][top][bottom][index][help] */
 282            unsigned flags, struct sockaddr_in *usin, int addr_len)
 283 {
 284         struct sockaddr_in sin;
 285         int tmp;
 286 
 287         /* 
 288          *      Check the flags. We support no flags for UDP sending
 289          */
 290         if (flags&~MSG_DONTROUTE) 
 291                 return(-EINVAL);
 292         /*
 293          *      Get and verify the address. 
 294          */
 295          
 296         if (usin) 
 297         {
 298                 if (addr_len < sizeof(sin)) 
 299                         return(-EINVAL);
 300                 memcpy(&sin,usin,sizeof(sin));
 301                 if (sin.sin_family && sin.sin_family != AF_INET) 
 302                         return(-EINVAL);
 303                 if (sin.sin_port == 0) 
 304                         return(-EINVAL);
 305         } 
 306         else 
 307         {
 308                 if (sk->state != TCP_ESTABLISHED) 
 309                         return(-EINVAL);
 310                 sin.sin_family = AF_INET;
 311                 sin.sin_port = sk->dummy_th.dest;
 312                 sin.sin_addr.s_addr = sk->daddr;
 313         }
 314   
 315         /*
 316          *      BSD socket semantics. You must set SO_BROADCAST to permit
 317          *      broadcasting of data.
 318          */
 319          
 320         if(sin.sin_addr.s_addr==INADDR_ANY)
 321                 sin.sin_addr.s_addr=ip_my_addr();
 322                 
 323         if(!sk->broadcast && ip_chk_addr(sin.sin_addr.s_addr)==IS_BROADCAST)
 324                 return -EACCES;                 /* Must turn broadcast on first */
 325 
 326         sk->inuse = 1;
 327 
 328         /* Send the packet. */
 329         tmp = udp_send(sk, &sin, from, len, flags);
 330 
 331         /* The datagram has been sent off.  Release the socket. */
 332         release_sock(sk);
 333         return(tmp);
 334 }
 335 
 336 /*
 337  *      In BSD SOCK_DGRAM a write is just like a send.
 338  */
 339 
 340 static int udp_write(struct sock *sk, unsigned char *buff, int len, int noblock,
     /* [previous][next][first][last][top][bottom][index][help] */
 341           unsigned flags)
 342 {
 343         return(udp_sendto(sk, buff, len, noblock, flags, NULL, 0));
 344 }
 345 
 346 
 347 /*
 348  *      IOCTL requests applicable to the UDP protocol
 349  */
 350  
 351 int udp_ioctl(struct sock *sk, int cmd, unsigned long arg)
     /* [previous][next][first][last][top][bottom][index][help] */
 352 {
 353         int err;
 354         switch(cmd) 
 355         {
 356                 case TIOCOUTQ:
 357                 {
 358                         unsigned long amount;
 359 
 360                         if (sk->state == TCP_LISTEN) return(-EINVAL);
 361                         amount = sk->prot->wspace(sk)/*/2*/;
 362                         err=verify_area(VERIFY_WRITE,(void *)arg,
 363                                         sizeof(unsigned long));
 364                         if(err)
 365                                 return(err);
 366                         put_fs_long(amount,(unsigned long *)arg);
 367                         return(0);
 368                 }
 369 
 370                 case TIOCINQ:
 371                 {
 372                         struct sk_buff *skb;
 373                         unsigned long amount;
 374 
 375                         if (sk->state == TCP_LISTEN) return(-EINVAL);
 376                         amount = 0;
 377                         skb = skb_peek(&sk->receive_queue);
 378                         if (skb != NULL) {
 379                                 /*
 380                                  * We will only return the amount
 381                                  * of this packet since that is all
 382                                  * that will be read.
 383                                  */
 384                                 amount = skb->len;
 385                         }
 386                         err=verify_area(VERIFY_WRITE,(void *)arg,
 387                                                 sizeof(unsigned long));
 388                         if(err)
 389                                 return(err);
 390                         put_fs_long(amount,(unsigned long *)arg);
 391                         return(0);
 392                 }
 393 
 394                 default:
 395                         return(-EINVAL);
 396         }
 397         return(0);
 398 }
 399 
 400 
 401 /*
 402  *      This should be easy, if there is something there we\
 403  *      return it, otherwise we block.
 404  */
 405 
 406 int udp_recvfrom(struct sock *sk, unsigned char *to, int len,
     /* [previous][next][first][last][top][bottom][index][help] */
 407              int noblock, unsigned flags, struct sockaddr_in *sin,
 408              int *addr_len)
 409 {
 410         int copied = 0;
 411         int truesize;
 412         struct sk_buff *skb;
 413         int er;
 414 
 415         /*
 416          *      Check any passed addresses
 417          */
 418          
 419         if (addr_len) 
 420                 *addr_len=sizeof(*sin);
 421   
 422         /*
 423          *      From here the generic datagram does a lot of the work. Come
 424          *      the finished NET3, it will do _ALL_ the work!
 425          */
 426                 
 427         skb=skb_recv_datagram(sk,flags,noblock,&er);
 428         if(skb==NULL)
 429                 return er;
 430   
 431         truesize = skb->len;
 432         copied = min(len, truesize);
 433 
 434         /*
 435          *      FIXME : should use udp header size info value 
 436          */
 437          
 438         skb_copy_datagram(skb,sizeof(struct udphdr),to,copied);
 439         sk->stamp=skb->stamp;
 440 
 441         /* Copy the address. */
 442         if (sin) 
 443         {
 444                 sin->sin_family = AF_INET;
 445                 sin->sin_port = skb->h.uh->source;
 446                 sin->sin_addr.s_addr = skb->daddr;
 447         }
 448   
 449         skb_free_datagram(skb);
 450         release_sock(sk);
 451         return(truesize);
 452 }
 453 
 454 /*
 455  *      Read has the same semantics as recv in SOCK_DGRAM
 456  */
 457 
 458 int udp_read(struct sock *sk, unsigned char *buff, int len, int noblock,
     /* [previous][next][first][last][top][bottom][index][help] */
 459          unsigned flags)
 460 {
 461         return(udp_recvfrom(sk, buff, len, noblock, flags, NULL, NULL));
 462 }
 463 
 464 
 465 int udp_connect(struct sock *sk, struct sockaddr_in *usin, int addr_len)
     /* [previous][next][first][last][top][bottom][index][help] */
 466 {
 467         struct rtable *rt;
 468         unsigned long sa;
 469         if (addr_len < sizeof(*usin)) 
 470                 return(-EINVAL);
 471 
 472         if (usin->sin_family && usin->sin_family != AF_INET) 
 473                 return(-EAFNOSUPPORT);
 474         if (usin->sin_addr.s_addr==INADDR_ANY)
 475                 usin->sin_addr.s_addr=ip_my_addr();
 476 
 477         if(!sk->broadcast && ip_chk_addr(usin->sin_addr.s_addr)==IS_BROADCAST)
 478                 return -EACCES;                 /* Must turn broadcast on first */
 479         
 480         rt=(sk->localroute?ip_rt_local:ip_rt_route)(usin->sin_addr.s_addr, NULL, &sa);
 481         if(rt==NULL)
 482                 return -ENETUNREACH;
 483         sk->saddr = sa;         /* Update source address */
 484         sk->daddr = usin->sin_addr.s_addr;
 485         sk->dummy_th.dest = usin->sin_port;
 486         sk->state = TCP_ESTABLISHED;
 487         udp_cache_zap();
 488         sk->ip_route_cache = rt;
 489         sk->ip_route_stamp = rt_stamp;
 490         return(0);
 491 }
 492 
 493 
 494 static void udp_close(struct sock *sk, int timeout)
     /* [previous][next][first][last][top][bottom][index][help] */
 495 {
 496         sk->inuse = 1;
 497         sk->state = TCP_CLOSE;
 498         if(uh_cache_sk==sk)
 499                 udp_cache_zap();
 500         if (sk->dead) 
 501                 destroy_sock(sk);
 502         else
 503                 release_sock(sk);
 504 }
 505 
 506 
 507 /*
 508  *      All we need to do is get the socket, and then do a checksum. 
 509  */
 510  
 511 int udp_rcv(struct sk_buff *skb, struct device *dev, struct options *opt,
     /* [previous][next][first][last][top][bottom][index][help] */
 512         unsigned long daddr, unsigned short len,
 513         unsigned long saddr, int redo, struct inet_protocol *protocol)
 514 {
 515         struct sock *sk;
 516         struct udphdr *uh;
 517         unsigned short ulen;
 518         int addr_type = IS_MYADDR;
 519         
 520         if(!dev || dev->pa_addr!=daddr)
 521                 addr_type=ip_chk_addr(daddr);
 522                 
 523         /*
 524          *      Get the header.
 525          */
 526          
 527         uh = (struct udphdr *) skb->h.uh;
 528         
 529         ip_statistics.IpInDelivers++;
 530 
 531         /*
 532          *      Validate the packet and the UDP length.
 533          */
 534          
 535         ulen = ntohs(uh->len);
 536 
 537         if (ulen > len || len < sizeof(*uh) || ulen < sizeof(*uh)) 
 538         {
 539                 NETDEBUG(printk("UDP: short packet: %d/%d\n", ulen, len));
 540                 udp_statistics.UdpInErrors++;
 541                 kfree_skb(skb, FREE_WRITE);
 542                 return(0);
 543         }
 544 
 545         if (uh->check && udp_check(uh, len, saddr, daddr)) 
 546         {
 547                 /* <mea@utu.fi> wants to know, who sent it, to
 548                    go and stomp on the garbage sender... */
 549                 NETDEBUG(printk("UDP: bad checksum. From %08lX:%d to %08lX:%d ulen %d\n",
 550                        ntohl(saddr),ntohs(uh->source),
 551                        ntohl(daddr),ntohs(uh->dest),
 552                        ulen));
 553                 udp_statistics.UdpInErrors++;
 554                 kfree_skb(skb, FREE_WRITE);
 555                 return(0);
 556         }
 557 
 558 
 559         len=ulen;
 560 
 561 #ifdef CONFIG_IP_MULTICAST
 562         if (addr_type!=IS_MYADDR)
 563         {
 564                 /*
 565                  *      Multicasts and broadcasts go to each listener.
 566                  */
 567                 struct sock *sknext=NULL;
 568                 sk=get_sock_mcast(udp_prot.sock_array[ntohs(uh->dest)&(SOCK_ARRAY_SIZE-1)], uh->dest,
 569                                 saddr, uh->source, daddr);
 570                 if(sk)
 571                 {               
 572                         do
 573                         {
 574                                 struct sk_buff *skb1;
 575 
 576                                 sknext=get_sock_mcast(sk->next, uh->dest, saddr, uh->source, daddr);
 577                                 if(sknext)
 578                                         skb1=skb_clone(skb,GFP_ATOMIC);
 579                                 else
 580                                         skb1=skb;
 581                                 if(skb1)
 582                                         udp_deliver(sk, uh, skb1, dev,saddr,daddr,len);
 583                                 sk=sknext;
 584                         }
 585                         while(sknext!=NULL);
 586                 }
 587                 else
 588                         kfree_skb(skb, FREE_READ);
 589                 return 0;
 590         }       
 591 #endif
 592         if(saddr==uh_cache_saddr && daddr==uh_cache_daddr && uh->dest==uh_cache_dport && uh->source==uh_cache_sport)
 593                 sk=(struct sock *)uh_cache_sk;
 594         else
 595         {
 596                 sk = get_sock(&udp_prot, uh->dest, saddr, uh->source, daddr);
 597                 uh_cache_saddr=saddr;
 598                 uh_cache_daddr=daddr;
 599                 uh_cache_dport=uh->dest;
 600                 uh_cache_sport=uh->source;
 601                 uh_cache_sk=sk;
 602         }
 603         
 604         if (sk == NULL) 
 605         {
 606                 udp_statistics.UdpNoPorts++;
 607                 if (addr_type == IS_MYADDR) 
 608                 {
 609                         icmp_send(skb, ICMP_DEST_UNREACH, ICMP_PORT_UNREACH, 0, dev);
 610                 }
 611                 /*
 612                  * Hmm.  We got an UDP broadcast to a port to which we
 613                  * don't wanna listen.  Ignore it.
 614                  */
 615                 skb->sk = NULL;
 616                 kfree_skb(skb, FREE_WRITE);
 617                 return(0);
 618         }
 619         return udp_deliver(sk,uh,skb,dev, saddr, daddr, len);
 620 }
 621 
 622 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] */
 623 {
 624         skb->sk = sk;
 625         skb->dev = dev;
 626         skb->len = len;
 627 
 628         /*
 629          *      These are supposed to be switched. 
 630          */
 631          
 632         skb->daddr = saddr;
 633         skb->saddr = daddr;
 634 
 635 
 636         /*
 637          *      Charge it to the socket, dropping if the queue is full.
 638          */
 639 
 640         skb->len = len - sizeof(*uh);  
 641          
 642         if (sock_queue_rcv_skb(sk,skb)<0) 
 643         {
 644                 udp_statistics.UdpInErrors++;
 645                 ip_statistics.IpInDiscards++;
 646                 ip_statistics.IpInDelivers--;
 647                 skb->sk = NULL;
 648                 kfree_skb(skb, FREE_WRITE);
 649                 release_sock(sk);
 650                 return(0);
 651         }
 652         udp_statistics.UdpInDatagrams++;
 653         release_sock(sk);
 654         return(0);
 655 }
 656 
 657 
 658 struct proto udp_prot = {
 659         sock_wmalloc,
 660         sock_rmalloc,
 661         sock_wfree,
 662         sock_rfree,
 663         sock_rspace,
 664         sock_wspace,
 665         udp_close,
 666         udp_read,
 667         udp_write,
 668         udp_sendto,
 669         udp_recvfrom,
 670         ip_build_header,
 671         udp_connect,
 672         NULL,
 673         ip_queue_xmit,
 674         NULL,
 675         NULL,
 676         NULL,
 677         udp_rcv,
 678         datagram_select,
 679         udp_ioctl,
 680         NULL,
 681         NULL,
 682         ip_setsockopt,
 683         ip_getsockopt,
 684         128,
 685         0,
 686         "UDP",
 687         0, 0,
 688         {NULL,}
 689 };
 690 

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