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

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