public static IPv6Frame[] FragmentV6(IPv6Frame ipv6Frame, int iMaximumTransmissionUnit, uint iIdentification) { Frame fFrame = ipv6Frame.EncapsulatedFrame; List <IPv6Frame> lIPv6Frames = new List <IPv6Frame>(); if (ipv6Frame.Length > iMaximumTransmissionUnit) { ipv6Frame.EncapsulatedFrame = null; byte[][] bChunks = CreateChunks(fFrame.FrameBytes, iMaximumTransmissionUnit - ipv6Frame.Length); int iDataCounter = 0; for (int iC1 = 0; iC1 < bChunks.Length; iC1++) { IPv6Frame ipv6Clone = (IPv6Frame)ipv6Frame.Clone(); FragmentExtensionHeader fragHeader = new FragmentExtensionHeader(); fragHeader.EncapsulatedFrame = new RawDataFrame(bChunks[iC1]); ipv6Clone.EncapsulatedFrame = fragHeader; fragHeader.FragmentOffset = ((iDataCounter) / 8); fragHeader.MoreFragments = iC1 != bChunks.Length - 1; fragHeader.Identification = iIdentification; fragHeader.Protocol = ipv6Clone.Protocol; ipv6Clone.Protocol = IPProtocol.IPv6_Frag; iDataCounter += bChunks[iC1].Length; lIPv6Frames.Add(ipv6Clone); } } else { lIPv6Frames.Add(ipv6Frame); } return(lIPv6Frames.ToArray()); }
/// <summary> /// Decapsulates the given IP frame if the binding of this socket matches the frame and invokes the FrameDecapsulated event when finished. /// <remarks>This mehtod also handles IP fragmentation</remarks> /// </summary> /// <param name="fFrame">The frame to process</param> /// <param name="bPush">A bool indicating whether the frame is delivered with a push flag</param> /// <returns>A bool indicating whether the given frame matched the binding of this socket</returns> public override bool PushUp(Frame fFrame, bool bPush) { if (!FrameTypes.IsIP(fFrame)) { fFrame = IPFrame.Create(fFrame.FrameBytes); } IPFrame ipFrame = (IPFrame)fFrame; if (!ipFrame.SourceAddress.Equals(RemoteBinding) || !ipFrame.DestinationAddress.Equals(LocalBinding)) { return(false); } if (ipFrame.FrameType == FrameTypes.IPv4) { IPv4Frame ipv4Frame = (IPv4Frame)ipFrame; if (ipv4Frame.Protocol != this.ProtocolBinding) { return(false); } if (ipv4Frame.EncapsulatedFrame != null) { if (ipv4Frame.PacketFlags.MoreFragments) { HandleFragment(bPush, ipv4Frame.PacketFlags.MoreFragments, ipv4Frame.Identification, ipv4Frame.FragmentOffset, ipv4Frame.EncapsulatedFrame.FrameBytes); } else { InvokeFrameDecapsulated(ipv4Frame.EncapsulatedFrame, bPush); } } return(true); } else if (ipFrame.FrameType == FrameTypes.IPv6) { ProtocolParser.ParseCompleteFrame(fFrame); Frame fPayload = null; Frame ipHeader = fFrame; while (ipHeader.EncapsulatedFrame != null && ipHeader.EncapsulatedFrame is IIPHeader) { if (((IIPHeader)ipHeader).Protocol == this.ProtocolBinding) { fPayload = ipHeader.EncapsulatedFrame; break; } } if (fPayload == null) { return(false); //Wrong payload type :( } FragmentExtensionHeader fragHeader = (FragmentExtensionHeader)ProtocolParser.GetFrameByType(fFrame, FragmentExtensionHeader.DefaultFrameType); if (fragHeader != null) { HandleFragment(bPush, fragHeader.MoreFragments, fragHeader.Identification, fragHeader.FragmentOffset, fPayload.FrameBytes); } else { InvokeFrameDecapsulated(fPayload, bPush); } } throw new ArgumentException("Only IPv4 and IPv6 frames are supported at the moment."); }