⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ip.c

📁 An implementation of the TCP/IP protocol suite for the LINUX operating system. INET is implemented u
💻 C
📖 第 1 页 / 共 4 页
字号:
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 + -