Search code examples
gogopacket

Send EAPoL packet: Request Identity


I try to send Request Identity EAPoL packet:

func eapol_requestIdentity(handle *pcap.Handle, iface *net.Interface, id uint8) error {
    
        len := uint16(5) // eap1 field length
    
        eap1 := layers.EAP{
            Code: layers.EAPCodeResponse,
            Id:   id,
            Type: layers.EAPTypeIdentity,
            TypeData: []byte{byte(layers.EAPTypeIdentity)}, // bugfix
            Length:   len,
        }
    
        eapol := layers.EAPOL{
            Version: 1,
            Type:    layers.EAPOLTypeEAP,
            Length:  eap1.Length,
        }
    
        eth := layers.Ethernet{
            SrcMAC:       iface.HardwareAddr,
            DstMAC:       net.HardwareAddr{0x01, 0x80, 0xc2, 0x00, 0x00, 0x03},
            EthernetType: layers.EthernetTypeEAPOL,
        }
    
        buf := gopacket.NewSerializeBuffer()
        opts := gopacket.SerializeOptions{
            //FixLengths:       true, // doesn't work
            FixLengths:       false,
            ComputeChecksums: true,
        }
    
        gopacket.SerializeLayers(buf, opts, &eth, &eapol, &eap1)
        log.Printf("send EOPoL : Request Identity %u...", id)
        if err := handle.WritePacketData(buf.Bytes()); err != nil {
            log.Printf("Send err ", err)
            return err
        }
        log.Printf("send packet [OK]")
    
        return nil
    }

I don't understand: if I delete line TypeData: [] byte{byte(layers.EAPTypeIdentity)} or line Type: layers.EAPTypeIdentity, my application sent a wrong packet. Is it normal?... why must I set data twice for de same byte in packet?

Also, I tried to set FixLengths to true, but length fields are bads in sent packet...


Solution

  • I am not very familiar with EAP, but according to the RFC, Type and Type-Data are two different fields:

        0                   1                   2                   3
        0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
       |     Code      |  Identifier   |            Length             |
       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
       |     Type      |  Type-Data ...
       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-
    

    So it stands to reason that if you leave out a piece of the packet, that it is "wrong".

    As for the length, it seems there is a bug in gopacket when calculating the length. According to the RFC

    The Length field is two octets and indicates the length of the EAP packet including the Code, Identifier, Length, Type, and Type-Data fields

    But when FixLengths is true, gopacket only counts Type and Type-Data.

    if opts.FixLengths {
      e.Length = uint16(len(e.TypeData) + 1)
    }
    

    The +1 should be +5, so it seems like you discovered a bug.

    Edit: Looks like you already filled a bug report: https://github.com/google/gopacket/issues/931