+static void pfroute_parse_iface(meshlink_handle_t *mesh, const struct rt_msghdr *rtm) {
+ const struct if_msghdr *ifm = (const struct if_msghdr *)rtm;
+
+ if(ifm->ifm_flags & IFF_UP && ifm->ifm_flags & IFF_MULTICAST && !(ifm->ifm_flags & IFF_LOOPBACK)) {
+ iface_up(mesh, ifm->ifm_index);
+ } else {
+ iface_down(mesh, ifm->ifm_index);
+ }
+}
+
+static void pfroute_parse_addr(meshlink_handle_t *mesh, const struct rt_msghdr *rtm) {
+ const struct ifa_msghdr *ifam = (const struct ifa_msghdr *)rtm;
+ const char *p = (const char *)(ifam + 1);
+
+ for(unsigned int i = 1; i; i <<= 1) {
+ if(!(ifam->ifam_addrs & i)) {
+ continue;
+ }
+
+ const sockaddr_t *sa = (const sockaddr_t *)p;
+
+ if(i == RTA_IFA) {
+ discovery_address_t addr = {
+ .index = ifam->ifam_index,
+ };
+
+ if(sa->sa.sa_family == AF_INET) {
+ addr.address.in = sa->in;
+ addr.address.in.sin_port = ntohs(5353);
+ } else if(sa->sa.sa_family == AF_INET6) {
+ addr.address.in6 = sa->in6;
+ addr.address.in6.sin6_port = ntohs(5353);
+ } else {
+ addr.address.sa.sa_family = AF_UNKNOWN;
+ }
+
+ if(addr.address.sa.sa_family != AF_UNKNOWN) {
+ if(ifam->ifam_type == RTM_NEWADDR) {
+ addr_add(mesh, &addr);
+ } else {
+ addr_del(mesh, &addr);
+ }
+ }
+
+ break;
+ }
+
+ size_t len = (sa->sa.sa_len + 3) & ~3;
+ p += len;
+ }
+}
+