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_select
  3. udp_err
  4. udp_check
  5. udp_send_check
  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

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

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