'Enumerate all interfaces and collect their MAC addresses.'

def Run(self, unused_args):

    libc = ctypes.cdll.LoadLibrary(ctypes.util.find_library('c'))
    ifa = Ifaddrs()
    p_ifa = ctypes.pointer(ifa)
    libc.getifaddrs(ctypes.pointer(p_ifa))
    addresses = {}
    macs = {}
    ifs = set()
    m = p_ifa
    while m:
        ifname = ctypes.string_at(m.contents.ifa_name)
        ifs.add(ifname)
        try:
            iffamily = ord(m.contents.ifa_addr[0])
            if (iffamily == 2):
                data = ctypes.cast(m.contents.ifa_addr, ctypes.POINTER(Sockaddrin))
                ip4 = ''.join(map(chr, data.contents.sin_addr))
                address_type = rdf_client.NetworkAddress.Family.INET
                address = rdf_client.NetworkAddress(address_type=address_type, packed_bytes=ip4)
                addresses.setdefault(ifname, []).append(address)
            if (iffamily == 17):
                data = ctypes.cast(m.contents.ifa_addr, ctypes.POINTER(Sockaddrll))
                addlen = data.contents.sll_halen
                macs[ifname] = ''.join(map(chr, data.contents.sll_addr[:addlen]))
            if (iffamily == 10):
                data = ctypes.cast(m.contents.ifa_addr, ctypes.POINTER(Sockaddrin6))
                ip6 = ''.join(map(chr, data.contents.sin6_addr))
                address_type = rdf_client.NetworkAddress.Family.INET6
                address = rdf_client.NetworkAddress(address_type=address_type, packed_bytes=ip6)
                addresses.setdefault(ifname, []).append(address)
        except ValueError:
            pass
        m = m.contents.ifa_next
    libc.freeifaddrs(p_ifa)
    for interface in ifs:
        mac = macs.setdefault(interface, '')
        address_list = addresses.setdefault(interface, '')
        args = {'ifname': interface}
        if mac:
            args['mac_address'] = mac
        if addresses:
            args['addresses'] = address_list
        self.SendReply(rdf_client.Interface(**args))
