]> git.meshlink.io Git - catta/commitdiff
handle address change events
authorSven M. Hallberg <pesco@khjk.org>
Thu, 11 Sep 2014 18:55:17 +0000 (20:55 +0200)
committerSven M. Hallberg <pesco@khjk.org>
Thu, 11 Sep 2014 18:55:17 +0000 (20:55 +0200)
src/iface-windows.c

index 4dd0d6c2b38646df71c964a26c73d42ff7b52d5d..c62e96a31f7c980ff56bb9d1944701e8a2c7e721 100644 (file)
@@ -46,6 +46,17 @@ struct ChangeEvent {
 };
 
 
 };
 
 
+// helper: determine the global_scope flag for an address
+static void set_global_scope_flag(CattaInterfaceAddress *ifaddr, const CattaAddress *addr)
+{
+    if(addr->proto == CATTA_PROTO_INET6) {
+        const struct in6_addr *ia = (struct in6_addr *)addr->data.ipv6.address;
+        ifaddr->global_scope = !(IN6_IS_ADDR_LINKLOCAL(ia) || IN6_IS_ADDR_MULTICAST(ia));
+    } else {
+        ifaddr->global_scope = 1;
+    }
+}
+
 // integrate the information from an IP_ADAPTER_UNICAST_ADDRESS structure for
 // given CattaHwInterface into the CattaInterfaceMonitor
 static void ip_adapter_unicast_address(CattaInterfaceMonitor *m,
 // integrate the information from an IP_ADAPTER_UNICAST_ADDRESS structure for
 // given CattaHwInterface into the CattaInterfaceMonitor
 static void ip_adapter_unicast_address(CattaInterfaceMonitor *m,
@@ -91,16 +102,7 @@ static void ip_adapter_unicast_address(CattaInterfaceMonitor *m,
         }
     }
 
         }
     }
 
-    // set global scope flag
-    // XXX should we use the IP_ADAPTER_ADDRESS_DNS_ELIGIBLE flag for this?
-    //     it looks like it gets set for IPv4 addresses that are not localhost
-    //     and for IPv6 addresses with global scope. not sure about multicast
-    //     addresses.
-    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;
+    set_global_scope_flag(ifaddr, &addr);
 
     // XXX debugging, remove
     {
 
     // XXX debugging, remove
     {
@@ -256,7 +258,7 @@ static void WINAPI acn_callback(void *m, MIB_UNICASTIPADDRESS_ROW *row, MIB_NOTI
     queue_event(m, new_event(ADDRESS_CHANGE_EVENT, type, row, sizeof(*row)));
 }
 
     queue_event(m, new_event(ADDRESS_CHANGE_EVENT, type, row, sizeof(*row)));
 }
 
-void update_hw_interface(CattaHwInterface *hw)
+static void update_hw_interface(CattaHwInterface *hw)
 {
     MIB_IF_ROW2 row;
     DWORD r;
 {
     MIB_IF_ROW2 row;
     DWORD r;
@@ -316,6 +318,9 @@ void update_hw_interface(CattaHwInterface *hw)
             multicast,
             (int)row.AccessType);
     }
             multicast,
             (int)row.AccessType);
     }
+
+    catta_hw_interface_check_relevant(hw);
+    catta_hw_interface_update_rrs(hw, 0);
 }
 
 static void handle_iface_event(CattaInterfaceMonitor *m, MIB_IPINTERFACE_ROW *row, MIB_NOTIFICATION_TYPE type)
 }
 
 static void handle_iface_event(CattaInterfaceMonitor *m, MIB_IPINTERFACE_ROW *row, MIB_NOTIFICATION_TYPE type)
