|
|
1.1 ! root 1: /* ip.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 <asm/segment.h> ! 24: #include <asm/system.h> ! 25: #include <linux/types.h> ! 26: #include <linux/kernel.h> ! 27: #include <linux/sched.h> ! 28: #include <linux/string.h> ! 29: #include <linux/socket.h> ! 30: #include <netinet/in.h> ! 31: #include "timer.h" ! 32: #include "ip.h" ! 33: #include "tcp.h" ! 34: #include "sock.h" ! 35: #include <linux/errno.h> ! 36: #include "arp.h" ! 37: #include "icmp.h" ! 38: ! 39: unsigned long ip_addr[MAX_IP_ADDRES]={0,0,0}; ! 40: ! 41: #undef IP_DEBUG ! 42: #ifdef IP_DEBUG ! 43: #define PRINTK printk ! 44: #else ! 45: #define PRINTK dummy_routine ! 46: #endif ! 47: ! 48: static struct rtable *rt_base=NULL; /* used to base all the routing data. */ ! 49: ! 50: struct ip_protocol *ip_protos[MAX_IP_PROTOS] = { NULL, }; ! 51: ! 52: #if 0 ! 53: static struct ip_protocol * ! 54: get_protocol(unsigned char prot) ! 55: { ! 56: unsigned char hash; ! 57: struct ip_protocol *p; ! 58: PRINTK ("get_protocol (%d)\n ", prot); ! 59: hash = prot & (MAX_IP_PROTOS -1); ! 60: for (p = ip_protos[hash] ; p != NULL; p=p->next) ! 61: { ! 62: PRINTK ("trying protocol %d\n", p->protocol); ! 63: if (p->protocol == prot) ! 64: return (p); ! 65: } ! 66: return (NULL); ! 67: ! 68: } ! 69: #endif ! 70: ! 71: void ! 72: add_ip_protocol (struct ip_protocol *prot) ! 73: { ! 74: unsigned char hash; ! 75: struct ip_protocol *p2; ! 76: hash = prot->protocol & (MAX_IP_PROTOS-1); ! 77: prot ->next = ip_protos[hash]; ! 78: ip_protos[hash] = prot; ! 79: prot->copy = 0; ! 80: /* set the copy bit if we need to. */ ! 81: for (p2 = prot->next; p2 != NULL; p2=p2->next) ! 82: { ! 83: if (p2->protocol == prot->protocol) ! 84: { ! 85: prot->copy = 1; ! 86: break; ! 87: } ! 88: } ! 89: ! 90: } ! 91: ! 92: int ! 93: delete_ip_protocol (struct ip_protocol *prot) ! 94: { ! 95: struct ip_protocol *p; ! 96: struct ip_protocol *lp=NULL; ! 97: unsigned char hash; ! 98: ! 99: ! 100: hash = prot->protocol & (MAX_IP_PROTOS -1); ! 101: if (prot == ip_protos[hash]) ! 102: { ! 103: ip_protos[hash]=ip_protos[hash]->next; ! 104: return (0); ! 105: } ! 106: ! 107: for (p = ip_protos[hash]; p != NULL; p = p->next) ! 108: { ! 109: /* we have to worry if the protocol being deleted is the ! 110: last one on the list, then we may need to reset someones ! 111: copied bit. */ ! 112: if (p->next != NULL && p->next == prot) ! 113: { ! 114: /* if we are the last one with this protocol and ! 115: there is a previous one, reset its copy bit. */ ! 116: ! 117: if (p->copy == 0 && lp != NULL) ! 118: lp->copy = 0; ! 119: p->next = prot->next; ! 120: return (0); ! 121: } ! 122: ! 123: if (p->next != NULL && p->next->protocol == prot->protocol) ! 124: { ! 125: lp = p; ! 126: } ! 127: } ! 128: return (-1); ! 129: } ! 130: ! 131: /* addr1 is the address which may or may not be broadcast etc. ! 132: addr2 is the "real addr." */ ! 133: ! 134: int ! 135: ip_addr_match (unsigned long addr1, unsigned long addr2) ! 136: { ! 137: int i; ! 138: if (addr1 == addr2) return (1); ! 139: for (i = 0; i < 4; i++, addr1 >>= 8, addr2 >>= 8) ! 140: { ! 141: if ((addr1 & 0xff) != (addr2 & 0xff)) ! 142: { ! 143: /* the only way this could be a match is for the rest of ! 144: addr1 to be 0. */ ! 145: if (addr1 != 0) ! 146: { ! 147: return (0); ! 148: } ! 149: return (1); ! 150: } ! 151: } ! 152: return (1); ! 153: } ! 154: ! 155: int ! 156: my_ip_addr(unsigned long addr) ! 157: { ! 158: int i; ! 159: for (i = 0; i < MAX_IP_ADDRES; i++) ! 160: { ! 161: if (ip_addr[i] == 0) return (0); ! 162: if (ip_addr_match (addr, ip_addr[i])) return (1); ! 163: } ! 164: return (0); ! 165: } ! 166: ! 167: /* these two routines will do routining. */ ! 168: static void ! 169: strict_route(struct ip_header *iph, struct options *opt) ! 170: { ! 171: } ! 172: ! 173: static void ! 174: loose_route(struct ip_header *iph, struct options *opt) ! 175: { ! 176: } ! 177: ! 178: void ! 179: print_rt(struct rtable *rt) ! 180: { ! 181: PRINTK ("net = %08X router = %08X\n",rt->net, rt->router); ! 182: PRINTK ("dev = %X, next = %X\n",rt->dev, rt->next); ! 183: } ! 184: ! 185: void ! 186: print_ipprot (struct ip_protocol *ipprot) ! 187: { ! 188: PRINTK ("handler = %X, protocol = %d\n", ! 189: ipprot->handler, ipprot->protocol); ! 190: } ! 191: ! 192: /* This assumes that address are all in net order. */ ! 193: static struct device * ! 194: ip_route(struct options *opt, unsigned long daddr , unsigned long *raddr) ! 195: { ! 196: struct rtable *rt; ! 197: /* look through the routing table for some ! 198: kind of match. */ ! 199: for (rt=rt_base; rt != NULL; rt=rt->next) ! 200: { ! 201: /* see if we found one. */ ! 202: if (ip_addr_match (rt->net, daddr)) ! 203: { ! 204: *raddr = rt->router; ! 205: return (rt->dev); ! 206: } ! 207: } ! 208: return (NULL); ! 209: }; ! 210: ! 211: void ! 212: add_route (struct rtable *rt) ! 213: { ! 214: int mask; ! 215: struct rtable *r; ! 216: struct rtable *r1; ! 217: PRINTK ("add_route (rt=%X):\n",rt); ! 218: print_rt(rt); ! 219: ! 220: if (rt_base == NULL) ! 221: { ! 222: rt->next = NULL; ! 223: rt_base = rt; ! 224: return; ! 225: } ! 226: ! 227: /* what we have to do is loop though this until we have found the ! 228: first address which has the same generality as the one in rt. Then ! 229: we can put rt in after it. */ ! 230: for (mask = 0xff000000; mask != 0xffffffff; mask = (mask >> 8) | mask) ! 231: { ! 232: if (mask & rt->net) ! 233: { ! 234: mask = mask << 8; ! 235: break; ! 236: } ! 237: } ! 238: PRINTK ("mask = %X\n",mask); ! 239: r1=rt_base; ! 240: for (r=rt_base; r != NULL; r=r->next) ! 241: { ! 242: /* see if we are getting a duplicate. */ ! 243: if (r->net == rt->net) ! 244: { ! 245: if (r == rt_base) ! 246: { ! 247: rt->next = r->next; ! 248: rt_base = rt; ! 249: } ! 250: else ! 251: { ! 252: rt->next = r->next; ! 253: r1->next = rt; ! 254: } ! 255: free_s (r, sizeof (*r)); ! 256: return; ! 257: } ! 258: ! 259: if (!(r->net & mask)) ! 260: { ! 261: PRINTK("adding before r=%X\n",r); ! 262: print_rt(r); ! 263: if (r == rt_base) ! 264: { ! 265: rt->next = rt_base; ! 266: rt_base = rt; ! 267: return; ! 268: } ! 269: rt->next = r; ! 270: r1->next = rt; ! 271: return; ! 272: } ! 273: r1 = r; ! 274: } ! 275: PRINTK ("adding after r1=%X\n",r1); ! 276: print_rt(r1); ! 277: /* goes at the end. */ ! 278: rt->next = NULL; ! 279: r1->next = rt; ! 280: } ! 281: ! 282: int ! 283: ip_set_dev (struct ip_config *u_ipc) ! 284: { ! 285: struct rtable *rt; ! 286: struct device *dev; ! 287: struct ip_config ipc; ! 288: static int ip_ads = 0; ! 289: ! 290: if (ip_ads >= MAX_IP_ADDRES) return (-EINVAL); ! 291: ! 292: verify_area (u_ipc, sizeof (ipc)); ! 293: memcpy_fromfs(&ipc, u_ipc, sizeof (ipc)); ! 294: ipc.name[MAX_IP_NAME-1] = 0; ! 295: dev = get_dev (ipc.name); ! 296: ! 297: if (dev == NULL) return (-EINVAL); ! 298: ! 299: /* see if we need to add a broadcast address. */ ! 300: if (ipc.net != -1) ! 301: { ! 302: arp_add_broad (ipc.net, dev); ! 303: rt = malloc (sizeof (*rt)); ! 304: if (rt == NULL) return (-ENOMEM); ! 305: ! 306: rt->net = ipc.net; ! 307: rt->dev = dev; ! 308: rt->router = 0; ! 309: add_route (rt); ! 310: /* dev->net = ipc.net;*/ ! 311: } ! 312: ! 313: if (ipc.router != -1) ! 314: { ! 315: rt = malloc (sizeof (*rt)); ! 316: if (rt == NULL) return (-ENOMEM); ! 317: rt->net = 0; ! 318: rt->dev = dev; ! 319: rt->router = ipc.router; ! 320: add_route (rt); ! 321: } ! 322: ! 323: if (dev->loopback) ! 324: { ! 325: rt = malloc (sizeof (*rt)); ! 326: if (rt == NULL) return (-ENOMEM); ! 327: rt->net = ipc.paddr; ! 328: rt->dev = dev; ! 329: rt->router = 0; ! 330: add_route (rt); ! 331: ! 332: } ! 333: ! 334: ! 335: if (!my_ip_addr (ipc.paddr)) ! 336: ip_addr[ip_ads++] = ipc.paddr; ! 337: ! 338: dev->up = ipc.up; ! 339: if (dev->up) ! 340: { ! 341: if (dev->open) ! 342: dev->open(dev); ! 343: } ! 344: else ! 345: { ! 346: if (dev->stop) ! 347: dev->stop(dev); ! 348: } ! 349: return (0); ! 350: ! 351: } ! 352: ! 353: /* this routine will check to see if we have lost a gateway. */ ! 354: void ! 355: ip_route_check (unsigned long daddr) ! 356: { ! 357: } ! 358: ! 359: /* this routine puts the options at the end of an ip header. */ ! 360: static int ! 361: build_options (struct ip_header *iph, struct options *opt) ! 362: { ! 363: unsigned char *ptr; ! 364: /* currently we don't support any options. */ ! 365: ptr = (unsigned char *)(iph+1); ! 366: *ptr = 0; ! 367: return (4); ! 368: } ! 369: ! 370: /* This routine builds the appropriate hardware/ip headers for ! 371: the routine. It assumes that if *prot != NULL then the ! 372: protocol knows what it's doing, otherwise it uses the ! 373: routing/arp tables to select a protocol struct. */ ! 374: ! 375: int ! 376: ip_build_header (struct sk_buff *skb, unsigned long saddr, ! 377: unsigned long daddr, struct device **dev, int type, ! 378: struct options *opt, int len) ! 379: { ! 380: static struct options optmem; ! 381: struct ip_header *iph; ! 382: unsigned char *buff; ! 383: static int count = 0; ! 384: unsigned long raddr; /* for the router. */ ! 385: int tmp; ! 386: if (saddr == 0) saddr = MY_IP_ADDR; ! 387: PRINTK ("ip_build_header (skb=%X, saddr=%X, daddr=%X, *dev=%X,\n" ! 388: " type=%d, opt=%X, len = %d)\n", ! 389: skb, saddr, daddr, *dev, type, opt, len); ! 390: buff = (unsigned char *)(skb + 1); ! 391: /* see if we need to look up the device. */ ! 392: if (*dev == NULL) ! 393: { ! 394: *dev = ip_route(&optmem,daddr, &raddr); ! 395: if (*dev == NULL) ! 396: { ! 397: return (-ENETUNREACH); ! 398: } ! 399: opt = &optmem; ! 400: } ! 401: else ! 402: { ! 403: /* we still need the address of the first hop. */ ! 404: ip_route (&optmem, daddr, &raddr); ! 405: } ! 406: if (raddr == 0) raddr = daddr; ! 407: /* now build the header. */ ! 408: /* we need to worry about routing in here. daddr should ! 409: really be the address of the next hop. */ ! 410: /* but raddr is . */ ! 411: if ((*dev)->hard_header) ! 412: { ! 413: tmp = (*dev)->hard_header(buff, *dev, ETHERTYPE_IP, raddr, saddr, len); ! 414: } ! 415: else ! 416: { ! 417: tmp = 0; ! 418: } ! 419: if (tmp < 0) ! 420: { ! 421: tmp = -tmp; ! 422: skb->arp = 0; ! 423: } ! 424: else ! 425: { ! 426: skb->arp = 1; ! 427: } ! 428: buff += tmp; ! 429: len -= tmp; ! 430: skb->dev = *dev; ! 431: /* now build the ip header. */ ! 432: iph = (struct ip_header *)buff; ! 433: iph->version = 4; ! 434: iph->tos = 0; ! 435: iph->frag_off = 0; ! 436: iph->ttl = 32; ! 437: iph->daddr = daddr; ! 438: iph->saddr = saddr; ! 439: iph->protocol=type; ! 440: iph->ihl = 5; ! 441: iph->id = net16(count++); ! 442: /* build_options (iph, opt);*/ ! 443: return (20+tmp); ! 444: } ! 445: ! 446: static int ! 447: do_options(struct ip_header *iph, struct options *opt) ! 448: { ! 449: unsigned char *buff; ! 450: int done = 0; ! 451: int len=sizeof (*iph); ! 452: int i; ! 453: /* zero out the options. */ ! 454: opt->record_route.route_size = 0; ! 455: opt->loose_route.route_size = 0; ! 456: opt->strict_route.route_size = 0; ! 457: opt->tstamp.ptr = 0; ! 458: opt->security = 0; ! 459: opt->compartment = 0; ! 460: opt->handling = 0; ! 461: opt->stream = 0; ! 462: opt->tcc = 0; ! 463: return (0); ! 464: /* advance the pointer to start at the options. */ ! 465: buff = (unsigned char *)(iph + 1); ! 466: ! 467: /*now start the processing. */ ! 468: while (!done && len < iph->ihl*4) ! 469: { ! 470: switch (*buff) ! 471: { ! 472: case IPOPT_END: ! 473: done=1; ! 474: break; ! 475: ! 476: case IPOPT_NOOP: ! 477: buff++; ! 478: len ++; ! 479: break; ! 480: ! 481: case IPOPT_SEC: ! 482: buff++; ! 483: if (*buff != 11) ! 484: return (1); ! 485: buff++; ! 486: opt->security = net16(*(unsigned short *)buff); ! 487: buff += 2; ! 488: opt->compartment = net16(*(unsigned short *)buff); ! 489: buff += 2; ! 490: opt-> handling = net16(*(unsigned short *)buff); ! 491: buff += 2; ! 492: opt->tcc = ((*buff) << 16) + net16(*(unsigned short *)(buff+1)); ! 493: buff += 3; ! 494: len += 11; ! 495: break; ! 496: ! 497: case IPOPT_LSRR: ! 498: buff ++; ! 499: if ((*buff - 3)% 4 != 0) return (1); ! 500: len += *buff; ! 501: opt->loose_route.route_size = (*buff -3)/4; ! 502: buff ++; ! 503: if (*buff % 4 != 0) return (1); ! 504: opt->loose_route.pointer = *buff/4 - 1; ! 505: buff ++; ! 506: buff ++; ! 507: for (i = 0; i < opt->loose_route.route_size; i++) ! 508: { ! 509: opt->loose_route.route[i]=*(unsigned long *)buff; ! 510: buff += 4; ! 511: } ! 512: break; ! 513: ! 514: ! 515: case IPOPT_SSRR: ! 516: buff ++; ! 517: if ((*buff - 3)% 4 != 0) return (1); ! 518: len += *buff; ! 519: opt->strict_route.route_size = (*buff -3)/4; ! 520: buff ++; ! 521: if (*buff % 4 != 0) return (1); ! 522: opt->strict_route.pointer = *buff/4 - 1; ! 523: buff ++; ! 524: buff ++; ! 525: for (i = 0; i < opt->strict_route.route_size; i++) ! 526: { ! 527: opt->strict_route.route[i]=*(unsigned long *)buff; ! 528: buff += 4; ! 529: } ! 530: break; ! 531: ! 532: case IPOPT_RR: ! 533: buff ++; ! 534: if ((*buff - 3)% 4 != 0) return (1); ! 535: len += *buff; ! 536: opt->record_route.route_size = (*buff -3)/4; ! 537: buff ++; ! 538: if (*buff % 4 != 0) return (1); ! 539: opt->record_route.pointer = *buff/4 - 1; ! 540: buff ++; ! 541: buff ++; ! 542: for (i = 0; i < opt->record_route.route_size; i++) ! 543: { ! 544: opt->record_route.route[i]=*(unsigned long *)buff; ! 545: buff += 4; ! 546: } ! 547: break; ! 548: ! 549: case IPOPT_SID: ! 550: len += 4; ! 551: buff +=2; ! 552: opt->stream = *(unsigned short *)buff; ! 553: buff += 2; ! 554: break; ! 555: ! 556: case IPOPT_TIMESTAMP: ! 557: buff ++; ! 558: len += *buff; ! 559: if (*buff % 4 != 0) return (1); ! 560: opt->tstamp.len = *buff / 4 - 1; ! 561: buff ++; ! 562: if ((*buff - 1) % 4 != 0) return (1); ! 563: opt->tstamp.ptr = (*buff-1)/4; ! 564: buff ++; ! 565: opt->tstamp.x.full_char = *buff; ! 566: buff ++; ! 567: for (i = 0; i < opt->tstamp.len; i++) ! 568: { ! 569: opt->tstamp.data[i] = *(unsigned long *)buff; ! 570: buff += 4; ! 571: } ! 572: break; ! 573: ! 574: default: ! 575: return (1); ! 576: } ! 577: } ! 578: if (opt->record_route.route_size == 0) ! 579: { ! 580: if (opt->strict_route.route_size != 0) ! 581: { ! 582: memcpy (&(opt->record_route), &(opt->strict_route), ! 583: sizeof (opt->record_route)); ! 584: } ! 585: else if (opt->loose_route.route_size != 0) ! 586: { ! 587: memcpy (&(opt->record_route), &(opt->loose_route), ! 588: sizeof (opt->record_route)); ! 589: } ! 590: } ! 591: ! 592: if (opt->strict_route.route_size != 0 && ! 593: opt->strict_route.route_size != opt->strict_route.pointer) ! 594: { ! 595: strict_route (iph, opt); ! 596: return (0); ! 597: } ! 598: ! 599: if (opt->loose_route.route_size != 0 && ! 600: opt->loose_route.route_size != opt->loose_route.pointer) ! 601: { ! 602: loose_route (iph, opt); ! 603: return (0); ! 604: } ! 605: ! 606: return (0); ! 607: } ! 608: ! 609: ! 610: /* This routine does all the checksum computations that don't require ! 611: anything special (like copying or special headers.) */ ! 612: ! 613: unsigned short ! 614: ip_compute_csum(unsigned char * buff, int len) ! 615: { ! 616: unsigned long sum = 0; ! 617: if (len > 3) ! 618: { ! 619: /* do the first multiple of 4 bytes and convert to 16 bits. */ ! 620: __asm__("\t clc\n" ! 621: "1:\n" ! 622: "\t lodsl\n" ! 623: "\t adcl %%eax, %%ebx\n" ! 624: "\t loop 1b\n" ! 625: "\t adcl $0, %%ebx\n" ! 626: "\t movl %%ebx, %%eax\n" ! 627: "\t shrl $16, %%eax\n" ! 628: "\t addw %%ax, %%bx\n" ! 629: "\t adcw $0, %%bx\n" ! 630: : "=b" (sum) , "=S" (buff) ! 631: : "0" (sum), "c" (len >> 2) ,"1" (buff) ! 632: : "ax", "cx", "si", "bx" ); ! 633: } ! 634: if (len & 2) ! 635: { ! 636: __asm__("\t lodsw\n" ! 637: "\t addw %%ax, %%bx\n" ! 638: "\t adcw $0, %%bx\n" ! 639: : "=b" (sum), "=S" (buff) ! 640: : "0" (sum), "1" (buff) ! 641: : "bx", "ax", "si"); ! 642: } ! 643: if (len & 1) ! 644: { ! 645: __asm__("\t lodsb\n" ! 646: "\t movb $0, %%ah\n" ! 647: "\t addw %%ax, %%bx\n" ! 648: "\t adcw $0, %%bx\n" ! 649: : "=b" (sum), "=S" (buff) ! 650: : "0" (sum), "1" (buff) ! 651: : "bx", "ax", "si"); ! 652: } ! 653: sum =~sum; ! 654: return (sum&0xffff); ! 655: } ! 656: ! 657: static int ! 658: ip_csum(struct ip_header *iph) ! 659: { ! 660: if (iph->check == 0) return (0); ! 661: if (ip_compute_csum((unsigned char *)iph, iph->ihl*4) == 0) return (0); ! 662: return (1); ! 663: } ! 664: ! 665: static void ! 666: ip_send_check(struct ip_header *iph) ! 667: { ! 668: iph->check = 0; ! 669: iph->check = ip_compute_csum((unsigned char *)iph, iph->ihl*4); ! 670: } ! 671: ! 672: int ! 673: ip_rcv(struct sk_buff *skb, struct device *dev, struct packet_type *pt) ! 674: { ! 675: struct ip_header *iph; ! 676: unsigned char hash; ! 677: unsigned char flag=0; ! 678: static struct options opt; /* since we don't use these yet, and they ! 679: take up stack space. */ ! 680: struct ip_protocol *ipprot; ! 681: ! 682: iph=skb->h.iph; ! 683: ! 684: PRINTK("<<\n"); ! 685: print_iph(iph); ! 686: ! 687: if (ip_csum (iph) || do_options (iph,&opt) || iph->version != 4) ! 688: { ! 689: PRINTK ("ip packet thrown out. \n"); ! 690: skb->sk = NULL; ! 691: free_skb(skb, 0); ! 692: return (0); ! 693: } ! 694: ! 695: /* for now we will only deal with packets meant for us. */ ! 696: if (!my_ip_addr(iph->daddr)) ! 697: { ! 698: PRINTK ("packet meant for someone else.\n"); ! 699: skb->sk = NULL; ! 700: free_skb(skb, 0); ! 701: return (0); ! 702: } ! 703: ! 704: /* deal with fragments. or don't for now.*/ ! 705: if ((iph->frag_off & 64) || (net16(iph->frag_off)&0x1fff)) ! 706: { ! 707: printk ("packet fragmented. \n"); ! 708: skb->sk = NULL; ! 709: free_skb(skb, 0); ! 710: return(0); ! 711: } ! 712: ! 713: skb->h.raw += iph->ihl*4; ! 714: ! 715: /* add it to the arp table if it's talking to us. That way we ! 716: will be able to talk to them also. */ ! 717: ! 718: hash = iph->protocol & (MAX_IP_PROTOS -1); ! 719: for (ipprot = ip_protos[hash]; ipprot != NULL; ipprot=ipprot->next) ! 720: { ! 721: struct sk_buff *skb2; ! 722: PRINTK ("Using protocol = %X:\n", ipprot); ! 723: print_ipprot (ipprot); ! 724: /* pass it off to everyone who wants it. */ ! 725: /* we should check the return values here. */ ! 726: /* see if we need to make a copy of it. This will ! 727: only be set if more than one protpocol wants it. ! 728: and then not for the last one. */ ! 729: ! 730: if (ipprot->copy) ! 731: { ! 732: skb2 = malloc (skb->mem_len); ! 733: if (skb2 == NULL) continue; ! 734: memcpy (skb2, skb, skb->mem_len); ! 735: skb2->mem_addr = skb2; ! 736: } ! 737: else ! 738: { ! 739: skb2 = skb; ! 740: } ! 741: flag = 1; ! 742: ipprot->handler (skb2, dev, &opt, iph->daddr, ! 743: net16(iph->tot_len) - iph->ihl*4, ! 744: iph->saddr, 0, ipprot); ! 745: ! 746: } ! 747: if (!flag) ! 748: { ! 749: icmp_reply (skb, ICMP_DEST_UNREACH, ICMP_PROT_UNREACH, dev); ! 750: skb->sk = NULL; ! 751: free_skb (skb, 0); ! 752: } ! 753: ! 754: ! 755: return (0); ! 756: } ! 757: ! 758: ! 759: /* queues a packet to be sent, and starts the transmitter if ! 760: necessary. if free = 1 then we free the block after transmit, ! 761: otherwise we don't. */ ! 762: /* This routine also needs to put in the total length, and compute ! 763: the checksum. */ ! 764: void ! 765: ip_queue_xmit (volatile struct sock *sk, struct device *dev, ! 766: struct sk_buff *skb, int free) ! 767: { ! 768: struct ip_header *iph; ! 769: unsigned char *ptr; ! 770: if (sk == NULL) free = 1; ! 771: skb->free = free; ! 772: skb->dev = dev; ! 773: skb->when = jiffies; ! 774: PRINTK(">>\n"); ! 775: ptr = (unsigned char *)(skb + 1); ! 776: ptr += dev->hard_header_len; ! 777: iph = (struct ip_header *)ptr; ! 778: iph->tot_len = net16(skb->len-dev->hard_header_len); ! 779: ip_send_check (iph); ! 780: print_iph(iph); ! 781: skb->next = NULL; ! 782: if (!free) ! 783: { ! 784: skb->link3 = NULL; ! 785: sk->packets_out++; ! 786: cli(); ! 787: if (sk->send_tail == NULL) ! 788: { ! 789: sk->send_tail = skb; ! 790: sk->send_head = skb; ! 791: } ! 792: else ! 793: { ! 794: sk->send_tail->link3 = skb; ! 795: sk->send_tail = skb; ! 796: } ! 797: sti(); ! 798: sk->time_wait.len = sk->rtt*2; ! 799: sk->timeout=TIME_WRITE; ! 800: reset_timer ((struct timer *)&sk->time_wait); ! 801: } ! 802: else ! 803: { ! 804: skb->sk = sk; ! 805: } ! 806: if (dev->up) ! 807: { ! 808: if (sk) ! 809: dev->queue_xmit(skb, dev, sk->priority); ! 810: else ! 811: dev->queue_xmit (skb, dev, SOPRI_NORMAL); ! 812: } ! 813: else ! 814: { ! 815: if (free) ! 816: free_skb (skb, FREE_WRITE); ! 817: } ! 818: } ! 819: ! 820: void ! 821: ip_retransmit (volatile struct sock *sk, int all) ! 822: { ! 823: struct sk_buff * skb; ! 824: struct proto *prot; ! 825: struct device *dev; ! 826: ! 827: prot = sk->prot; ! 828: skb = sk->send_head; ! 829: while (skb != NULL) ! 830: { ! 831: dev = skb->dev; ! 832: /* rebuild_header sees if the arp is done. If not it sends a new ! 833: arp, and if so it builds the header. */ ! 834: if (!skb->arp) ! 835: { ! 836: if (dev->rebuild_header ((struct enet_header *)(skb+1),dev)) ! 837: { ! 838: if (!all) break; ! 839: skb=skb->link3; ! 840: continue; ! 841: } ! 842: } ! 843: skb->arp = 1; ! 844: skb->when = jiffies; ! 845: ! 846: if (dev->up) ! 847: if (sk) ! 848: dev->queue_xmit(skb, dev, sk->priority); ! 849: else ! 850: dev->queue_xmit(skb, dev, SOPRI_NORMAL ); ! 851: ! 852: sk->retransmits++; ! 853: sk->prot->retransmits ++; ! 854: if (!all) break; ! 855: /* this should cut it off before we send too ! 856: many packets. */ ! 857: if (sk->retransmits > sk->cong_window) break; ! 858: skb=skb->link3; ! 859: } ! 860: sk->time_wait.len = sk->rtt*2; ! 861: sk->timeout = TIME_WRITE; ! 862: reset_timer ((struct timer *)&sk->time_wait); ! 863: } ! 864: ! 865: void ! 866: print_iph (struct ip_header *ip) ! 867: { ! 868: PRINTK ("ip header:\n"); ! 869: PRINTK (" ihl = %d, version = %d, tos = %d, tot_len = %d\n", ! 870: ip->ihl, ip->version, ip->tos, net16(ip->tot_len)); ! 871: PRINTK (" id = %x, ttl = %d, prot = %d, check=%x\n", ! 872: ip->id, ip->ttl, ip->protocol, ip->check); ! 873: PRINTK (" frag_off=%d\n", ip->frag_off); ! 874: PRINTK (" saddr = %X, daddr = %X\n",ip->saddr, ip->daddr); ! 875: } ! 876: ! 877: #if 0 ! 878: int ! 879: ip_handoff (volatile struct sock *sk) ! 880: { ! 881: struct ip_protocol *p; ! 882: struct sk_buff *skb; ! 883: p = get_protocol (sk->protocol); ! 884: ! 885: if (p == NULL) ! 886: { ! 887: /* this can never happen. */ ! 888: printk ("sock_ioctl: protocol not found. \n"); ! 889: /* what else can I do, I suppose I could send a sigkill. */ ! 890: return (-EIO); ! 891: } ! 892: ! 893: while (p->handler != sk->prot->rcv) ! 894: { ! 895: p=p->next; ! 896: if (p == NULL) ! 897: { ! 898: /* this can never happen. */ ! 899: printk ("sock_ioctl: protocol not found. \n"); ! 900: /* what else can I do, I suppose I could send a sigkill. */ ! 901: return (-EIO); ! 902: } ! 903: } ! 904: p = p-> next; ! 905: sk->inuse = 1; ! 906: ! 907: /* now we have to remove the top sock buff. If there are none, then ! 908: we return. */ ! 909: if (sk->rqueue == NULL) return (0); ! 910: skb = sk->rqueue; ! 911: if (skb->next == skb) ! 912: { ! 913: sk->rqueue = NULL; ! 914: } ! 915: else ! 916: { ! 917: sk->rqueue = skb->next; ! 918: skb->next->prev = skb->prev; ! 919: skb->prev->next = skb->next; ! 920: } ! 921: if (p != NULL) ! 922: { ! 923: p->handler ((unsigned char *)(skb+1), skb->dev, NULL, skb->saddr, ! 924: skb->len, skb->daddr, p->protocol, 0); ! 925: } ! 926: free_skb (skb, FREE_READ); ! 927: release_sock (sk); ! 928: return (0); ! 929: } ! 930: ! 931: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.