root/net/inet/udp.c

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

DEFINITIONS

This source file includes following definitions.
  1. udp_err
  2. udp_check
  3. udp_send_check
  4. udp_send
  5. udp_sendto
  6. udp_write
  7. udp_ioctl
  8. udp_recvfrom
  9. udp_read
  10. udp_connect
  11. udp_close
  12. udp_rcv

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

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