int main(int argc, char *argv[]) { int r = 0; char err[128]; struct mdns_ctx *ctx; signal(SIGINT, sighandler); signal(SIGTERM, sighandler); if ((r = mdns_init(&ctx, MDNS_ADDR_IPV4, MDNS_PORT)) < 0) goto err; // test with `ping mdnshost.local` mdns_announce(ctx, "mdnshost.local", RR_A, callback, ctx); if ((r = mdns_serve(ctx, stop, NULL)) < 0) goto err; err: if (r < 0) { mdns_strerror(r, err, sizeof(err)); fprintf(stderr, "fatal: %s\n", err); } mdns_destroy(ctx); return (0); }
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 = NULL; ctx = malloc(sizeof(struct mdns_ctx)); if (ctx == NULL) return (MDNS_STDERR); ctx->services = NULL; ctx->sock = INVALID_SOCKET; errno = os_init("2.2"); if (errno != 0) return mdns_destroy(ctx), (MDNS_NETERR); if (mdns_resolve(&ctx->addr, addr, port) < 0) return mdns_destroy(ctx), (MDNS_LKPERR); if ((ctx->sock = socket(ss_family(&ctx->addr), SOCK_DGRAM, IPPROTO_UDP)) == INVALID_SOCKET) return mdns_destroy(ctx), (MDNS_NETERR); if (setsockopt(ctx->sock, SOL_SOCKET, SO_REUSEADDR, (const void *) &on_off, sizeof(on_off)) < 0) return mdns_destroy(ctx), (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_destroy(ctx), (MDNS_NETERR); #else /* _WIN32 */ if (bind(ctx->sock, (const struct sockaddr *) &ctx->addr, ss_len(&ctx->addr)) < 0) return mdns_destroy(ctx), (MDNS_NETERR); #endif /* _WIN32 */ if (os_mcast_join(ctx->sock, &ctx->addr) < 0) return mdns_destroy(ctx), (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_destroy(ctx), (MDNS_NETERR); if (setsockopt(ctx->sock, ss_level(&ctx->addr), IP_MULTICAST_LOOP, (const void *) &loop, sizeof(loop)) < 0) return mdns_destroy(ctx), (MDNS_NETERR); *p_ctx = ctx; return (0); }