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

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