123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275 |
- /*
- * tinysvcmdns - a tiny MDNS implementation for publishing services
- * Copyright (C) 2011 Darell Tan
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. The name of the author may not be used to endorse or promote products
- * derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
- #ifndef _WIN32
- #define _GNU_SOURCE
- #endif
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <stdbool.h>
- #include <signal.h>
- #include <stdint.h>
- #ifdef _WIN32
- #include <winsock2.h>
- #include <iphlpapi.h>
- #pragma comment(lib, "IPHLPAPI.lib")
- typedef uint32_t in_addr_t;
- #define strcasecmp stricmp
- #elif defined (__linux__) || defined (__FreeBSD__) || defined (sun)
- #include <unistd.h>
- #include <sys/socket.h>
- #include <netdb.h>
- #include <arpa/inet.h>
- #include <sys/ioctl.h>
- #include <net/if.h>
- #include <strings.h>
- #include <ifaddrs.h>
- #if defined (__FreeBSD__) || defined (sun)
- #include <net/if_dl.h>
- #include <net/if_types.h>
- #endif
- #if defined (sun)
- #include <sys/sockio.h>
- #endif
- #elif defined (__APPLE__)
- #include <unistd.h>
- #include <sys/socket.h>
- #include <netdb.h>
- #include <arpa/inet.h>
- #include <sys/ioctl.h>
- #include <net/if.h>
- #include <ifaddrs.h>
- #endif
- #include "mdnssvc.h"
- struct mdns_service *svc;
- struct mdnsd *svr;
- /*---------------------------------------------------------------------------*/
- #ifdef _WIN32
- static void winsock_init(void) {
- WSADATA wsaData;
- WORD wVersionRequested = MAKEWORD(2, 2);
- int WSerr = WSAStartup(wVersionRequested, &wsaData);
- if (WSerr != 0) exit(1);
- }
- /*---------------------------------------------------------------------------*/
- static void winsock_close(void) {
- WSACleanup();
- }
- #endif
- /*---------------------------------------------------------------------------*/
- struct in_addr get_interface(char* iface) {
- struct in_addr addr;
- // try to get the address from the parameter
- addr.s_addr = iface && *iface ? inet_addr(iface) : INADDR_NONE;
- // if we already are given an address; just use it
- if (addr.s_addr != INADDR_NONE) return addr;
- #ifdef _WIN32
- struct sockaddr_in* host = NULL;
- ULONG size = sizeof(IP_ADAPTER_ADDRESSES) * 32;
- // otherwise we need to loop and find somethign that works
- IP_ADAPTER_ADDRESSES* adapters = (IP_ADAPTER_ADDRESSES*)malloc(size);
- int ret = GetAdaptersAddresses(AF_UNSPEC, GAA_FLAG_INCLUDE_GATEWAYS | GAA_FLAG_SKIP_MULTICAST | GAA_FLAG_SKIP_ANYCAST, 0, adapters, &size);
- for (PIP_ADAPTER_ADDRESSES adapter = adapters; adapter; adapter = adapter->Next) {
- if (adapter->TunnelType == TUNNEL_TYPE_TEREDO ||
- adapter->OperStatus != IfOperStatusUp || 0)
- continue;
- char name[256];
- wcstombs(name, adapter->FriendlyName, sizeof(name));
- if (iface && *iface && strcasecmp(iface, name)) continue;
- for (IP_ADAPTER_UNICAST_ADDRESS* unicast = adapter->FirstUnicastAddress; unicast;
- unicast = unicast->Next) {
- if (adapter->FirstGatewayAddress && unicast->Address.lpSockaddr->sa_family == AF_INET) {
- addr = ((struct sockaddr_in*)unicast->Address.lpSockaddr)->sin_addr;
- return addr;
- }
- }
- }
- return addr;
- #else
- struct ifaddrs* ifaddr;
- if (getifaddrs(&ifaddr) == -1) return addr;
- for (struct ifaddrs* ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next) {
- if (ifa->ifa_addr == NULL || ifa->ifa_addr->sa_family != AF_INET ||
- !(ifa->ifa_flags & IFF_UP) || !(ifa->ifa_flags & IFF_MULTICAST) ||
- ifa->ifa_flags & IFF_LOOPBACK ||
- (iface && *iface && strcasecmp(iface, ifa->ifa_name)))
- continue;
- addr = ((struct sockaddr_in*)ifa->ifa_addr)->sin_addr;
- break;
- }
- freeifaddrs(ifaddr);
- return addr;
- #endif
- }
- #ifdef _WIN32
- /*----------------------------------------------------------------------------*/
- int asprintf(char** strp, const char* fmt, ...)
- {
- va_list args;
- va_start(args, fmt);
- int len = vsnprintf(NULL, 0, fmt, args);
- *strp = malloc(len + 1);
- if (*strp) len = vsprintf(*strp, fmt, args);
- else len = 0;
- va_end(args);
- return len;
- }
- #endif
- /*---------------------------------------------------------------------------*/
- static void print_usage(void) {
- printf("[-v] [-o <ip|ifname>] -i <identity> -t <type> -p <port> [<txt>] ...[<txt>]\n");
- }
- /*---------------------------------------------------------------------------*/
- static void sighandler(int signum) {
- mdnsd_stop(svr);
- #ifdef _WIN32
- winsock_close();
- #endif
- exit(0);
- }
- /*---------------------------------------------------------------------------*/
- /* */
- /*---------------------------------------------------------------------------*/
- int main(int argc, char *argv[]) {
- const char** txt = NULL;
- struct in_addr host;
- char hostname[256],* arg, * identity = NULL, * type = NULL, * addr = NULL;
- int port = 0;
- bool verbose = false;
- if (argc <= 2) {
- print_usage();
- exit(0);
- }
- #ifdef _WIN32
- winsock_init();
- #endif
- signal(SIGINT, sighandler);
- signal(SIGTERM, sighandler);
- #if defined(SIGPIPE)
- signal(SIGPIPE, SIG_IGN);
- #endif
- #if defined(SIGQUIT)
- signal(SIGQUIT, sighandler);
- #endif
- #if defined(SIGHUP)
- signal(SIGHUP, sighandler);
- #endif
- while ((arg = *++argv) != NULL) {
- if (!strcasecmp(arg, "-o") || !strcasecmp(arg, "host")) {
- addr = *++argv;
- argc -= 2;
- } else if (!strcasecmp(arg, "-p")) {
- port = atoi(*++argv);
- } else if (!strcasecmp(arg, "-v")) {
- verbose = true;
- } else if (!strcasecmp(arg, "-t")) {
- (void)! asprintf(&type, "%s.local", *++argv);
- } else if (!strcasecmp(arg, "-i")) {
- identity = *++argv;
- } else {
- // nothing let's try to be smart and handle legacy crappy
- if (!identity) identity = *argv;
- else if (!type) (void) !asprintf(&type, "%s.local", *argv);
- else if (!port) port = atoi(*argv);
- else {
- txt = (const char**) malloc((argc + 1) * sizeof(char**));
- memcpy(txt, argv, argc * sizeof(char**));
- txt[argc] = NULL;
- }
- argc--;
- }
- }
- gethostname(hostname, sizeof(hostname));
- strcat(hostname, ".local");
- host = get_interface(addr);
- svr = mdnsd_start(host, verbose);
- if (svr) {
- printf("host: %s\nidentity: %s\ntype: %s\nip: %s\nport: %u\n", hostname, identity, type, inet_ntoa(host), port);
- mdnsd_set_hostname(svr, hostname, host);
- svc = mdnsd_register_svc(svr, identity, type, port, NULL, txt);
- mdns_service_destroy(svc);
- #ifdef _WIN32
- Sleep(INFINITE);
- #else
- pause();
- #endif
- mdnsd_stop(svr);
- } else {
- printf("Can't start server");
- print_usage();
- }
- free(type);
- free(txt);
- #ifdef _WIN32
- winsock_close();
- #endif
- return 0;
- }
|