"""
Ethernet (TCP/IP protocol stack)
"""
from construct import *
from ethernet import MacAddressAdapter
from construct.protocols.layer3.ipv4 import IpAddressAdapter
from binascii import unhexlify
import six



def HwAddress(name):
    return IfThenElse(name, lambda ctx: ctx.hardware_type == "ETHERNET",
        MacAddressAdapter(Field("data", lambda ctx: ctx.hwaddr_length)),
        Field("data", lambda ctx: ctx.hwaddr_length)
    )

def ProtoAddress(name):
    return IfThenElse(name, lambda ctx: ctx.protocol_type == "IP",
        IpAddressAdapter(Field("data", lambda ctx: ctx.protoaddr_length)),
        Field("data", lambda ctx: ctx.protoaddr_length)
    )

arp_header = Struct("arp_header",
    Enum(UBInt16("hardware_type"),
        ETHERNET = 1,
        EXPERIMENTAL_ETHERNET = 2,
        ProNET_TOKEN_RING = 4,
        CHAOS = 5,
        IEEE802 = 6,
        ARCNET = 7,
        HYPERCHANNEL = 8,
        ULTRALINK = 13,
        FRAME_RELAY = 15,
        FIBRE_CHANNEL = 18,
        IEEE1394 = 24,
        HIPARP = 28,
        ISO7816_3 = 29,
        ARPSEC = 30,
        IPSEC_TUNNEL = 31,
        INFINIBAND = 32,
    ),
    Enum(UBInt16("protocol_type"),
        IP = 0x0800,
    ),
    UBInt8("hwaddr_length"),
    UBInt8("protoaddr_length"),
    Enum(UBInt16("opcode"),
        REQUEST = 1,
        REPLY = 2,
        REQUEST_REVERSE = 3,
        REPLY_REVERSE = 4,
        DRARP_REQUEST = 5,
        DRARP_REPLY = 6,
        DRARP_ERROR = 7,
        InARP_REQUEST = 8,
        InARP_REPLY = 9,
        ARP_NAK = 10
        
    ),
    HwAddress("source_hwaddr"),
    ProtoAddress("source_protoaddr"),
    HwAddress("dest_hwaddr"),
    ProtoAddress("dest_protoaddr"),
)

rarp_header = Rename("rarp_header", arp_header)


if __name__ == "__main__":
    cap1 = unhexlify(six.b("00010800060400010002e3426009c0a80204000000000000c0a80201"))
    obj = arp_header.parse(cap1)
    print (obj)
    print (repr(arp_header.build(obj)))

    print ("-" * 80)
    
    cap2 = unhexlify(six.b("00010800060400020011508c283cc0a802010002e3426009c0a80204"))
    obj = arp_header.parse(cap2)
    print (obj)
    print (repr(arp_header.build(obj)))