@@ -395,12 +400,30 @@ static void handle_iface_event(CattaInterfaceMonitor *m, MIB_IPINTERFACE_ROW *ro
 static void handle_addr_event(CattaInterfaceMonitor *m, MIB_UNICASTIPADDRESS_ROW *row, MIB_NOTIFICATION_TYPE type)
 {
     CattaIfIndex idx = row->InterfaceIndex;
 static void handle_addr_event(CattaInterfaceMonitor *m, MIB_UNICASTIPADDRESS_ROW *row, MIB_NOTIFICATION_TYPE type)
 {
     CattaIfIndex idx = row->InterfaceIndex;
-    CattaProtocol proto = catta_af_to_proto(row->Address.si_family);
-    const char *protostr = catta_proto_to_string(proto);
+    CattaInterfaceAddress *ifaddr;
+    CattaInterface *iface;
+    CattaAddress addr;
+    const char *protostr;
+
+    // fill addr struct for address lookup
+    switch(row->Address.si_family) {
+    case AF_INET:
+        memcpy(addr.data.data, &row->Address.Ipv4.sin_addr, sizeof(struct in_addr));
+        break;
+    case AF_INET6:
+        memcpy(addr.data.data, &row->Address.Ipv6.sin6_addr, sizeof(struct in6_addr));
+        break;
+    default:
+        catta_log_debug("unexpected address family on interface %d: %u", idx, row->Address.si_family);
+        return;
+    }
+    addr.proto = catta_af_to_proto(row->Address.si_family);
+    protostr = catta_proto_to_string(addr.proto);
 
     // XXX debug, remove
     {
         const char *typestr = NULL;
 
     // XXX debug, remove
     {
         const char *typestr = NULL;
+        char buf[CATTA_ADDRESS_STR_MAX];
 
         switch(type) {
             case MibParameterNotification:  typestr = "ParameterNotification"; break;
 
         switch(type) {
             case MibParameterNotification:  typestr = "ParameterNotification"; break;
@@ -409,19 +432,81 @@ static void handle_addr_event(CattaInterfaceMonitor *m, MIB_UNICASTIPADDRESS_ROW
             default:                        typestr = "Unknown";
         }
 
             default:                        typestr = "Unknown";
         }
 
-        catta_log_debug("address %s on iface %d for %s", typestr, idx, protostr);
+        catta_log_debug("%s for %s address %s on iface %d",
+                        typestr, protostr,
+                        catta_address_snprint(buf, sizeof(buf), &addr),
+                        idx);
     }
 
     }
 
+    // see if we know this address/interface
+    iface = catta_interface_monitor_get_interface(m, idx, addr.proto);
+    ifaddr = iface ? catta_interface_monitor_get_address(m, iface, &addr) : NULL;
+
+    // print debug messages for some unexpected cases
+    if(type==MibParameterNotification && !ifaddr)
+        catta_log_debug("ParameterNotification received for unknown address on interface %d (%s)", idx, protostr);
+    if(type==MibDeleteInstance && !ifaddr)
+        catta_log_debug("DeleteInstance received for unknown address on interface %d (%s)", idx, protostr);
+    if(type==MibAddInstance && ifaddr)
+        catta_log_debug("AddInstance received for existing address on interface %d (%s)", idx, protostr);
+    if(ifaddr && !iface)
+        catta_log_debug("missing CattaInterface for address on interface %d (%s)", idx, protostr);
+
     switch(type) {
     case MibParameterNotification:
     switch(type) {
     case MibParameterNotification:
-        break;
     case MibAddInstance:
     case MibAddInstance:
+        // fetch the full event data
+        if(GetUnicastIpAddressEntry(row) != NO_ERROR) {
+            catta_log_error("GetUnicastIpAddressEntry failed in handle_addr_event");
+            return;
+        }
+
+        // skip addresses that are not suitable as source addresses
+        if(row->SkipAsSource)
+            return;
+
+        // create the interface if it is missing
+        if(!iface) {
+            CattaHwInterface *hw;
+
+            if((hw = catta_interface_monitor_get_hw_interface(m, idx)) == NULL) {
+                catta_log_error("interface %d not found in handle_addr_event", idx);
+                return;
+            }
+
+            if((iface = catta_interface_new(m, hw, addr.proto)) == NULL) {
+                catta_log_error("catta_interface_new failed in handle_addr_event");
+                return;
+            }
+        }
+        assert(iface != NULL);
+
+        // create the interface-associated address if it is missing
+        if(!ifaddr) {
+            unsigned prefixlen = row->OnLinkPrefixLength;
+
+            if((ifaddr = catta_interface_address_new(m, iface, &addr, prefixlen)) == NULL) {
+                catta_log_error("catta_interface_address_new failed in handle_addr_event");
+                return;
+            }
+        }
+        assert(ifaddr != NULL);
+
+        set_global_scope_flag(ifaddr, &addr);
+        catta_log_debug("   global_scope: %d", ifaddr->global_scope); // XXX debugging, remove
         break;
     case MibDeleteInstance:
         break;
     case MibDeleteInstance:
+        if(ifaddr)
+            catta_interface_address_free(ifaddr);
         break;
     default:
         catta_log_debug("unexpected type (%d) of address change notification received", type);
     }
         break;
     default:
         catta_log_debug("unexpected type (%d) of address change notification received", type);
     }
+
+    if(iface) {
+        catta_interface_check_relevant(iface);
+        catta_interface_update_rrs(iface, 0);
+    }
 }
 
 static void handle_events(CattaInterfaceMonitor *m)
 }
 
 static void handle_events(CattaInterfaceMonitor *m)