예제 #1
1
파일: forwarder.go 프로젝트: grkvlt/weave
func fragment(eth layers.Ethernet, ip layers.IPv4, pmtu int, frame *ForwardedFrame, forward func(*ForwardedFrame)) error {
	// We are not doing any sort of NAT, so we don't need to worry
	// about checksums of IP payload (eg UDP checksum).
	headerSize := int(ip.IHL) * 4
	// &^ is bit clear (AND NOT). So here we're clearing the lowest 3
	// bits.
	maxSegmentSize := (pmtu - headerSize) &^ 7
	opts := gopacket.SerializeOptions{
		FixLengths:       false,
		ComputeChecksums: true}
	payloadSize := int(ip.Length) - headerSize
	payload := ip.BaseLayer.Payload[:payloadSize]
	offsetBase := int(ip.FragOffset) << 3
	origFlags := ip.Flags
	ip.Flags = ip.Flags | layers.IPv4MoreFragments
	ip.Length = uint16(headerSize + maxSegmentSize)
	if eth.EthernetType == layers.EthernetTypeLLC {
		// using LLC, so must set eth length correctly. eth length
		// is just the length of the payload
		eth.Length = ip.Length
	} else {
		eth.Length = 0
	}
	for offset := 0; offset < payloadSize; offset += maxSegmentSize {
		var segmentPayload []byte
		if len(payload) <= maxSegmentSize {
			// last one
			segmentPayload = payload
			ip.Length = uint16(len(payload) + headerSize)
			ip.Flags = origFlags
			if eth.EthernetType == layers.EthernetTypeLLC {
				eth.Length = ip.Length
			} else {
				eth.Length = 0
			}
		} else {
			segmentPayload = payload[:maxSegmentSize]
			payload = payload[maxSegmentSize:]
		}
		ip.FragOffset = uint16((offset + offsetBase) >> 3)
		buf := gopacket.NewSerializeBuffer()
		segPayload := gopacket.Payload(segmentPayload)
		err := gopacket.SerializeLayers(buf, opts, &eth, &ip, &segPayload)
		if err != nil {
			return err
		}
		// make copies of the frame we received
		segFrame := *frame
		segFrame.frame = buf.Bytes()
		forward(&segFrame)
	}
	return nil
}
예제 #2
0
/*Shim inserts the given router into the shim layer route record of the given
IPv4 packet, creating a new route record if it's not already present.*/
func Shim(ipLayer *layers.IPv4, r Router) {
	ipPayload := bytes.NewBuffer(ipLayer.LayerPayload())
	var modifiedIPPayload bytes.Buffer

	var rr RouteRecord

	if Shimmed(ipLayer) {
		rr.ReadFrom(ipPayload)
		ipLayer.Length -= uint16(rr.Len())
	} else {
		rr.Protocol = uint8(ipLayer.Protocol)
	}

	/*Add the specified router to the route record and put the record at the
	beginning of the payload.*/
	rr.AddRouter(r)
	rr.WriteTo(&modifiedIPPayload)
	ipPayload.WriteTo(&modifiedIPPayload)

	ipLayer.Length += uint16(rr.Len())
	ipLayer.Protocol = layers.IPProtocol(IPProtocolAITFRouteRecord)
	ipLayer.Checksum = 0
	ipLayer.Payload = modifiedIPPayload.Bytes()
}
예제 #3
0
/*Unshim removes the shim layer from an IPv4 packet, if it's present.*/
func Unshim(ipLayer *layers.IPv4) *RouteRecord {
	if Shimmed(ipLayer) {
		/*Remove the route record from the payload*/
		ipPayload := bytes.NewBuffer(ipLayer.LayerPayload())
		var rr RouteRecord
		rr.ReadFrom(ipPayload)

		ipLayer.Length -= uint16(rr.Len())
		ipLayer.Protocol = layers.IPProtocol(rr.Protocol)
		ipLayer.Checksum = 0
		ipLayer.Payload = ipPayload.Bytes()

		return &rr
	}

	return nil
}