aregm / nff-go

NFF-Go -Network Function Framework for GO (former YANFF)
BSD 3-Clause "New" or "Revised" License
1.38k stars 156 forks source link

ICMP sending empty packets #699

Closed sitilge closed 4 years ago

sitilge commented 4 years ago

I am trying to send an ICMP Echo reply back to the sender. However, after looking at the packet dump, I can see that the reply message does not contain the new values set in layers.ICMPv4. What could be the problem here?

func (p *IPPort) HandleICMP(pkt *packet.Packet) {
    if !p.Generated.IPv4.AddressAcquired {
        return
    }

    layer := layers.ICMPv4{
        TypeCode: layers.ICMPv4TypeEchoReply,
        Id:              pkt.GetICMPNoCheck().Identifier,
        Seq:          pkt.GetICMPNoCheck().SeqNum,
    }

    payload := gopacket.NewSerializeBuffer()
    opts := gopacket.SerializeOptions{
        FixLengths:       true,
        ComputeChecksums: true,
    }
    err := gopacket.SerializeLayers(payload, opts, &layer)
    if err != nil {
        common.LogFatal(common.Debug, err)
    }

    out, err := packet.NewPacket()
    if err != nil {
        common.LogFatal(common.Debug, err)
    }

    packet.InitEmptyIPv4ICMPPacket(out, uint(len(payload.Bytes())))

    load, _ := out.GetPacketPayload()
    copy(load, payload.Bytes())

    out.Ether.SAddr = pkt.Ether.DAddr
    out.Ether.DAddr = pkt.Ether.SAddr

    out.GetIPv4NoCheck().SrcAddr = pkt.GetIPv4NoCheck().DstAddr
    out.GetIPv4NoCheck().DstAddr = pkt.GetIPv4NoCheck().SrcAddr
    out.GetIPv4NoCheck().HdrChecksum = packet.SwapBytesUint16(packet.CalculateIPv4Checksum(out.GetIPv4NoCheck()))

    out.GetICMPNoCheck().Cksum = packet.SwapBytesUint16(packet.CalculateIPv4ICMPChecksum(
        out.GetIPv4NoCheck(),
        out.GetICMPNoCheck(),
        unsafe.Pointer(uintptr(unsafe.Pointer(out.GetICMPNoCheck())) + types.ICMPLen),
    ))

    out.SendPacket(p.Index)
}