root/net/tcp/udp.c

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

DEFINITIONS

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

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