|
|
1.1 ! root 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 [email protected] 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) ! 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) ! 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, ! 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, ! 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, ! 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, ! 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, ! 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, ! 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, ! 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, ! 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) ! 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) ! 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, ! 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:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.