static void deps_diff (struct hs *hs, uint32_t port, const struct deps *deps, const struct tf *tf, const uint32_t *app, int napp) { for (int i = 0; i < deps->n; i++) { const struct dep *dep = &deps->deps[i]; if (app && !int_find (dep->rule, app, napp)) continue; if (dep->port > 0 && dep->port != port) continue; if (dep->port < 0 && !port_match (port, dep->port, tf)) continue; hs_diff (hs, DATA_ARR (dep->match)); } }
static void * reach_thread (void *vdata) { struct tdata *data = vdata; int sw = data->sw; struct list_res *res = &data->res; const uint32_t *out = g_out; int nout = g_nout; int ntfs = data_file->ntfs - 1; //int count = 0, loops = 0; while (true) { struct list_res queue = {0}; pthread_mutex_lock (&wait_lock); //fprintf (stderr, "%d %d\n", sw, queues[sw].n); while (!queues[sw].head) { waiters |= 1 << sw; if (waiters + 1 == 1 << ntfs) { for (int i = 0; i < ntfs; i++) { if (i == sw) continue; pthread_cond_broadcast (&conds[i]); } pthread_mutex_unlock (&wait_lock); return NULL; } pthread_cond_wait (&conds[sw], &wait_lock); if (waiters + 1 == 1 << ntfs) { pthread_mutex_unlock (&wait_lock); return NULL; } assert (waiters | (1 << sw)); } queue = queues[sw]; memset (&queues[sw], 0, sizeof queues[sw]); pthread_mutex_unlock (&wait_lock); struct res *cur; while ((cur = queue.head)) { list_pop (&queue); bool new_res = false; struct list_res nextqs[ntfs]; memset (nextqs, 0, sizeof nextqs); struct list_res ntf_res = ntf_apply (cur, sw); struct res *ntf_cur = ntf_res.head; while (ntf_cur) { struct res *ntf_next = ntf_cur->next; if (!out || int_find (ntf_cur->port, out, nout)) { list_append (res, ntf_cur); ref_add (ntf_cur, cur); if (out) { ntf_cur = ntf_next; continue; } } struct list_res ttf_res = tf_apply (tf_get (0), ntf_cur, true); struct res *ttf_cur = ttf_res.head; while (ttf_cur) { struct res *ttf_next = ttf_cur->next; if (is_loop (ttf_cur->port, cur)) { res_free (ttf_cur); ttf_cur = ttf_next; //loops++; continue; } ref_add (ttf_cur, cur); if (out && int_find (ttf_cur->port, out, nout)) list_append (res, ttf_cur); else { int new_sw = ntf_get_sw (ttf_cur->port); list_append (&nextqs[new_sw], ttf_cur); //count++; new_res = true; } ttf_cur = ttf_next; } if (out) res_free (ntf_cur); ntf_cur = ntf_next; } res_free_mt (cur, true); if (!new_res) continue; pthread_mutex_lock (&wait_lock); unsigned int wake = 0; for (int i = 0; i < ntfs; i++) { if (!nextqs[i].head) continue; list_concat (&queues[i], &nextqs[i]); pthread_cond_broadcast (&conds[i]); wake |= 1 << i; } waiters &= ~wake; pthread_mutex_unlock (&wait_lock); } } }
/* Initiliaze interfaces */ void update_interfaces (struct intnode *intn) { struct in6_addr addr; FILE *file; unsigned int prefixlen, scope, flags, ifindex; char devname[IFNAMSIZ]; /* Only update every 5 seconds to avoid rerunning it every packet */ if (g_conf->maxinterfaces) return; dbg ("Updating Interfaces\n"); /* Get link local addresses from /proc/net/if_inet6 */ file = fopen ("/proc/net/if_inet6", "r"); /* We can live without it though */ if (!file) { err ("Cannot open /proc/net/if_inet6\n"); return; } char buf[255]; /* Format "fe80000000000000029027fffe24bbab 02 0a 20 80 eth0" */ while (fgets (buf, sizeof (buf), file)) { if (21 != sscanf (buf, "%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx %x %x %x %x %8s", &addr.s6_addr[0], &addr.s6_addr[1], &addr.s6_addr[2], &addr.s6_addr[3], &addr.s6_addr[4], &addr.s6_addr[5], &addr.s6_addr[6], &addr.s6_addr[7], &addr.s6_addr[8], &addr.s6_addr[9], &addr.s6_addr[10], &addr.s6_addr[11], &addr.s6_addr[12], &addr.s6_addr[13], &addr.s6_addr[14], &addr.s6_addr[15], &ifindex, &prefixlen, &scope, &flags, devname)) { warn ("/proc/net/if_inet6 in wrong format!\n"); continue; } if (!IN6_IS_ADDR_LINKLOCAL (&addr) && (IN6_IS_ADDR_UNSPECIFIED (&addr) || IN6_IS_ADDR_LOOPBACK (&addr) || IN6_IS_ADDR_MULTICAST (&addr))) { continue; } if((intn=int_find(ifindex))==NULL) { g_conf->ints=(struct intnode*)realloc(g_conf->ints, sizeof(struct intnode)*(++g_conf->maxinterfaces)); if (!g_conf->ints) { err ("Cannot get memory for interface structures.\n"); } intn=g_conf->ints+g_conf->maxinterfaces-1; memset(intn, 0, sizeof(struct intnode)); } #ifdef WIN32 // Ugly WINXP workaround if(scope==0x20 && flags==0x80) { intn->mtu=1480; } else { intn->mtu=0; } #else intn->ifindex = ifindex; strcpy(intn->name, devname); struct ifreq ifreq; int sock; sock = socket (AF_INET6, SOCK_DGRAM, 0); if (sock < 0) { err ("Cannot get socket for setup\n"); } memcpy (&ifreq.ifr_name, &intn->name, sizeof (ifreq.ifr_name)); /* Get the MTU size of this interface */ /* We will use that for fragmentation */ if (ioctl (sock, SIOCGIFMTU, &ifreq) != 0) { warn ("Cannot get MTU size for %s index %d: %s\n", intn->name, intn->ifindex, strerror (errno)); } intn->mtu = ifreq.ifr_mtu; /* Get hardware address + type */ if (ioctl (sock, SIOCGIFHWADDR, &ifreq) != 0) { warn ("Cannot get hardware address for %s, interface index %d : %s\n", intn->name, intn->ifindex, strerror (errno)); } intn->hwaddr = ifreq.ifr_hwaddr; close (sock); #endif /* Link Local IPv6 address ? */ if (IN6_IS_ADDR_LINKLOCAL (&addr)) { /* Update the linklocal address */ intn->linklocal = addr; } else { intn->global = addr; } dbg ("Available interface %s index %u hardware %s/%u MTU %d\n", intn->name, intn->ifindex, (intn->hwaddr.sa_family == ARPHRD_ETHER ? "Ethernet" : (intn->hwaddr.sa_family == ARPHRD_SIT ? "sit" : "Unknown")), intn->hwaddr.sa_family, intn->mtu); } fclose (file); }
static bool port_match (uint32_t port, int32_t ofs, const struct tf *tf) { const struct ports *p = PORTS (tf, ofs); return int_find (port, p->arr, p->n); }
void update_interfaces (struct intnode *intn) { struct ifaddrs *myaddrs, *ifa; struct sockaddr_in *s4; struct sockaddr_in6 *s6; int if_index; /* * buf must be big enough for an IPv6 address (e.g. * 3ffe:2fa0:1010:ca22:020a:95ff:fe8a:1cf8) */ char buf[64]; if (getifaddrs(&myaddrs)) { err ("getifaddrs"); } for (ifa = myaddrs; ifa != NULL; ifa = ifa->ifa_next) { if (ifa->ifa_addr == NULL) continue; if ((ifa->ifa_flags & IFF_UP) == 0) continue; if_index=if_nametoindex(ifa->ifa_name); dbg("%s(%d): ", ifa->ifa_name,if_index); if(!if_index) { warn("cannot get interface index for %s\n",ifa->ifa_name); continue; } if((intn=int_find(if_index))==NULL) { g_conf->ints=(struct intnode*)realloc(g_conf->ints, sizeof(struct intnode)*(++g_conf->maxinterfaces)); if (!g_conf->ints) { err ("Cannot get memory for interface structures.\n"); } intn=g_conf->ints+g_conf->maxinterfaces-1; memset(intn, 0, sizeof(struct intnode)); } intn->ifindex=if_index; strcpy(intn->name,ifa->ifa_name); if(ifa->ifa_addr->sa_family == AF_LINK && ((struct if_data *)ifa->ifa_data)->ifi_type != IFT_LOOP && ifa->ifa_data) { dbg("MTU: %d\n", ((struct if_data *)ifa->ifa_data)->ifi_mtu); intn->mtu=((struct if_data *)ifa->ifa_data)->ifi_mtu; memcpy(&intn->hwaddr, ifa->ifa_addr, sizeof(struct sockaddr_in)); } if (ifa->ifa_addr->sa_family == AF_INET) { s4 = (struct sockaddr_in *) (ifa->ifa_addr); if (inet_ntop(ifa->ifa_addr->sa_family, (void *) &(s4->sin_addr), buf, sizeof(buf)) == NULL) { warn("%s: inet_ntop failed!\n", ifa->ifa_name); } else { dbg("%s\n", buf); } } else if (ifa->ifa_addr->sa_family == AF_INET6) { s6 = (struct sockaddr_in6 *) (ifa->ifa_addr); /* Link Local IPv6 address ? */ if (IN6_IS_ADDR_LINKLOCAL (&s6->sin6_addr)) { /* Update the linklocal address */ intn->linklocal = s6->sin6_addr; } else { intn->global = s6->sin6_addr; } if (inet_ntop(ifa->ifa_addr->sa_family, (void *) &(s6->sin6_addr), buf, sizeof(buf)) == NULL) { warn("%s: inet_ntop failed!\n", ifa->ifa_name); } else { dbg("%s\n", buf); } } } freeifaddrs(myaddrs); }