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

📄 ip.c

📁 An implementation of the TCP/IP protocol suite for the LINUX operating system. INET is implemented u
💻 C
📖 第 1 页 / 共 4 页
字号:
805         ip_free(qp);
806  
807         /* Done with all fragments. Fixup the new IP header. */
808         iph = skb->h.iph;
809         iph->frag_off = 0;
810         iph->tot_len = htons((iph->ihl * sizeof(unsigned long)) + count);
811         skb->ip_hdr = iph;
812         return(skb);
813 }
814  
815 
816 /* Process an incoming IP datagram fragment. */
817 static struct sk_buff *ip_defrag(struct iphdr *iph, struct sk_buff *skb, struct device *dev)
818 {
819         struct ipfrag *prev, *next;
820         struct ipfrag *tfp;
821         struct ipq *qp;
822         struct sk_buff *skb2;
823         unsigned char *ptr;
824         int flags, offset;
825         int i, ihl, end;
826 
827         /* Find the entry of this IP datagram in the "incomplete datagrams" queue. */
828         qp = ip_find(iph);
829  
830         /* Is this a non-fragmented datagram? */
831         offset = ntohs(iph->frag_off);
832         flags = offset & ~IP_OFFSET;
833         offset &= IP_OFFSET;
834         if (((flags & IP_MF) == 0) && (offset == 0)) 
835         {
836                 if (qp != NULL) 
837                         ip_free(qp);    /* Huh? How could this exist?? */
838                 return(skb);
839         }
840         offset <<= 3;           /* offset is in 8-byte chunks */
841  
842         /*
843          * If the queue already existed, keep restarting its timer as long
844          * as we still are receiving fragments.  Otherwise, create a fresh
845          * queue entry.
846          */
847         if (qp != NULL) 
848         {
849                 del_timer(&qp->timer);
850                 qp->timer.expires = IP_FRAG_TIME;       /* about 30 seconds     */
851                 qp->timer.data = (unsigned long) qp;    /* pointer to queue     */
852                 qp->timer.function = ip_expire;         /* expire function      */
853                 add_timer(&qp->timer);
854         } 
855         else 
856         {
857                 if ((qp = ip_create(skb, iph, dev)) == NULL) 
858                         return(NULL);
859         }
860  
861         /* Determine the position of this fragment. */
862         ihl = (iph->ihl * sizeof(unsigned long));
863         end = offset + ntohs(iph->tot_len) - ihl;
864  
865         /* Point into the IP datagram 'data' part. */
866         ptr = skb->data + dev->hard_header_len + ihl;
867  
868         /* Is this the final fragment? */
869         if ((flags & IP_MF) == 0) 
870                 qp->len = end;
871  
872         /*
873          * Find out which fragments are in front and at the back of us
874          * in the chain of fragments so far.  We must know where to put
875          * this fragment, right?
876          */
877         prev = NULL;
878         for(next = qp->fragments; next != NULL; next = next->next) 
879         {
880                 if (next->offset > offset) 
881                         break;  /* bingo! */
882                 prev = next;
883         }       
884  
885         /*
886          * We found where to put this one.
887          * Check for overlap with preceeding fragment, and, if needed,
888          * align things so that any overlaps are eliminated.
889          */
890         if (prev != NULL && offset < prev->end) 
891         {
892                 i = prev->end - offset;
893                 offset += i;    /* ptr into datagram */
894                 ptr += i;       /* ptr into fragment data */
895                 DPRINTF((DBG_IP, "IP: defrag: fixed low overlap %d bytes\n", i));
896         }       
897  
898         /*
899          * Look for overlap with succeeding segments.
900          * If we can merge fragments, do it.
901          */
902    
903         for(; next != NULL; next = tfp) 
904         {
905                 tfp = next->next;
906                 if (next->offset >= end) 
907                         break;          /* no overlaps at all */
908  
909                 i = end - next->offset;                 /* overlap is 'i' bytes */
910                 next->len -= i;                         /* so reduce size of    */
911                 next->offset += i;                      /* next fragment        */
912                 next->ptr += i;
913                 
914                 /* If we get a frag size of <= 0, remove it. */
915                 if (next->len <= 0) 
916                 {
917                         DPRINTF((DBG_IP, "IP: defrag: removing frag 0x%X (len %d)\n",
918                                                         next, next->len));
919                         if (next->prev != NULL) 
920                                 next->prev->next = next->next;
921                         else 
922                                 qp->fragments = next->next;
923                 
924                         if (tfp->next != NULL) 
925                                 next->next->prev = next->prev;
926                         
927                         kfree_s(next, sizeof(struct ipfrag));
928                 }
929                 DPRINTF((DBG_IP, "IP: defrag: fixed high overlap %d bytes\n", i));
930         }
931  
932         /* Insert this fragment in the chain of fragments. */
933         tfp = NULL;
934         tfp = ip_frag_create(offset, end, skb, ptr);
935         tfp->prev = prev;
936         tfp->next = next;
937         if (prev != NULL) 
938                 prev->next = tfp;
939         else 
940                 qp->fragments = tfp;
941    
942         if (next != NULL) 
943                 next->prev = tfp;
944  
945         /*
946          * OK, so we inserted this new fragment into the chain.
947          * Check if we now have a full IP datagram which we can
948          * bump up to the IP layer...
949          */
950    
951         if (ip_done(qp)) 
952         {
953                 skb2 = ip_glue(qp);             /* glue together the fragments */
954                 return(skb2);
955         }
956         return(NULL);
957  }
958  
959  
960  /*
961   * This IP datagram is too large to be sent in one piece.  Break it up into
962   * smaller pieces (each of size equal to the MAC header plus IP header plus
963   * a block of the data of the original IP data part) that will yet fit in a
964   * single device frame, and queue such a frame for sending by calling the
965   * ip_queue_xmit().  Note that this is recursion, and bad things will happen
966   * if this function causes a loop...
967   */
968  void ip_fragment(struct sock *sk, struct sk_buff *skb, struct device *dev, int is_frag)
969  {
970         struct iphdr *iph;
971         unsigned char *raw;
972         unsigned char *ptr;
973         struct sk_buff *skb2;
974         int left, mtu, hlen, len;
975         int offset;
976  
977         /* Point into the IP datagram header. */
978         raw = skb->data;
979         iph = (struct iphdr *) (raw + dev->hard_header_len);
980 
981         skb->ip_hdr = iph;
982                 
983         /* Setup starting values. */
984         hlen = (iph->ihl * sizeof(unsigned long));
985         left = ntohs(iph->tot_len) - hlen;
986         hlen += dev->hard_header_len;
987         mtu = (dev->mtu - hlen);
988         ptr = (raw + hlen);
989         
990         DPRINTF((DBG_IP, "IP: Fragmentation Desired\n"));
991         DPRINTF((DBG_IP, "    DEV=%s, MTU=%d, LEN=%d SRC=%s",
992                 dev->name, dev->mtu, left, in_ntoa(iph->saddr)));
993         DPRINTF((DBG_IP, " DST=%s\n", in_ntoa(iph->daddr)));
994  
995         /* Check for any "DF" flag. */
996         if (ntohs(iph->frag_off) & IP_DF) 
997         {
998                 DPRINTF((DBG_IP, "IP: Fragmentation Desired, but DF set !\n"));
999                 DPRINTF((DBG_IP, "    DEV=%s, MTU=%d, LEN=%d SRC=%s",
1000                         dev->name, dev->mtu, left, in_ntoa(iph->saddr)));
1001                 DPRINTF((DBG_IP, " DST=%s\n", in_ntoa(iph->daddr)));
1002  
1003                 /*
1004                  * FIXME:
1005                  * We should send an ICMP warning message here!
1006                  */
1007                  
1008                 icmp_send(skb,ICMP_DEST_UNREACH, ICMP_FRAG_NEEDED, dev); 
1009                 return;
1010         }
1011  
1012         /* Fragment the datagram. */
1013         if (is_frag & 2)
1014           offset = (ntohs(iph->frag_off) & 0x1fff) << 3;
1015         else
1016           offset = 0;
1017         while(left > 0) 
1018         {
1019                 len = left;
1020 #ifdef OLD              
1021                 if (len+8 > mtu) 
1022                         len = (dev->mtu - hlen - 8);
1023                 if ((left - len) >= 8) 
1024                 {
1025                         len /= 8;
1026                         len *= 8;
1027                 }
1028 #else
1029                 /* IF: it doesn't fit, use 'mtu' - the data space left */
1030                 if (len > mtu)
1031                         len = mtu;
1032                 /* IF: we are not sending upto and including the packet end
1033                    then align the next start on an eight byte boundary */
1034                 if (len < left)
1035                 {
1036                         len/=8;
1037                         len*=8;
1038                 }
1039 #endif                          
1040                 DPRINTF((DBG_IP,"IP: frag: creating fragment of %d bytes (%d total)\n",
1041                                                         len, len + hlen));
1042  
1043                 /* Allocate buffer. */
1044                 if ((skb2 = alloc_skb(sizeof(struct sk_buff) + len + hlen,GFP_ATOMIC)) == NULL) 
1045                 {
1046                         printk("IP: frag: no memory for new fragment!\n");
1047                         return;
1048                 }
1049                 skb2->arp = skb->arp;
1050                 skb2->free = skb->free;
1051                 skb2->len = len + hlen;
1052                 skb2->h.raw=(char *) skb2->data;
1053  
1054                 if (sk) 
1055                         sk->wmem_alloc += skb2->mem_len;
1056  
1057                 /* Copy the packet header into the new buffer. */
1058                 memcpy(skb2->h.raw, raw, hlen);
1059  
1060                 /* Copy a block of the IP datagram. */
1061                 memcpy(skb2->h.raw + hlen, ptr, len);
1062                 left -= len;
1063 
1064                 skb2->h.raw+=dev->hard_header_len; 
1065                 /* Fill in the new header fields. */
1066                 iph = (struct iphdr *)(skb2->h.raw/*+dev->hard_header_len*/);
1067                 iph->frag_off = htons((offset >> 3));
1068                 /* Added AC : If we are fragmenting a fragment thats not the
1069                    last fragment then keep MF on each bit */
1070                 if (left > 0 || (is_frag & 1)) 
1071                         iph->frag_off |= htons(IP_MF);
1072                 ptr += len;
1073                 offset += len;
1074 /*              printk("Queue frag\n");*/
1075  
1076                 /* Put this fragment into the sending queue. */
1077                 ip_queue_xmit(sk, dev, skb2, 1);
1078 /*              printk("Queued\n");*/
1079         }
1080  }
1081  
1082 
1083 
1084 #ifdef CONFIG_IP_FORWARD
1085 
1086 /* Forward an IP datagram to its next destination. */
1087 static void
1088 ip_forward(struct sk_buff *skb, struct device *dev, int is_frag)
1089 {
1090   struct device *dev2;
1091   struct iphdr *iph;
1092   struct sk_buff *skb2;
1093   struct rtable *rt;
1094   unsigned char *ptr;
1095   unsigned long raddr;
1096 
1097   /*
1098    * Only forward packets that were fired at us when we are in promiscuous
1099    * mode. In standard mode we rely on the driver to filter for us.
1100    */
1101    
1102   if(dev->flags&IFF_PROMISC)
1103   {
1104         if(memcmp((char *)&skb[1],dev->dev_addr,dev->addr_len))
1105                 return;
1106   }
1107   
1108   /*
1109    * According to the RFC, we must first decrease the TTL field. If
1110    * that reaches zero, we must reply an ICMP control message telling
1111    * that the packet's lifetime expired.
1112    */
1113   iph = skb->h.iph;
1114   iph->ttl--;
1115   if (iph->ttl <= 0) {
1116         DPRINTF((DBG_IP, "\nIP: *** datagram expired: TTL=0 (ignored) ***\n"));
1117         DPRINTF((DBG_IP, "    SRC = %s   ", in_ntoa(iph->saddr)));
1118         DPRINTF((DBG_IP, "    DST = %s (ignored)\n", in_ntoa(iph->daddr)));
1119 
1120         /* Tell the sender its packet died... */
1121         icmp_send(skb, ICMP_TIME_EXCEEDED, ICMP_EXC_TTL, dev);
1122         return;
1123   }
1124 
1125   /* Re-compute the IP header checksum. */
1126   ip_send_check(iph);
1127 
1128   /*
1129    * OK, the packet is still valid.  Fetch its destination address,
1130    * and give it to the IP sender for further processing.
1131    */
1132   rt = rt_route(iph->daddr, NULL);
1133   if (rt == NULL) {
1134         DPRINTF((DBG_IP, "\nIP: *** routing (phase I) failed ***\n"));
1135 
1136         /* Tell the sender its packet cannot be delivered... */
1137         icmp_send(skb, ICMP_DEST_UNREACH, ICMP_NET_UNREACH, dev);
1138         return;
1139   }
1140 
1141 
1142   /*
1143    * Gosh.  Not only is the packet valid; we even know how to
1144    * forward it onto its final destination.  Can we say this
1145    * is being plain lucky?
1146    * If the router told us that there is no GW, use the dest.
1147    * IP address itself- we seem to be connected directly...
1148    */
1149   raddr = rt->rt_gateway;
1150   if (raddr != 0) {
1151         rt = rt_route(raddr, NULL);
1152         if (rt == NULL) {
1153                 DPRINTF((DBG_IP, "\nIP: *** routing (phase II) failed ***\n"));
1154 
1155                 /* Tell the sender its packet cannot be delivered... */
1156                 icmp_send(skb, ICMP_DEST_UNREACH, ICMP_HOST_UNREACH, dev);
1157                 return;
1158         }
1159         if (rt->rt_gateway != 0) raddr = rt->rt_gateway;
1160   } else raddr = iph->daddr;
1161   dev2 = rt->rt_dev;
1162 
1163 
1164   if (dev == dev2)
1165         return;
1166   /*
1167    * We now allocate a new buffer, and copy the datagram into it.
1168    * If the indicated interface is up and running, kick it.
1169    */
1170   DPRINTF((DBG_IP, "\nIP: *** fwd %s -> ", in_ntoa(iph->saddr)));
1171   DPRINTF((DBG_IP, "%s (via %s), LEN=%d\n",
1172                         in_ntoa(raddr), dev2->name, skb->len));
1173 
1174   if (dev2->flags & IFF_UP) {
1175         skb2 = (struct sk_buff *) alloc_skb(sizeof(struct sk_buff) +
1176                        dev2->hard_header_len + skb->len, GFP_ATOMIC);
1177         if (skb2 == NULL) {
1178                 printk("\nIP: No memory available for IP forward\n");
1179                 return;
1180         }
1181         ptr = skb2->data;
1182         skb2->sk = NULL;
1183         skb2->free = 1;
1184         skb2->len = skb->len + dev2->hard_header_len;
1185         skb2->mem_addr = skb2;
1186         skb2->mem_len = sizeof(struct sk_buff) + skb2->len;
1187         skb2->next = NULL;
1188         skb2->h.raw = ptr;
1189 
1190         /* Copy the packet data into the new buffer. */
1191         memcpy(ptr + dev2->hard_header_len, skb->h.raw, skb->len);
1192                 
1193         /* Now build the MAC header. */
1194         (void) ip_send(skb2, raddr, skb->len, dev2, dev2->pa_addr);
1195 
1196         if(skb2->len > dev2->mtu)
1197         {
1198                 ip_fragment(NULL,skb2,dev2, is_frag);
1199                 kfree_skb(skb2,FREE_WRITE);
1200         }
1201         else
1202                 dev2->queue_xmit(skb2, dev2, SOPRI_NORMAL);
1203   }
1204 }
1205 
1206 

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -