root/net/inet/udp.c

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

DEFINITIONS

This source file includes following definitions.
  1. print_udp
  2. udp_err
  3. udp_check
  4. udp_send_check
  5. udp_send
  6. udp_sendto
  7. udp_write
  8. udp_ioctl
  9. udp_recvfrom
  10. udp_read
  11. udp_connect
  12. udp_close
  13. 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 uknown 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  *
  38  *
  39  *              This program is free software; you can redistribute it and/or
  40  *              modify it under the terms of the GNU General Public License
  41  *              as published by the Free Software Foundation; either version
  42  *              2 of the License, or (at your option) any later version.
  43  */
  44  
  45 #include <asm/system.h>
  46 #include <asm/segment.h>
  47 #include <linux/types.h>
  48 #include <linux/sched.h>
  49 #include <linux/fcntl.h>
  50 #include <linux/socket.h>
  51 #include <linux/sockios.h>
  52 #include <linux/in.h>
  53 #include <linux/errno.h>
  54 #include <linux/timer.h>
  55 #include <linux/termios.h>
  56 #include <linux/mm.h>
  57 #include "inet.h"
  58 #include "dev.h"
  59 #include "ip.h"
  60 #include "protocol.h"
  61 #include "tcp.h"
  62 #include "skbuff.h"
  63 #include "sock.h"
  64 #include "udp.h"
  65 #include "icmp.h"
  66 
  67 
  68 #define min(a,b)        ((a)<(b)?(a):(b))
  69 
  70 
  71 static void
  72 print_udp(struct udphdr *uh)
     /* [previous][next][first][last][top][bottom][index][help] */
  73 {
  74   if (inet_debug != DBG_UDP) return;
  75 
  76   if (uh == NULL) {
  77         printk("(NULL)\n");
  78         return;
  79   }
  80   printk("UDP: source = %d, dest = %d\n", ntohs(uh->source), ntohs(uh->dest));
  81   printk("     len = %d, check = %d\n", ntohs(uh->len), ntohs(uh->check));
  82 }
  83 
  84 
  85 /*
  86  * This routine is called by the ICMP module when it gets some
  87  * sort of error condition.  If err < 0 then the socket should
  88  * be closed and the error returned to the user.  If err > 0
  89  * it's just the icmp type << 8 | icmp code.  
  90  * Header points to the ip header of the error packet. We move
  91  * on past this. Then (as it used to claim before adjustment)
  92  * header points to the first 8 bytes of the udp header.  We need
  93  * to find the appropriate port.
  94  */
  95 void
  96 udp_err(int err, unsigned char *header, unsigned long daddr,
     /* [previous][next][first][last][top][bottom][index][help] */
  97         unsigned long saddr, struct inet_protocol *protocol)
  98 {
  99   struct udphdr *th;
 100   struct sock *sk;
 101   struct iphdr *ip=(struct iphdr *)header;
 102   
 103   header += 4*ip->ihl;
 104   
 105   th = (struct udphdr *)header;  
 106    
 107   DPRINTF((DBG_UDP,"UDP: err(err=%d, header=%X, daddr=%X, saddr=%X, protocl=%X)\n\
 108 sport=%d,dport=%d", err, header, daddr, saddr, protocol, (int)th->source,(int)th->dest));
 109 
 110   sk = get_sock(&udp_prot, th->source, daddr, th->dest, saddr);
 111 
 112   if (sk == NULL) 
 113         return; /* No socket for error */
 114         
 115   if (err < 0)          /* As per the calling spec */
 116   {
 117         sk->err = -err;
 118         sk->error_report(sk);           /* User process wakes to see error */
 119         return;
 120   }
 121   
 122   if (err & 0xff00 ==(ICMP_SOURCE_QUENCH << 8)) {       /* Slow down! */
 123         if (sk->cong_window > 1) 
 124                 sk->cong_window = sk->cong_window/2;
 125         return;
 126   }
 127 
 128   sk->err = icmp_err_convert[err & 0xff].errno;
 129 
 130   /* It's only fatal if we have connected to them. */
 131   if (icmp_err_convert[err & 0xff].fatal && sk->state == TCP_ESTABLISHED) {
 132         sk->err=ECONNREFUSED;
 133   }
 134   sk->error_report(sk);
 135 }
 136 
 137 
 138 static unsigned short
 139 udp_check(struct udphdr *uh, int len,
     /* [previous][next][first][last][top][bottom][index][help] */
 140           unsigned long saddr, unsigned long daddr)
 141 {
 142   unsigned long sum;
 143 
 144   DPRINTF((DBG_UDP, "UDP: check(uh=%X, len = %d, saddr = %X, daddr = %X)\n",
 145                                                         uh, len, saddr, daddr));
 146 
 147   print_udp(uh);
 148 
 149   __asm__("\t addl %%ecx,%%ebx\n"
 150           "\t adcl %%edx,%%ebx\n"
 151           "\t adcl $0, %%ebx\n"
 152           : "=b"(sum)
 153           : "0"(daddr), "c"(saddr), "d"((ntohs(len) << 16) + IPPROTO_UDP*256)
 154           : "cx","bx","dx" );
 155 
 156   if (len > 3) {
 157         __asm__("\tclc\n"
 158                 "1:\n"
 159                 "\t lodsl\n"
 160                 "\t adcl %%eax, %%ebx\n"
 161                 "\t loop 1b\n"
 162                 "\t adcl $0, %%ebx\n"
 163                 : "=b"(sum) , "=S"(uh)
 164                 : "0"(sum), "c"(len/4) ,"1"(uh)
 165                 : "ax", "cx", "bx", "si" );
 166   }
 167 
 168   /* Convert from 32 bits to 16 bits. */
 169   __asm__("\t movl %%ebx, %%ecx\n"
 170           "\t shrl $16,%%ecx\n"
 171           "\t addw %%cx, %%bx\n"
 172           "\t adcw $0, %%bx\n"
 173           : "=b"(sum)
 174           : "0"(sum)
 175           : "bx", "cx");
 176 
 177   /* Check for an extra word. */
 178   if ((len & 2) != 0) {
 179         __asm__("\t lodsw\n"
 180                 "\t addw %%ax,%%bx\n"
 181                 "\t adcw $0, %%bx\n"
 182                 : "=b"(sum), "=S"(uh)
 183                 : "0"(sum) ,"1"(uh)
 184                 : "si", "ax", "bx");
 185   }
 186 
 187   /* Now check for the extra byte. */
 188   if ((len & 1) != 0) {
 189         __asm__("\t lodsb\n"
 190                 "\t movb $0,%%ah\n"
 191                 "\t addw %%ax,%%bx\n"
 192                 "\t adcw $0, %%bx\n"
 193                 : "=b"(sum)
 194                 : "0"(sum) ,"S"(uh)
 195                 : "si", "ax", "bx");
 196   }
 197 
 198   /* We only want the bottom 16 bits, but we never cleared the top 16. */
 199   return((~sum) & 0xffff);
 200 }
 201 
 202 
 203 static void
 204 udp_send_check(struct udphdr *uh, unsigned long saddr, 
     /* [previous][next][first][last][top][bottom][index][help] */
 205                unsigned long daddr, int len, struct sock *sk)
 206 {
 207   uh->check = 0;
 208   if (sk && sk->no_check) 
 209         return;
 210   uh->check = udp_check(uh, len, saddr, daddr);
 211   if (uh->check == 0) uh->check = 0xffff;
 212 }
 213 
 214 
 215 static int
 216 udp_send(struct sock *sk, struct sockaddr_in *sin,
     /* [previous][next][first][last][top][bottom][index][help] */
 217          unsigned char *from, int len)
 218 {
 219   struct sk_buff *skb;
 220   struct device *dev;
 221   struct udphdr *uh;
 222   unsigned char *buff;
 223   unsigned long saddr;
 224   int size, tmp;
 225   int err;
 226   
 227   DPRINTF((DBG_UDP, "UDP: send(dst=%s:%d buff=%X len=%d)\n",
 228                 in_ntoa(sin->sin_addr.s_addr), ntohs(sin->sin_port),
 229                 from, len));
 230 
 231   err=verify_area(VERIFY_READ, from, len);
 232   if(err)
 233         return(err);
 234 
 235   /* Allocate a copy of the packet. */
 236   size = sizeof(struct sk_buff) + sk->prot->max_header + len;
 237   skb = sk->prot->wmalloc(sk, size, 0, GFP_KERNEL);
 238   if (skb == NULL) return(-ENOMEM);
 239 
 240   skb->mem_addr = skb;
 241   skb->mem_len  = size;
 242   skb->sk       = NULL; /* to avoid changing sk->saddr */
 243   skb->free     = 1;
 244   skb->arp      = 0;
 245 
 246   /* Now build the IP and MAC header. */
 247   buff = skb->data;
 248   saddr = 0;
 249   dev = NULL;
 250   DPRINTF((DBG_UDP, "UDP: >> IP_Header: %X -> %X dev=%X prot=%X len=%d\n",
 251                         saddr, sin->sin_addr.s_addr, dev, IPPROTO_UDP, skb->mem_len));
 252   tmp = sk->prot->build_header(skb, saddr, sin->sin_addr.s_addr,
 253                                &dev, IPPROTO_UDP, sk->opt, skb->mem_len,sk->ip_tos,sk->ip_ttl);
 254   skb->sk=sk;   /* So memory is freed correctly */
 255                             
 256   if (tmp < 0 ) {
 257         sk->prot->wfree(sk, skb->mem_addr, skb->mem_len);
 258         return(tmp);
 259   }
 260   buff += tmp;
 261   saddr = dev->pa_addr;
 262   DPRINTF((DBG_UDP, "UDP: >> MAC+IP len=%d\n", tmp));
 263 
 264   skb->len = tmp + sizeof(struct udphdr) + len; /* len + UDP + IP + MAC */
 265   skb->dev = dev;
 266 #ifdef OLD
 267   /*
 268    * This code used to hack in some form of fragmentation.
 269    * I removed that, since it didn't work anyway, and it made the
 270    * code a bad thing to read and understand. -FvK
 271    */
 272   if (len > dev->mtu) {
 273 #else
 274   if (skb->len > 4095)
 275   {
 276 #endif    
 277         printk("UDP: send: length %d > mtu %d (ignored)\n", len, dev->mtu);
 278         sk->prot->wfree(sk, skb->mem_addr, skb->mem_len);
 279         return(-EMSGSIZE);
 280   }
 281 
 282   /* Fill in the UDP header. */
 283   uh = (struct udphdr *) buff;
 284   uh->len = htons(len + sizeof(struct udphdr));
 285   uh->source = sk->dummy_th.source;
 286   uh->dest = sin->sin_port;
 287   buff = (unsigned char *) (uh + 1);
 288 
 289   /* Copy the user data. */
 290   memcpy_fromfs(buff, from, len);
 291 
 292   /* Set up the UDP checksum. */
 293   udp_send_check(uh, saddr, sin->sin_addr.s_addr, skb->len - tmp, sk);
 294 
 295   /* Send the datagram to the interface. */
 296   sk->prot->queue_xmit(sk, dev, skb, 1);
 297 
 298   return(len);
 299 }
 300 
 301 
 302 static int
 303 udp_sendto(struct sock *sk, unsigned char *from, int len, int noblock,
     /* [previous][next][first][last][top][bottom][index][help] */
 304            unsigned flags, struct sockaddr_in *usin, int addr_len)
 305 {
 306   struct sockaddr_in sin;
 307   int tmp;
 308   int err;
 309 
 310   DPRINTF((DBG_UDP, "UDP: sendto(len=%d, flags=%X)\n", len, flags));
 311 
 312   /* Check the flags. */
 313   if (flags) 
 314         return(-EINVAL);
 315   if (len < 0) 
 316         return(-EINVAL);
 317   if (len == 0) 
 318         return(0);
 319 
 320   /* Get and verify the address. */
 321   if (usin) {
 322         if (addr_len < sizeof(sin)) return(-EINVAL);
 323         err=verify_area(VERIFY_READ, usin, sizeof(sin));
 324         if(err)
 325                 return err;
 326         memcpy_fromfs(&sin, usin, sizeof(sin));
 327         if (sin.sin_family && sin.sin_family != AF_INET) 
 328                 return(-EINVAL);
 329         if (sin.sin_port == 0) 
 330                 return(-EINVAL);
 331   } else {
 332         if (sk->state != TCP_ESTABLISHED) return(-EINVAL);
 333         sin.sin_family = AF_INET;
 334         sin.sin_port = sk->dummy_th.dest;
 335         sin.sin_addr.s_addr = sk->daddr;
 336   }
 337   
 338   if(!sk->broadcast && chk_addr(sin.sin_addr.s_addr)==IS_BROADCAST)
 339         return -EACCES;                 /* Must turn broadcast on first */
 340   sk->inuse = 1;
 341 
 342   /* Send the packet. */
 343   tmp = udp_send(sk, &sin, from, len);
 344 
 345   /* The datagram has been sent off.  Release the socket. */
 346   release_sock(sk);
 347   return(tmp);
 348 }
 349 
 350 
 351 static int
 352 udp_write(struct sock *sk, unsigned char *buff, int len, int noblock,
     /* [previous][next][first][last][top][bottom][index][help] */
 353           unsigned flags)
 354 {
 355   return(udp_sendto(sk, buff, len, noblock, flags, NULL, 0));
 356 }
 357 
 358 
 359 int
 360 udp_ioctl(struct sock *sk, int cmd, unsigned long arg)
     /* [previous][next][first][last][top][bottom][index][help] */
 361 {
 362   int err;
 363   switch(cmd) {
 364         case DDIOCSDBG:
 365                 {
 366                         int val;
 367 
 368                         if (!suser()) return(-EPERM);
 369                         err=verify_area(VERIFY_READ, (void *)arg, sizeof(int));
 370                         if(err)
 371                                 return err;
 372                         val = get_fs_long((int *)arg);
 373                         switch(val) {
 374                                 case 0:
 375                                         inet_debug = 0;
 376                                         break;
 377                                 case 1:
 378                                         inet_debug = DBG_UDP;
 379                                         break;
 380                                 default:
 381                                         return(-EINVAL);
 382                         }
 383                 }
 384                 break;
 385         case TIOCOUTQ:
 386                 {
 387                         unsigned long amount;
 388 
 389                         if (sk->state == TCP_LISTEN) return(-EINVAL);
 390                         amount = sk->prot->wspace(sk)/*/2*/;
 391                         err=verify_area(VERIFY_WRITE,(void *)arg,
 392                                         sizeof(unsigned long));
 393                         if(err)
 394                                 return(err);
 395                         put_fs_long(amount,(unsigned long *)arg);
 396                         return(0);
 397                 }
 398 
 399         case TIOCINQ:
 400                 {
 401                         struct sk_buff *skb;
 402                         unsigned long amount;
 403 
 404                         if (sk->state == TCP_LISTEN) return(-EINVAL);
 405                         amount = 0;
 406                         skb = sk->rqueue;
 407                         if (skb != NULL) {
 408                                 /*
 409                                  * We will only return the amount
 410                                  * of this packet since that is all
 411                                  * that will be read.
 412                                  */
 413                                 amount = skb->len;
 414                         }
 415                         err=verify_area(VERIFY_WRITE,(void *)arg,
 416                                                 sizeof(unsigned long));
 417                         if(err)
 418                                 return(err);
 419                         put_fs_long(amount,(unsigned long *)arg);
 420                         return(0);
 421                 }
 422 
 423         default:
 424                 return(-EINVAL);
 425   }
 426   return(0);
 427 }
 428 
 429 
 430 /*
 431  * This should be easy, if there is something there we\
 432  * return it, otherwise we block.
 433  */
 434 int
 435 udp_recvfrom(struct sock *sk, unsigned char *to, int len,
     /* [previous][next][first][last][top][bottom][index][help] */
 436              int noblock, unsigned flags, struct sockaddr_in *sin,
 437              int *addr_len)
 438 {
 439   int copied = 0;
 440   struct sk_buff *skb;
 441   int er;
 442 
 443 
 444   /*
 445    * This will pick up errors that occured while the program
 446    * was doing something else.
 447    */
 448   if (sk->err) {
 449         int err;
 450 
 451         err = -sk->err;
 452         sk->err = 0;
 453         return(err);
 454   }
 455 
 456   if (len == 0) 
 457         return(0);
 458   if (len < 0) 
 459         return(-EINVAL);
 460 
 461   if (addr_len) {
 462         er=verify_area(VERIFY_WRITE, addr_len, sizeof(*addr_len));
 463         if(er)
 464                 return(er);
 465         put_fs_long(sizeof(*sin), addr_len);
 466   }
 467   if(sin)
 468   {
 469         er=verify_area(VERIFY_WRITE, sin, sizeof(*sin));
 470         if(er)
 471                 return(er);
 472   }
 473   er=verify_area(VERIFY_WRITE,to,len);
 474   if(er)
 475         return er;
 476   skb=skb_recv_datagram(sk,flags,noblock,&er);
 477   if(skb==NULL)
 478         return er;
 479   copied = min(len, skb->len);
 480 
 481   /* FIXME : should use udp header size info value */
 482   skb_copy_datagram(skb,sizeof(struct udphdr),to,copied);
 483 
 484   /* Copy the address. */
 485   if (sin) {
 486         struct sockaddr_in addr;
 487 
 488         addr.sin_family = AF_INET;
 489         addr.sin_port = skb->h.uh->source;
 490         addr.sin_addr.s_addr = skb->daddr;
 491         memcpy_tofs(sin, &addr, sizeof(*sin));
 492   }
 493   
 494   skb_free_datagram(skb);
 495   release_sock(sk);
 496   return(copied);
 497 }
 498 
 499 
 500 int
 501 udp_read(struct sock *sk, unsigned char *buff, int len, int noblock,
     /* [previous][next][first][last][top][bottom][index][help] */
 502          unsigned flags)
 503 {
 504   return(udp_recvfrom(sk, buff, len, noblock, flags, NULL, NULL));
 505 }
 506 
 507 
 508 int
 509 udp_connect(struct sock *sk, struct sockaddr_in *usin, int addr_len)
     /* [previous][next][first][last][top][bottom][index][help] */
 510 {
 511   struct sockaddr_in sin;
 512   int er;
 513   
 514   if (addr_len < sizeof(sin)) 
 515         return(-EINVAL);
 516 
 517   er=verify_area(VERIFY_READ, usin, sizeof(sin));
 518   if(er)
 519         return er;
 520 
 521   memcpy_fromfs(&sin, usin, sizeof(sin));
 522   if (sin.sin_family && sin.sin_family != AF_INET) 
 523         return(-EAFNOSUPPORT);
 524 
 525   if(!sk->broadcast && chk_addr(sin.sin_addr.s_addr)==IS_BROADCAST)
 526         return -EACCES;                 /* Must turn broadcast on first */
 527         
 528   sk->daddr = sin.sin_addr.s_addr;
 529   sk->dummy_th.dest = sin.sin_port;
 530   sk->state = TCP_ESTABLISHED;
 531   return(0);
 532 }
 533 
 534 
 535 static void
 536 udp_close(struct sock *sk, int timeout)
     /* [previous][next][first][last][top][bottom][index][help] */
 537 {
 538   sk->inuse = 1;
 539   sk->state = TCP_CLOSE;
 540   if (sk->dead) destroy_sock(sk);
 541     else release_sock(sk);
 542 }
 543 
 544 
 545 /* All we need to do is get the socket, and then do a checksum. */
 546 int
 547 udp_rcv(struct sk_buff *skb, struct device *dev, struct options *opt,
     /* [previous][next][first][last][top][bottom][index][help] */
 548         unsigned long daddr, unsigned short len,
 549         unsigned long saddr, int redo, struct inet_protocol *protocol)
 550 {
 551   struct sock *sk;
 552   struct udphdr *uh;
 553 
 554   uh = (struct udphdr *) skb->h.uh;
 555   sk = get_sock(&udp_prot, uh->dest, saddr, uh->source, daddr);
 556   if (sk == NULL) 
 557   {
 558         if (chk_addr(daddr) == IS_MYADDR) 
 559         {
 560                 icmp_send(skb, ICMP_DEST_UNREACH, ICMP_PORT_UNREACH, dev);
 561         }
 562         /*
 563          * Hmm.  We got an UDP broadcast to a port to which we
 564          * don't wanna listen.  The only thing we can do now is
 565          * to ignore the packet... -FvK
 566          */
 567         skb->sk = NULL;
 568         kfree_skb(skb, FREE_WRITE);
 569         return(0);
 570   }
 571 
 572   if (uh->check && udp_check(uh, len, saddr, daddr)) {
 573         DPRINTF((DBG_UDP, "UDP: bad checksum\n"));
 574         skb->sk = NULL;
 575         kfree_skb(skb, FREE_WRITE);
 576         return(0);
 577   }
 578 
 579   skb->sk = sk;
 580   skb->dev = dev;
 581   skb->len = len;
 582 
 583 /* These are supposed to be switched. */
 584   skb->daddr = saddr;
 585   skb->saddr = daddr;
 586 
 587 
 588   /* Charge it to the socket. */
 589   if (sk->rmem_alloc + skb->mem_len >= sk->rcvbuf) 
 590   {
 591         skb->sk = NULL;
 592         kfree_skb(skb, FREE_WRITE);
 593         release_sock(sk);
 594         return(0);
 595   }
 596   sk->rmem_alloc += skb->mem_len;
 597 
 598   /* At this point we should print the thing out. */
 599   DPRINTF((DBG_UDP, "<< \n"));
 600   print_udp(uh);
 601 
 602   /* Now add it to the data chain and wake things up. */
 603   
 604   skb_queue_tail(&sk->rqueue,skb);
 605 
 606   skb->len = len - sizeof(*uh);
 607 
 608   if (!sk->dead) 
 609         sk->data_ready(sk,skb->len);
 610         
 611   release_sock(sk);
 612   return(0);
 613 }
 614 
 615 
 616 struct proto udp_prot = {
 617   sock_wmalloc,
 618   sock_rmalloc,
 619   sock_wfree,
 620   sock_rfree,
 621   sock_rspace,
 622   sock_wspace,
 623   udp_close,
 624   udp_read,
 625   udp_write,
 626   udp_sendto,
 627   udp_recvfrom,
 628   ip_build_header,
 629   udp_connect,
 630   NULL,
 631   ip_queue_xmit,
 632   ip_retransmit,
 633   NULL,
 634   NULL,
 635   udp_rcv,
 636   datagram_select,
 637   udp_ioctl,
 638   NULL,
 639   NULL,
 640   ip_setsockopt,
 641   ip_getsockopt,
 642   128,
 643   0,
 644   {NULL,},
 645   "UDP"
 646 };

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