📄 ip.c
字号:
403 buff += 4;
404 }
405 break;
406 default:
407 return(1);
408 }
409
410 if (opt->record_route.route_size == 0) {
411 if (opt->strict_route.route_size != 0) {
412 memcpy(&(opt->record_route), &(opt->strict_route),
413 sizeof(opt->record_route));
414 } else if (opt->loose_route.route_size != 0) {
415 memcpy(&(opt->record_route), &(opt->loose_route),
416 sizeof(opt->record_route));
417 }
418 }
419
420 if (opt->strict_route.route_size != 0 &&
421 opt->strict_route.route_size != opt->strict_route.pointer) {
422 strict_route(iph, opt);
423 return(0);
424 }
425
426 if (opt->loose_route.route_size != 0 &&
427 opt->loose_route.route_size != opt->loose_route.pointer) {
428 loose_route(iph, opt);
429 return(0);
430 }
431
432 return(0);
433 }
434
435 /* This is a version of ip_compute_csum() optimized for IP headers, which
436 always checksum on 4 octet boundaries. */
437 static inline unsigned short
438 ip_fast_csum(unsigned char * buff, int wlen)
439 {
440 unsigned long sum = 0;
441
442 if (wlen) {
443 unsigned long bogus;
444 __asm__("clc\n"
445 "1:\t"
446 "lodsl\n\t"
447 "adcl %3, %0\n\t"
448 "decl %2\n\t"
449 "jne 1b\n\t"
450 "adcl $0, %0\n\t"
451 "movl %0, %3\n\t"
452 "shrl $16, %3\n\t"
453 "addw %w3, %w0\n\t"
454 "adcw $0, %w0"
455 : "=r" (sum), "=S" (buff), "=r" (wlen), "=a" (bogus)
456 : "" (sum), "1" (buff), "2" (wlen));
457 }
458 return (~sum) & 0xffff;
459 }
460
461 /*
462 * This routine does all the checksum computations that don't
463 * require anything special (like copying or special headers).
464 */
465 unsigned short
466 ip_compute_csum(unsigned char * buff, int len)
467 {
468 unsigned long sum = 0;
469
470 /* Do the first multiple of 4 bytes and convert to 16 bits. */
471 if (len > 3) {
472 __asm__("clc\n"
473 "1:\t"
474 "lodsl\n\t"
475 "adcl %%eax, %%ebx\n\t"
476 "loop 1b\n\t"
477 "adcl $0, %%ebx\n\t"
478 "movl %%ebx, %%eax\n\t"
479 "shrl $16, %%eax\n\t"
480 "addw %%ax, %%bx\n\t"
481 "adcw $0, %%bx"
482 : "=b" (sum) , "=S" (buff)
483 : "" (sum), "c" (len >> 2) ,"1" (buff)
484 : "ax", "cx", "si", "bx" );
485 }
486 if (len & 2) {
487 __asm__("lodsw\n\t"
488 "addw %%ax, %%bx\n\t"
489 "adcw $0, %%bx"
490 : "=b" (sum), "=S" (buff)
491 : "" (sum), "1" (buff)
492 : "bx", "ax", "si");
493 }
494 if (len & 1) {
495 __asm__("lodsb\n\t"
496 "movb $0, %%ah\n\t"
497 "addw %%ax, %%bx\n\t"
498 "adcw $0, %%bx"
499 : "=b" (sum), "=S" (buff)
500 : "" (sum), "1" (buff)
501 : "bx", "ax", "si");
502 }
503 sum =~sum;
504 return(sum & 0xffff);
505 }
506
507 /* Check the header of an incoming IP datagram. This version is still used in slhc.c. */
508 int
509 ip_csum(struct iphdr *iph)
510 {
511 return ip_fast_csum((unsigned char *)iph, iph->ihl);
512 }
513
514 /* Generate a checksym for an outgoing IP datagram. */
515 static void
516 ip_send_check(struct iphdr *iph)
517 {
518 iph->check = 0;
519 iph->check = ip_fast_csum((unsigned char *)iph, iph->ihl);
520 }
521
522 /************************ Fragment Handlers From NET2E not yet with tweaks to beat 4K **********************************/
523
524 static struct ipq *ipqueue = NULL; /* IP fragment queue */
525 /* Create a new fragment entry. */
526 static struct ipfrag *ip_frag_create(int offset, int end, struct sk_buff *skb, unsigned char *ptr)
527 {
528 struct ipfrag *fp;
529
530 fp = (struct ipfrag *) kmalloc(sizeof(struct ipfrag), GFP_ATOMIC);
531 if (fp == NULL)
532 {
533 printk("IP: frag_create: no memory left !\n");
534 return(NULL);
535 }
536 memset(fp, 0, sizeof(struct ipfrag));
537
538 /* Fill in the structure. */
539 fp->offset = offset;
540 fp->end = end;
541 fp->len = end - offset;
542 fp->skb = skb;
543 fp->ptr = ptr;
544
545 return(fp);
546 }
547
548
549 /*
550 * Find the correct entry in the "incomplete datagrams" queue for
551 * this IP datagram, and return the queue entry address if found.
552 */
553 static struct ipq *ip_find(struct iphdr *iph)
554 {
555 struct ipq *qp;
556 struct ipq *qplast;
557
558 cli();
559 qplast = NULL;
560 for(qp = ipqueue; qp != NULL; qplast = qp, qp = qp->next)
561 {
562 if (iph->id== qp->iph->id && iph->saddr == qp->iph->saddr &&
563 iph->daddr == qp->iph->daddr && iph->protocol == qp->iph->protocol)
564 {
565 del_timer(&qp->timer); /* So it doesnt vanish on us. The timer will be reset anyway */
566 sti();
567 return(qp);
568 }
569 }
570 sti();
571 return(NULL);
572 }
573
574
575 /*
576 * Remove an entry from the "incomplete datagrams" queue, either
577 * because we completed, reassembled and processed it, or because
578 * it timed out.
579 */
580
581 static void ip_free(struct ipq *qp)
582 {
583 struct ipfrag *fp;
584 struct ipfrag *xp;
585
586 /* Stop the timer for this entry. */
587 /* printk("ip_free\n");*/
588 del_timer(&qp->timer);
589
590 /* Remove this entry from the "incomplete datagrams" queue. */
591 cli();
592 if (qp->prev == NULL)
593 {
594 ipqueue = qp->next;
595 if (ipqueue != NULL)
596 ipqueue->prev = NULL;
597 }
598 else
599 {
600 qp->prev->next = qp->next;
601 if (qp->next != NULL)
602 qp->next->prev = qp->prev;
603 }
604
605 /* Release all fragment data. */
606 /* printk("ip_free: kill frag data\n");*/
607 fp = qp->fragments;
608 while (fp != NULL)
609 {
610 xp = fp->next;
611 IS_SKB(fp->skb);
612 kfree_skb(fp->skb,FREE_READ);
613 kfree_s(fp, sizeof(struct ipfrag));
614 fp = xp;
615 }
616
617 /* printk("ip_free: cleanup\n");*/
618
619 /* Release the MAC header. */
620 kfree_s(qp->mac, qp->maclen);
621
622 /* Release the IP header. */
623 kfree_s(qp->iph, qp->ihlen + 8);
624
625 /* Finally, release the queue descriptor itself. */
626 kfree_s(qp, sizeof(struct ipq));
627 /* printk("ip_free:done\n");*/
628 sti();
629 }
630
631
632 /* Oops- a fragment queue timed out. Kill it and send an ICMP reply. */
633
634 static void ip_expire(unsigned long arg)
635 {
636 struct ipq *qp;
637
638 qp = (struct ipq *)arg;
639 DPRINTF((DBG_IP, "IP: queue_expire: fragment queue 0x%X timed out!\n", qp));
640
641 /* Send an ICMP "Fragment Reassembly Timeout" message. */
642 #if 0
643 icmp_send(qp->iph->ip_src.s_addr, ICMP_TIME_EXCEEDED,
644 ICMP_EXC_FRAGTIME, qp->iph);
645 #endif
646 if(qp->fragments!=NULL)
647 icmp_send(qp->fragments->skb,ICMP_TIME_EXCEEDED,
648 ICMP_EXC_FRAGTIME, qp->dev);
649
650 /* Nuke the fragment queue. */
651 ip_free(qp);
652 }
653
654
655 /*
656 * Add an entry to the 'ipq' queue for a newly received IP datagram.
657 * We will (hopefully :-) receive all other fragments of this datagram
658 * in time, so we just create a queue for this datagram, in which we
659 * will insert the received fragments at their respective positions.
660 */
661
662 static struct ipq *ip_create(struct sk_buff *skb, struct iphdr *iph, struct device *dev)
663 {
664 struct ipq *qp;
665 int maclen;
666 int ihlen;
667
668 qp = (struct ipq *) kmalloc(sizeof(struct ipq), GFP_ATOMIC);
669 if (qp == NULL)
670 {
671 printk("IP: create: no memory left !\n");
672 return(NULL);
673 }
674 memset(qp, 0, sizeof(struct ipq));
675
676 /* Allocate memory for the MAC header. */
677 maclen = ((unsigned long) iph) - ((unsigned long) skb->data);
678 qp->mac = (unsigned char *) kmalloc(maclen, GFP_ATOMIC);
679 if (qp->mac == NULL)
680 {
681 printk("IP: create: no memory left !\n");
682 kfree_s(qp, sizeof(struct ipq));
683 return(NULL);
684 }
685
686 /* Allocate memory for the IP header (plus 8 octects for ICMP). */
687 ihlen = (iph->ihl * sizeof(unsigned long));
688 qp->iph = (struct iphdr *) kmalloc(ihlen + 8, GFP_ATOMIC);
689 if (qp->iph == NULL)
690 {
691 printk("IP: create: no memory left !\n");
692 kfree_s(qp->mac, maclen);
693 kfree_s(qp, sizeof(struct ipq));
694 return(NULL);
695 }
696
697 /* Fill in the structure. */
698 memcpy(qp->mac, skb->data, maclen);
699 memcpy(qp->iph, iph, ihlen + 8);
700 qp->len = 0;
701 qp->ihlen = ihlen;
702 qp->maclen = maclen;
703 qp->fragments = NULL;
704 qp->dev = dev;
705 /* printk("Protocol = %d\n",qp->iph->protocol);*/
706
707 /* Start a timer for this entry. */
708 qp->timer.expires = IP_FRAG_TIME; /* about 30 seconds */
709 qp->timer.data = (unsigned long) qp; /* pointer to queue */
710 qp->timer.function = ip_expire; /* expire function */
711 add_timer(&qp->timer);
712
713 /* Add this entry to the queue. */
714 qp->prev = NULL;
715 cli();
716 qp->next = ipqueue;
717 if (qp->next != NULL)
718 qp->next->prev = qp;
719 ipqueue = qp;
720 sti();
721 return(qp);
722 }
723
724
725 /* See if a fragment queue is complete. */
726 static int ip_done(struct ipq *qp)
727 {
728 struct ipfrag *fp;
729 int offset;
730
731 /* Only possible if we received the final fragment. */
732 if (qp->len == 0)
733 return(0);
734
735 /* Check all fragment offsets to see if they connect. */
736 fp = qp->fragments;
737 offset = 0;
738 while (fp != NULL)
739 {
740 if (fp->offset > offset)
741 return(0); /* fragment(s) missing */
742 offset = fp->end;
743 fp = fp->next;
744 }
745
746 /* All fragments are present. */
747 return(1);
748 }
749
750
751 /* Build a new IP datagram from all its fragments. */
752 static struct sk_buff *ip_glue(struct ipq *qp)
753 {
754 struct sk_buff *skb;
755 struct iphdr *iph;
756 struct ipfrag *fp;
757 unsigned char *ptr;
758 int count, len;
759
760 /* Allocate a new buffer for the datagram. */
761 len = sizeof(struct sk_buff)+qp->maclen + qp->ihlen + qp->len;
762 if ((skb = alloc_skb(len,GFP_ATOMIC)) == NULL)
763 {
764 printk("IP: queue_glue: no memory for glueing queue 0x%X\n", (int) qp);
765 ip_free(qp);
766 return(NULL);
767 }
768
769 /* Fill in the basic details. */
770 skb->len = (len - qp->maclen);
771 skb->h.raw = skb->data;
772 skb->free = 1;
773
774 /* Copy the original MAC and IP headers into the new buffer. */
775 ptr = (unsigned char *) skb->h.raw;
776 memcpy(ptr, ((unsigned char *) qp->mac), qp->maclen);
777 /* printk("Copied %d bytes of mac header.\n",qp->maclen);*/
778 ptr += qp->maclen;
779 memcpy(ptr, ((unsigned char *) qp->iph), qp->ihlen);
780 /* printk("Copied %d byte of ip header.\n",qp->ihlen);*/
781 ptr += qp->ihlen;
782 skb->h.raw += qp->maclen;
783
784 /* printk("Protocol = %d\n",skb->h.iph->protocol);*/
785 count = 0;
786
787 /* Copy the data portions of all fragments into the new buffer. */
788 fp = qp->fragments;
789 while(fp != NULL)
790 {
791 if(count+fp->len>skb->len)
792 {
793 printk("Invalid fragment list: Fragment over size.\n");
794 ip_free(qp);
795 kfree_skb(skb,FREE_WRITE);
796 return NULL;
797 }
798 /* printk("Fragment %d size %d\n",fp->offset,fp->len);*/
799 memcpy((ptr + fp->offset), fp->ptr, fp->len);
800 count += fp->len;
801 fp = fp->next;
802 }
803
804 /* We glued together all fragments, so remove the queue entry. */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -