X-Git-Url: http://git.meshlink.io/?a=blobdiff_plain;f=src%2Fiface-windows.c;h=5624f739fed2c2644fbb3aa7e91c302c5f505831;hb=9b5f82efd97de784c9356c65dbfb704b94d974eb;hp=e3ca771b212c02dc8af671b72c48fa14d2774558;hpb=28302bf673d9a57b0919a91943c6aeb083ddcdb2;p=catta diff --git a/src/iface-windows.c b/src/iface-windows.c index e3ca771..5624f73 100644 --- a/src/iface-windows.c +++ b/src/iface-windows.c @@ -20,6 +20,7 @@ #include "iface-windows.h" #include "iface.h" +#include // wcstombs #include #include #include @@ -27,59 +28,87 @@ #include "util.h" // catta_format_mac_address -// for the luid-to-idx hashmap -static unsigned luid_hash(const void *data) +// integrate the information from an IP_ADAPTER_UNICAST_ADDRESS structure for +// given CattaHwInterface into the CattaInterfaceMonitor +static void ip_adapter_unicast_address(CattaInterfaceMonitor *m, + CattaHwInterface *hw, + IP_ADAPTER_UNICAST_ADDRESS *a) { - return ((NET_LUID *)data)->Info.NetLuidIndex; -} -static int luid_equal(const void *a, const void *b) -{ - return (((NET_LUID *)a)->Value == ((NET_LUID *)b)->Value); -} + CattaInterface *iface; + CattaAddress addr; + CattaInterfaceAddress *ifaddr; + struct sockaddr *sa = a->Address.lpSockaddr; + + // fill addr struct for address lookup + switch(sa->sa_family) { + case AF_INET: + memcpy(addr.data.data, &((struct sockaddr_in *)sa)->sin_addr, sizeof(struct in_addr)); + break; + case AF_INET6: + memcpy(addr.data.data, &((struct sockaddr_in6 *)sa)->sin6_addr, sizeof(struct in6_addr)); + break; + default: + catta_log_debug("unexpected address family on interface %d: %u", hw->index, sa->sa_family); + return; + } + addr.proto = catta_af_to_proto(sa->sa_family); -static CattaIfIndex find_ifindex(CattaInterfaceMonitor *m, NET_LUID luid) -{ - CattaIfIndex *pi = NULL; - NET_LUID *key = NULL; - - if((pi = catta_hashmap_lookup(m->osdep.idxmap, &luid)) == NULL) { - // allocate memory for the hashmap key and value - key = catta_malloc(sizeof(luid)); - pi = catta_malloc(sizeof(CattaIfIndex)); - if(!key || !pi) - goto fail; - - *key = luid; - - // find an index for this luid - *pi = m->osdep.nidx; - if(*pi < 0) // overflow - goto fail; - - // register the index - if(catta_hashmap_replace(m->osdep.idxmap, key, pi) < 0) - goto fail; - m->osdep.nidx++; + // get protocol-specific CattaInterface object + if(!(iface = catta_interface_monitor_get_interface(m, hw->index, addr.proto))) { + catta_log_error("CattaInterface (index %d, proto %d) not found", hw->index, addr.proto); + return; + } + + // find or allocate a CattaInterfaceAddress struct for this address + if(!(ifaddr = catta_interface_monitor_get_address(m, iface, &addr))) { + if(!(ifaddr = catta_interface_address_new(m, iface, &addr, a->OnLinkPrefixLength))) { + catta_log_error("out of memory in ip_adapter_unicast_address"); + return; + } } - return *pi; + // set global scope flag + if(addr.proto == CATTA_PROTO_INET6) + ifaddr->global_scope = !(IN6_IS_ADDR_LINKLOCAL((struct in6_addr *)addr.data.data) + || IN6_IS_ADDR_MULTICAST((struct in6_addr *)addr.data.data)); + else + ifaddr->global_scope = 1; -fail: - catta_free(key); - catta_free(pi); - return -1; + // XXX debugging, remove + { + char s[CATTA_ADDRESS_STR_MAX]; + catta_log_debug(" address: %s\n" + " global_scope: %d", + catta_address_snprint(s, sizeof(s), &addr), + ifaddr->global_scope); + } } // integrate the information from an IP_ADAPTER_ADDRESSES structure // as returned by GetAdaptersAddresses into the CattaInterfaceMonitor -static void ip_adapter_address(CattaInterfaceMonitor *m, IP_ADAPTER_ADDRESSES *p) +static void ip_adapter(CattaInterfaceMonitor *m, IP_ADAPTER_ADDRESSES *p) { + IP_ADAPTER_UNICAST_ADDRESS *a; CattaIfIndex idx; CattaHwInterface *hw; - - // look up the interface index by LUID - if((idx = find_ifindex(m, p->Luid)) < 0) { - catta_log_error("could not allocate index ip_adapter_address"); + size_t n; + + // we want an index specific to the hardware interface, but Windows + // has one for IPv4 and one for IPv6. it seems like these are always the + // same unless one of the protocols is not available. let's have a bunch of + // checks... + if(!p->IfIndex && !p->Ipv6IfIndex) { + return; // no usable protocols + } else if(!p->IfIndex) { + idx = p->Ipv6IfIndex; // IPv6 but no IPv4 (huh!) + } else if(!p->Ipv6IfIndex) { + idx = p->IfIndex; // IPv4 but no IPv6 + } else if(p->IfIndex == p->Ipv6IfIndex) { + idx = p->IfIndex; // same index for both protocols + } else { + // both indexes valid but not equal + catta_log_error("unsupported interface: %ls (IfIndex and Ipv6IfIndex differ: %u/%u)", + p->FriendlyName, (unsigned int)p->IfIndex, (unsigned int)p->Ipv6IfIndex); return; } @@ -93,44 +122,60 @@ static void ip_adapter_address(CattaInterfaceMonitor *m, IP_ADAPTER_ADDRESSES *p // fill the CattaHwInterface struct with data hw->flags_ok = - (p->OperStatus & IfOperStatusUp) && - !(p->IfType & IF_TYPE_SOFTWARE_LOOPBACK) && + (p->OperStatus == IfOperStatusUp) && + !(p->IfType == IF_TYPE_SOFTWARE_LOOPBACK) && !(p->Flags & IP_ADAPTER_NO_MULTICAST) && - (m->server->config.allow_point_to_point || !(p->IfType & IF_TYPE_PPP)); + (m->server->config.allow_point_to_point || !(p->IfType == IF_TYPE_PPP)); // XXX what about IF_TYPE_TUNNEL? + n = wcstombs(NULL, p->FriendlyName, 0) + 1; catta_free(hw->name); - hw->name = catta_strdup(p->AdapterName); + hw->name = catta_new(char, n); + wcstombs(hw->name, p->FriendlyName, n); hw->mtu = p->Mtu; hw->mac_address_size = p->PhysicalAddressLength; - if (hw->mac_address_size > CATTA_MAC_ADDRESS_MAX) - hw->mac_address_size = CATTA_MAC_ADDRESS_MAX; + if(hw->mac_address_size > CATTA_MAC_ADDRESS_MAX) + hw->mac_address_size = CATTA_MAC_ADDRESS_MAX; memcpy(hw->mac_address, p->PhysicalAddress, hw->mac_address_size); - // XXX process addresses - // XXX debugging, remove - { - char mac[256]; - catta_log_debug("======\n name: %s\n index:%d\n mtu:%d\n mac:%s\n flags_ok:%d\n======", - hw->name, hw->index, - hw->mtu, - catta_format_mac_address(mac, sizeof(mac), hw->mac_address, hw->mac_address_size), - hw->flags_ok); - } + { + char mac[256]; + catta_log_debug(" name: %s\n" + " index: %d\n" + " IfIndex: %u\n" + " Ipv6IfIndex: %u\n" + " mtu: %d\n" + " mac: %s\n" + " flags_ok: %d\n" + " type: %u\n" + " status: %u\n" + " multicast: %d\n" + " flags: 0x%.4x", + hw->name, hw->index, + (unsigned int)p->IfIndex, (unsigned int)p->Ipv6IfIndex, + hw->mtu, + catta_format_mac_address(mac, sizeof(mac), hw->mac_address, hw->mac_address_size), + hw->flags_ok, + (unsigned int)p->IfType, + (unsigned int)p->OperStatus, + !(p->Flags & IP_ADAPTER_NO_MULTICAST), + (unsigned int)p->Flags); + } + + // process addresses + // XXX remove addresses that are no longer in the list + for(a=p->FirstUnicastAddress; a; a=a->Next) + ip_adapter_unicast_address(m, hw, a); + catta_log_debug("====="); } int catta_interface_monitor_init_osdep(CattaInterfaceMonitor *m) { - m->osdep.nidx = 0; - m->osdep.idxmap = catta_hashmap_new(luid_hash, luid_equal, catta_free, catta_free); - if(m->osdep.idxmap == NULL) { - catta_log_error("out of memory in catta_interface_monitor_init_osdep"); - return -1; - } + (void)*m; // silence "unused paramter" warning // XXX register callbacks to get notified of interface/address changes @@ -139,7 +184,7 @@ int catta_interface_monitor_init_osdep(CattaInterfaceMonitor *m) void catta_interface_monitor_free_osdep(CattaInterfaceMonitor *m) { - catta_hashmap_free(m->osdep.idxmap); + (void)*m; // silence "unused paramter" warning } void catta_interface_monitor_sync(CattaInterfaceMonitor *m) @@ -170,7 +215,7 @@ void catta_interface_monitor_sync(CattaInterfaceMonitor *m) // create 'CattaInterface's for every adapter for(p=buf; p; p=p->Next) - ip_adapter_address(m, p); + ip_adapter(m, p); catta_free(buf);