+static int
+_si_netconfig(uint32_t *v4, uint32_t *v6, uint32_t *v6to4)
+{
+ int status, checkit;
+ struct ifaddrs *ifa, *ifap;
+ struct sockaddr_in6 *sa6;
+
+ pthread_mutex_lock(&net_config_mutex);
+
+ checkit = 1;
+
+ if (net_config_token < 0)
+ {
+ status = notify_register_check(kNotifySCNetworkChange, &net_config_token);
+ if (status != 0) net_config_token = -1;
+ }
+
+ if (net_config_token >= 0)
+ {
+ status = notify_check(net_config_token, &checkit);
+ if (status != 0) checkit = 1;
+ }
+
+ status = 0;
+
+ if (checkit != 0)
+ {
+ if (getifaddrs(&ifa) < 0)
+ {
+ status = -1;
+ }
+ else
+ {
+ net_v4_count = 0;
+ net_v6_count = 0;
+ net_v6to4_count = 0;
+ for (ifap = ifa; ifap != NULL; ifap = ifap->ifa_next)
+ {
+ if (ifap->ifa_addr == NULL) continue;
+ if ((ifap->ifa_flags & IFF_UP) == 0) continue;
+
+ if (ifap->ifa_addr->sa_family == AF_INET)
+ {
+ net_v4_count++;
+ }
+ else if (ifap->ifa_addr->sa_family == AF_INET6)
+ {
+ net_v6_count++;
+ sa6 = (struct sockaddr_in6 *)ifap->ifa_addr;
+ if (sa6->sin6_addr.__u6_addr.__u6_addr16[0] == ntohs(V6TO4_PREFIX_16)) net_v6to4_count++;
+ }
+ }
+
+ freeifaddrs(ifa);
+ }
+ }
+
+ if (v4 != NULL) *v4 = net_v4_count;
+ if (v6 != NULL) *v6 = net_v6_count;
+ if (v6to4 != NULL) *v6to4 = net_v6to4_count;
+
+ pthread_mutex_unlock(&net_config_mutex);
+
+ return status;
+}
+