void my_browse_hook(struct mdns *m, int ev, const char *name, const char *app, const char *proto) { switch (ev) { case MDNS_SERVICE_UP: /* If no name, this is a service type */ if (name == NULL) { if (mdns_browse_add(m, app, proto) == -1) err(1, "mdns_browse_add"); return; } if (res->flags & F_RESOLV) { if (mdns_resolve(m, name, app, proto) == -1) err(1, "mdns_resolve"); return; } if (res->flags & F_SCRIPT) printf("up|proto|%s|app|%s|name|%s\n", proto, app, name); else printf("+++ %-48s %-20s %-3s\n", name, app, proto); break; case MDNS_SERVICE_DOWN: if (name != NULL) { if (res->flags & F_SCRIPT) printf("down|proto|%s|app|%s|name|%s\n", proto, app, name); else printf("--- %-48s %-20s %-3s\n", name, app, proto); } break; default: errx(1, "Unhandled event"); break; } }
int mdns_init(struct mdns_ctx **p_ctx, const char *addr, unsigned short port) { const uint32_t on_off = 1; const uint32_t ttl = 255; const uint8_t loop = 1; #ifdef _WIN32 union { struct sockaddr_storage ss; struct sockaddr_in sin; struct sockaddr_in6 sin6; } dumb; #endif /* _WIN32 */ struct mdns_ctx *ctx; if (p_ctx == NULL) return (MDNS_STDERR); *p_ctx = malloc(sizeof(struct mdns_ctx)); if (*p_ctx == NULL) return (MDNS_STDERR); ctx = *p_ctx; ctx->sock = INVALID_SOCKET; errno = os_init("2.2"); if (errno != 0) return (MDNS_NETERR); if (mdns_resolve(&ctx->addr, addr, port) < 0) return (MDNS_LKPERR); if ((ctx->sock = socket(ss_family(&ctx->addr), SOCK_DGRAM, IPPROTO_UDP)) == INVALID_SOCKET) return (MDNS_NETERR); if (setsockopt(ctx->sock, SOL_SOCKET, SO_REUSEADDR, (const void *) &on_off, sizeof(on_off)) < 0) return (MDNS_NETERR); #ifdef _WIN32 /* bind the receiver on any local address */ memset(&dumb, 0, sizeof(dumb)); dumb.ss.ss_family = ss_family(&ctx->addr); if (dumb.ss.ss_family == AF_INET) { dumb.sin.sin_port = htons(port); dumb.sin.sin_addr.s_addr = INADDR_ANY; } else { dumb.sin6.sin6_port = htons(port); dumb.sin6.sin6_addr = in6addr_any; } if (bind(ctx->sock, (const struct sockaddr *) &dumb, ss_len(&dumb.ss)) < 0) return (MDNS_NETERR); #else /* _WIN32 */ if (bind(ctx->sock, (const struct sockaddr *) &ctx->addr, ss_len(&ctx->addr)) < 0) return (MDNS_NETERR); #endif /* _WIN32 */ if (os_mcast_join(ctx->sock, &ctx->addr) < 0) return (MDNS_NETERR); if (setsockopt(ctx->sock, ss_level(&ctx->addr), ss_family(&ctx->addr)==AF_INET ? IP_MULTICAST_TTL : IPV6_MULTICAST_HOPS, (const void *) &ttl, sizeof(ttl)) < 0) return (MDNS_NETERR); if (setsockopt(ctx->sock, ss_level(&ctx->addr), IP_MULTICAST_LOOP, (const void *) &loop, sizeof(loop)) < 0) return (MDNS_NETERR); ctx->services = NULL; return (0); }