2
0

mdnsd.c 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866
  1. /*
  2. * tinysvcmdns - a tiny MDNS implementation for publishing services
  3. * Copyright (C) 2011 Darell Tan
  4. * All rights reserved.
  5. *
  6. * Redistribution and use in source and binary forms, with or without
  7. * modification, are permitted provided that the following conditions
  8. * are met:
  9. * 1. Redistributions of source code must retain the above copyright
  10. * notice, this list of conditions and the following disclaimer.
  11. * 2. Redistributions in binary form must reproduce the above copyright
  12. * notice, this list of conditions and the following disclaimer in the
  13. * documentation and/or other materials provided with the distribution.
  14. * 3. The name of the author may not be used to endorse or promote products
  15. * derived from this software without specific prior written permission.
  16. *
  17. * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
  18. * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  19. * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
  20. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
  21. * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  22. * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  23. * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  24. * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  25. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  26. * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  27. */
  28. #ifdef _WIN32
  29. #include <winsock2.h>
  30. #include <ws2tcpip.h>
  31. #define LOG_ERR 3
  32. #else
  33. #include <sys/select.h>
  34. #include <sys/socket.h>
  35. #include <sys/ioctl.h>
  36. #include <netinet/in.h>
  37. #include <arpa/inet.h>
  38. #include <net/if.h>
  39. #include <syslog.h>
  40. #endif
  41. #include <sys/types.h>
  42. #include <sys/stat.h>
  43. #include <fcntl.h>
  44. #include <signal.h>
  45. #include <string.h>
  46. #include <stdio.h>
  47. #include <stdlib.h>
  48. #include <stdarg.h>
  49. #ifndef _WIN32
  50. #include <unistd.h>
  51. #endif
  52. #include <assert.h>
  53. #if __has_include(<pthread.h>)
  54. #include <pthread.h>
  55. #define mutex_lock(m) pthread_mutex_lock(&m);
  56. #define mutex_unlock(m) pthread_mutex_unlock(&m);
  57. #elif _WIN32
  58. #define USE_WIN32_THREAD
  59. #define mutex_lock(m) WaitForSingleObject(m, INFINITE);
  60. #define mutex_unlock(m) ReleaseMutex(m);
  61. #else
  62. #error missing pthread
  63. #endif
  64. #include "mdns.h"
  65. #include "mdnssvc.h"
  66. #if _MSC_VER
  67. #define ssize_t SSIZE_T
  68. #endif
  69. #define MDNS_ADDR "224.0.0.251"
  70. #define MDNS_PORT 5353
  71. #define PACKET_SIZE 65536
  72. #define SERVICES_DNS_SD_NLABEL \
  73. ((uint8_t *) "\x09_services\x07_dns-sd\x04_udp\x05local")
  74. #define log_message(l,f,...) mdnsd_log(true, f, ##__VA_ARGS__)
  75. struct mdnsd {
  76. #ifdef USE_WIN32_THREAD
  77. HANDLE data_lock;
  78. #else
  79. pthread_mutex_t data_lock;
  80. #endif
  81. int sockfd;
  82. int notify_pipe[2];
  83. int stop_flag;
  84. struct rr_group *group;
  85. struct rr_list *announce;
  86. struct rr_list *services;
  87. struct rr_list *leave;
  88. uint8_t *hostname;
  89. };
  90. struct mdns_service {
  91. struct rr_list *entries;
  92. };
  93. static bool log_verbose;
  94. /////////////////////////////////
  95. void mdnsd_log(bool force, char* fmt, ...) {
  96. if (force || log_verbose) {
  97. va_list ap;
  98. va_start(ap, fmt);
  99. int size = vsnprintf(NULL, 0, fmt, ap);
  100. if (size > 0) {
  101. char* buf = malloc(size + 1);
  102. vsprintf(buf, fmt, ap);
  103. fprintf(stderr, "%s", buf);
  104. free(buf);
  105. }
  106. va_end(ap);
  107. }
  108. }
  109. static int create_recv_sock(uint32_t host) {
  110. int sd = socket(AF_INET, SOCK_DGRAM, 0);
  111. int r = -1;
  112. int on = 1;
  113. char onChar = 1;
  114. struct sockaddr_in serveraddr;
  115. struct ip_mreq mreq;
  116. unsigned char ttl = 255;
  117. if (sd < 0) {
  118. log_message(LOG_ERR, "recv socket(): %m\n");
  119. return sd;
  120. }
  121. if ((r = setsockopt(sd, SOL_SOCKET, SO_REUSEADDR, (char *) &on, sizeof(on))) < 0) {
  122. log_message(LOG_ERR, "recv setsockopt(SO_REUSEADDR): %m\n");
  123. return r;
  124. }
  125. #if !defined(_WIN32)
  126. on = sizeof(on);
  127. socklen_t len;
  128. if (!getsockopt(sd, SOL_SOCKET, SO_REUSEPORT,(char*) &on, &len)) {
  129. on = 1;
  130. if ((r = setsockopt(sd, SOL_SOCKET, SO_REUSEPORT,(char*) &on, sizeof(on))) < 0) {
  131. log_message(LOG_ERR, "recv setsockopt(SO_REUSEPORT): %m\n", r);
  132. }
  133. }
  134. #endif
  135. /* bind to an address */
  136. memset(&serveraddr, 0, sizeof(serveraddr));
  137. serveraddr.sin_family = AF_INET;
  138. serveraddr.sin_port = htons(MDNS_PORT);
  139. serveraddr.sin_addr.s_addr = htonl(INADDR_ANY); /* receive multicast */
  140. if ((r = bind(sd, (struct sockaddr *)&serveraddr, sizeof(serveraddr))) < 0) {
  141. log_message(LOG_ERR, "recv bind(): %m\n");
  142. return r;
  143. }
  144. memset(&mreq, 0, sizeof(struct ip_mreq));
  145. mreq.imr_interface.s_addr = host;
  146. if ((r = setsockopt(sd, IPPROTO_IP, IP_MULTICAST_IF, (char*) &mreq.imr_interface.s_addr, sizeof(mreq.imr_interface.s_addr))) < 0) {
  147. log_message(LOG_ERR, "recv setsockopt(IP_PROTO_IP): %m\n");
  148. return r;
  149. }
  150. if ((r = setsockopt(sd, IPPROTO_IP, IP_MULTICAST_TTL, (void*) &ttl, sizeof(ttl))) < 0) {
  151. log_message(LOG_ERR, "recv setsockopt(IP_MULTICAST_IP): %m\n");
  152. return r;
  153. }
  154. // add membership to receiving socket
  155. mreq.imr_multiaddr.s_addr = inet_addr(MDNS_ADDR);
  156. if ((r = setsockopt(sd, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char *) &mreq, sizeof(mreq))) < 0) {
  157. log_message(LOG_ERR, "recv setsockopt(IP_ADD_MEMBERSHIP): %m\n");
  158. return r;
  159. }
  160. // enable loopback in case someone else needs the data
  161. if ((r = setsockopt(sd, IPPROTO_IP, IP_MULTICAST_LOOP, (char *) &onChar, sizeof(onChar))) < 0) {
  162. log_message(LOG_ERR, "recv setsockopt(IP_MULTICAST_LOOP): %m\n");
  163. return r;
  164. }
  165. #ifdef IP_PKTINFO
  166. on = 1;
  167. if ((r = setsockopt(sd, IPPROTO_IP, IP_PKTINFO, (char *) &on, sizeof(on))) < 0) {
  168. log_message(LOG_ERR, "recv setsockopt(IP_PKTINFO): %m\n");
  169. return r;
  170. }
  171. #endif
  172. return sd;
  173. }
  174. static ssize_t send_packet(int fd, const void *data, size_t len) {
  175. static struct sockaddr_in toaddr;
  176. if (toaddr.sin_family != AF_INET) {
  177. memset(&toaddr, 0, sizeof(struct sockaddr_in));
  178. toaddr.sin_family = AF_INET;
  179. toaddr.sin_port = htons(MDNS_PORT);
  180. toaddr.sin_addr.s_addr = inet_addr(MDNS_ADDR);
  181. }
  182. return sendto(fd, data, len, 0, (struct sockaddr *) &toaddr, sizeof(struct sockaddr_in));
  183. }
  184. // populate the specified list which matches the RR name and type
  185. // type can be RR_ANY, which populates all entries EXCEPT RR_NSEC
  186. static int populate_answers(struct mdnsd *svr, struct rr_list **rr_head, uint8_t *name, enum rr_type type) {
  187. int num_ans = 0;
  188. struct rr_group *ans_grp;
  189. struct rr_list *n;
  190. // check if we have the records
  191. mutex_lock(svr->data_lock);
  192. ans_grp = rr_group_find(svr->group, name);
  193. if (ans_grp == NULL) {
  194. mutex_unlock(svr->data_lock);
  195. return num_ans;
  196. }
  197. // decide which records should go into answers
  198. n = ans_grp->rr;
  199. for (; n; n = n->next) {
  200. // exclude NSEC for RR_ANY
  201. if (type == RR_ANY && n->e->type == RR_NSEC)
  202. continue;
  203. if ((type == n->e->type || type == RR_ANY) && cmp_nlabel(name, n->e->name) == 0) {
  204. num_ans += rr_list_append(rr_head, n->e);
  205. }
  206. }
  207. mutex_unlock(svr->data_lock);
  208. return num_ans;
  209. }
  210. // given a list of RRs, look up related records and add them
  211. static void add_related_rr(struct mdnsd *svr, struct rr_list *list, struct mdns_pkt *reply) {
  212. for (; list; list = list->next) {
  213. struct rr_entry *ans = list->e;
  214. switch (ans->type) {
  215. case RR_PTR:
  216. // target host A, AAAA records
  217. reply->num_add_rr += populate_answers(svr, &reply->rr_add,
  218. MDNS_RR_GET_PTR_NAME(ans), RR_ANY);
  219. break;
  220. case RR_SRV:
  221. // target host A, AAAA records
  222. reply->num_add_rr += populate_answers(svr, &reply->rr_add,
  223. ans->data.SRV.target, RR_ANY);
  224. // perhaps TXT records of the same name?
  225. // if we use RR_ANY, we risk pulling in the same RR_SRV
  226. reply->num_add_rr += populate_answers(svr, &reply->rr_add,
  227. ans->name, RR_TXT);
  228. break;
  229. case RR_A:
  230. case RR_AAAA:
  231. reply->num_add_rr += populate_answers(svr, &reply->rr_add,
  232. ans->name, RR_NSEC);
  233. break;
  234. default:
  235. // nothing to add
  236. break;
  237. }
  238. }
  239. }
  240. // creates an announce packet given the type name PTR
  241. static void announce_srv(struct mdnsd *svr, struct mdns_pkt *reply, uint8_t *name) {
  242. mdns_init_reply(reply, 0);
  243. reply->num_ans_rr += populate_answers(svr, &reply->rr_ans, name, RR_PTR);
  244. // remember to add the services dns-sd PTR too
  245. reply->num_ans_rr += populate_answers(svr, &reply->rr_ans,
  246. SERVICES_DNS_SD_NLABEL, RR_PTR);
  247. // see if we can match additional records for answers
  248. add_related_rr(svr, reply->rr_ans, reply);
  249. // additional records for additional records
  250. add_related_rr(svr, reply->rr_add, reply);
  251. }
  252. // processes the incoming MDNS packet
  253. // returns >0 if processed, 0 otherwise
  254. static int process_mdns_pkt(struct mdnsd *svr, struct mdns_pkt *pkt, struct mdns_pkt *reply) {
  255. int i;
  256. struct rr_list *qnl;
  257. struct rr_list *ans, *prev_ans;
  258. assert(pkt != NULL);
  259. // is it standard query?
  260. if ((pkt->flags & MDNS_FLAG_RESP) == 0 &&
  261. MDNS_FLAG_GET_OPCODE(pkt->flags) == 0) {
  262. mdns_init_reply(reply, pkt->id);
  263. DEBUG_PRINTF("flags = %04x, qn = %d, ans = %d, add = %d\n",
  264. pkt->flags,
  265. pkt->num_qn,
  266. pkt->num_ans_rr,
  267. pkt->num_add_rr);
  268. // loop through questions
  269. qnl = pkt->rr_qn;
  270. for (i = 0; i < pkt->num_qn; i++, qnl = qnl->next) {
  271. struct rr_entry *qn = qnl->e;
  272. int num_ans_added = 0;
  273. char *namestr = nlabel_to_str(qn->name);
  274. DEBUG_PRINTF("qn #%d: type %s (%02x) %s - ", i, rr_get_type_name(qn->type), qn->type, namestr);
  275. free(namestr);
  276. // mark that a unicast response is desired
  277. reply->unicast |= qn->unicast_query;
  278. num_ans_added = populate_answers(svr, &reply->rr_ans, qn->name, qn->type);
  279. reply->num_ans_rr += num_ans_added;
  280. DEBUG_PRINTF("added %d answers\n", num_ans_added);
  281. }
  282. // remove our replies if they were already in their answers
  283. ans = NULL; prev_ans = NULL;
  284. for (ans = reply->rr_ans; ans; ) {
  285. struct rr_list *next_ans = ans->next;
  286. struct rr_entry *known_ans = rr_entry_match(pkt->rr_ans, ans->e);
  287. // discard answers that have at least half of the actual TTL
  288. if (known_ans != NULL && known_ans->ttl >= ans->e->ttl / 2) {
  289. char *namestr = nlabel_to_str(ans->e->name);
  290. DEBUG_PRINTF("removing answer for %s\n", namestr);
  291. free(namestr);
  292. // check if list item is head
  293. if (prev_ans == NULL)
  294. reply->rr_ans = ans->next;
  295. else
  296. prev_ans->next = ans->next;
  297. free(ans);
  298. ans = prev_ans;
  299. // adjust answer count
  300. reply->num_ans_rr--;
  301. }
  302. prev_ans = ans;
  303. ans = next_ans;
  304. }
  305. // see if we can match additional records for answers
  306. add_related_rr(svr, reply->rr_ans, reply);
  307. // additional records for additional records
  308. add_related_rr(svr, reply->rr_add, reply);
  309. DEBUG_PRINTF("\n");
  310. return reply->num_ans_rr;
  311. }
  312. return 0;
  313. }
  314. int create_pipe(int handles[2]) {
  315. #ifdef _WIN32
  316. SOCKET sock = socket(AF_INET, SOCK_STREAM, 0);
  317. struct sockaddr_in serv_addr;
  318. int len;
  319. if (sock == INVALID_SOCKET) {
  320. return -1;
  321. }
  322. memset(&serv_addr, 0, sizeof(serv_addr));
  323. serv_addr.sin_family = AF_INET;
  324. serv_addr.sin_port = htons(0);
  325. serv_addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
  326. if (bind(sock, (struct sockaddr*)&serv_addr, sizeof(serv_addr)) == SOCKET_ERROR) {
  327. closesocket(sock);
  328. return -1;
  329. }
  330. if (listen(sock, 1) == SOCKET_ERROR) {
  331. closesocket(sock);
  332. return -1;
  333. }
  334. len = sizeof(serv_addr);
  335. if (getsockname(sock, (SOCKADDR*)&serv_addr, &len) == SOCKET_ERROR) {
  336. closesocket(sock);
  337. return -1;
  338. }
  339. if ((handles[1] = socket(PF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET) {
  340. closesocket(sock);
  341. return -1;
  342. }
  343. if (connect(handles[1], (struct sockaddr*)&serv_addr, len) == SOCKET_ERROR) {
  344. closesocket(sock);
  345. return -1;
  346. }
  347. if ((handles[0] = accept(sock, (struct sockaddr*)&serv_addr, &len)) == INVALID_SOCKET) {
  348. closesocket((SOCKET)handles[1]);
  349. handles[1] = INVALID_SOCKET;
  350. closesocket(sock);
  351. return -1;
  352. }
  353. closesocket(sock);
  354. return 0;
  355. #else
  356. return pipe(handles);
  357. #endif
  358. }
  359. int read_pipe(int s, char* buf, int len) {
  360. #ifdef _WIN32
  361. int ret = recv(s, buf, len, 0);
  362. if (ret < 0 && WSAGetLastError() == WSAECONNRESET) {
  363. ret = 0;
  364. }
  365. return ret;
  366. #else
  367. return read(s, buf, len);
  368. #endif
  369. }
  370. int write_pipe(int s, char* buf, int len) {
  371. #ifdef _WIN32
  372. return send(s, buf, len, 0);
  373. #else
  374. return write(s, buf, len);
  375. #endif
  376. }
  377. int close_pipe(int s) {
  378. #ifdef _WIN32
  379. return closesocket(s);
  380. #else
  381. return close(s);
  382. #endif
  383. }
  384. // main loop to receive, process and send out MDNS replies
  385. // also handles MDNS service announces
  386. static void main_loop(struct mdnsd *svr) {
  387. fd_set sockfd_set;
  388. int max_fd = svr->sockfd;
  389. char notify_buf[2]; // buffer for reading of notify_pipe
  390. struct mdns_pkt *mdns_reply;
  391. struct mdns_pkt *mdns;
  392. struct rr_list *svc_le;
  393. void *pkt_buffer = malloc(PACKET_SIZE);
  394. if (svr->notify_pipe[0] > max_fd)
  395. max_fd = svr->notify_pipe[0];
  396. mdns_reply = malloc(sizeof(struct mdns_pkt));
  397. memset(mdns_reply, 0, sizeof(struct mdns_pkt));
  398. while (! svr->stop_flag) {
  399. FD_ZERO(&sockfd_set);
  400. FD_SET(svr->sockfd, &sockfd_set);
  401. FD_SET(svr->notify_pipe[0], &sockfd_set);
  402. select(max_fd + 1, &sockfd_set, NULL, NULL, NULL);
  403. if (FD_ISSET(svr->notify_pipe[0], &sockfd_set)) {
  404. // flush the notify_pipe
  405. read_pipe(svr->notify_pipe[0], (char*)&notify_buf, 1);
  406. } else if (FD_ISSET(svr->sockfd, &sockfd_set)) {
  407. struct sockaddr_in fromaddr;
  408. socklen_t sockaddr_size = sizeof(struct sockaddr_in);
  409. ssize_t recvsize = recvfrom(svr->sockfd, pkt_buffer, PACKET_SIZE, 0,
  410. (struct sockaddr *) &fromaddr, &sockaddr_size);
  411. if (recvsize < 0) {
  412. log_message(LOG_ERR, "recv(): %m\n");
  413. }
  414. DEBUG_PRINTF("data from=%s size=%ld\n", inet_ntoa(fromaddr.sin_addr), (long) recvsize);
  415. mdns = mdns_parse_pkt(pkt_buffer, recvsize);
  416. if (mdns != NULL) {
  417. if (process_mdns_pkt(svr, mdns, mdns_reply)) {
  418. size_t replylen = mdns_encode_pkt(mdns_reply, pkt_buffer, PACKET_SIZE);
  419. if (mdns_reply->unicast) {
  420. int sock = socket(fromaddr.sin_family, SOCK_DGRAM, 0);
  421. sendto(sock, pkt_buffer, replylen, 0, (void*) &fromaddr, sizeof(struct sockaddr_in));
  422. DEBUG_PRINTF("unicast answer\n");
  423. #ifdef _WIN32
  424. closesocket(sock);
  425. #else
  426. close(sock);
  427. #endif
  428. } else {
  429. send_packet(svr->sockfd, pkt_buffer, replylen);
  430. }
  431. } else if (mdns->num_qn == 0) {
  432. DEBUG_PRINTF("(no questions in packet)\n\n");
  433. }
  434. mdns_pkt_destroy(mdns);
  435. }
  436. }
  437. // send out announces
  438. while (1) {
  439. struct rr_entry *ann_e = NULL;
  440. char *namestr;
  441. // extract from head of list
  442. mutex_lock(svr->data_lock);
  443. if (svr->announce)
  444. ann_e = rr_list_remove(&svr->announce, svr->announce->e);
  445. mutex_unlock(svr->data_lock);
  446. if (! ann_e)
  447. break;
  448. namestr = nlabel_to_str(ann_e->name);
  449. DEBUG_PRINTF("sending announce for %s\n", namestr);
  450. free(namestr);
  451. announce_srv(svr, mdns_reply, ann_e->name);
  452. if (mdns_reply->num_ans_rr > 0) {
  453. size_t replylen = mdns_encode_pkt(mdns_reply, pkt_buffer, PACKET_SIZE);
  454. send_packet(svr->sockfd, pkt_buffer, replylen);
  455. }
  456. }
  457. // send out bye-bye for terminating services
  458. while (1) {
  459. struct rr_entry *leave_e = NULL;
  460. char *namestr;
  461. mutex_lock(svr->data_lock);
  462. if (svr->leave)
  463. leave_e = rr_list_remove(&svr->leave, svr->leave->e);
  464. mutex_unlock(svr->data_lock);
  465. if (!leave_e)
  466. break;
  467. mdns_init_reply(mdns_reply, 0);
  468. namestr = nlabel_to_str(leave_e->name);
  469. DEBUG_PRINTF("sending bye-bye for %s\n", namestr);
  470. free(namestr);
  471. leave_e->ttl = 0;
  472. mdns_reply->num_ans_rr += rr_list_append(&mdns_reply->rr_ans, leave_e);
  473. // send out packet
  474. if (mdns_reply->num_ans_rr > 0) {
  475. size_t replylen = mdns_encode_pkt(mdns_reply, pkt_buffer, PACKET_SIZE);
  476. send_packet(svr->sockfd, pkt_buffer, replylen);
  477. }
  478. rr_entry_destroy(leave_e->data.PTR.entry);
  479. rr_entry_destroy(leave_e);
  480. }
  481. }
  482. // main thread terminating. send out "goodbye packets" for services
  483. mdns_init_reply(mdns_reply, 0);
  484. mutex_lock(svr->data_lock);
  485. svc_le = svr->services;
  486. for (; svc_le; svc_le = svc_le->next) {
  487. // set TTL to zero
  488. svc_le->e->ttl = 0;
  489. mdns_reply->num_ans_rr += rr_list_append(&mdns_reply->rr_ans, svc_le->e);
  490. }
  491. mutex_unlock(svr->data_lock);
  492. // send out packet
  493. if (mdns_reply->num_ans_rr > 0) {
  494. size_t replylen = mdns_encode_pkt(mdns_reply, pkt_buffer, PACKET_SIZE);
  495. send_packet(svr->sockfd, pkt_buffer, replylen);
  496. }
  497. // destroy packet
  498. mdns_init_reply(mdns_reply, 0);
  499. free(mdns_reply);
  500. free(pkt_buffer);
  501. close_pipe(svr->sockfd);
  502. svr->stop_flag = 2;
  503. }
  504. /////////////////////////////////////////////////////
  505. void mdnsd_set_hostname(struct mdnsd *svr, const char *hostname, struct in_addr addr) {
  506. struct rr_entry *a_e = NULL,
  507. *nsec_e = NULL;
  508. // currently can't be called twice
  509. // dont ask me what happens if the IP changes
  510. assert(svr->hostname == NULL);
  511. a_e = rr_create_a(create_nlabel(hostname), addr);
  512. nsec_e = rr_create(create_nlabel(hostname), RR_NSEC);
  513. nsec_e->ttl = DEFAULT_TTL_FOR_RECORD_WITH_HOSTNAME;
  514. rr_set_nsec(nsec_e, RR_A);
  515. mutex_lock(svr->data_lock);
  516. svr->hostname = create_nlabel(hostname);
  517. rr_group_add(&svr->group, a_e);
  518. rr_group_add(&svr->group, nsec_e);
  519. mutex_unlock(svr->data_lock);
  520. }
  521. void mdnsd_set_hostname_v6(struct mdnsd *svr, const char *hostname, struct in6_addr *addr) {
  522. struct rr_entry *aaaa_e = NULL, *nsec_e = NULL;
  523. // currently can't be called twice
  524. // dont ask me what happens if the IP changes
  525. assert(svr->hostname == NULL);
  526. aaaa_e = rr_create_aaaa(create_nlabel(hostname), addr); // 120 seconds automatically
  527. nsec_e = rr_create(create_nlabel(hostname), RR_NSEC);
  528. nsec_e->ttl = DEFAULT_TTL_FOR_RECORD_WITH_HOSTNAME; // set to 120 seconds (default is 4500)
  529. rr_set_nsec(nsec_e, RR_AAAA);
  530. mutex_lock(svr->data_lock);
  531. svr->hostname = create_nlabel(hostname);
  532. rr_group_add(&svr->group, aaaa_e);
  533. rr_group_add(&svr->group, nsec_e);
  534. mutex_unlock(svr->data_lock);
  535. }
  536. void mdnsd_add_rr(struct mdnsd *svr, struct rr_entry *rr) {
  537. mutex_lock(svr->data_lock);
  538. rr_group_add(&svr->group, rr);
  539. mutex_unlock(svr->data_lock);
  540. }
  541. struct mdns_service *mdnsd_register_svc(struct mdnsd *svr, const char *instance_name,
  542. const char *type, uint16_t port, const char *hostname, const char *txt[]) {
  543. struct rr_entry *txt_e = NULL,
  544. *srv_e = NULL,
  545. *ptr_e = NULL,
  546. *bptr_e = NULL;
  547. uint8_t *target;
  548. uint8_t *inst_nlabel, *type_nlabel, *nlabel;
  549. struct mdns_service *service = malloc(sizeof(struct mdns_service));
  550. memset(service, 0, sizeof(struct mdns_service));
  551. // combine service name
  552. type_nlabel = create_nlabel(type);
  553. inst_nlabel = create_label(instance_name);
  554. nlabel = join_nlabel(inst_nlabel, type_nlabel);
  555. // create TXT record
  556. if (txt && *txt) {
  557. txt_e = rr_create(dup_nlabel(nlabel), RR_TXT);
  558. rr_list_append(&service->entries, txt_e);
  559. // add TXTs
  560. for (; *txt; txt++)
  561. rr_add_txt(txt_e, *txt);
  562. }
  563. // create SRV record
  564. assert(hostname || svr->hostname); // either one as target
  565. target = hostname ?
  566. create_nlabel(hostname) :
  567. dup_nlabel(svr->hostname);
  568. srv_e = rr_create_srv(dup_nlabel(nlabel), port, target);
  569. rr_list_append(&service->entries, srv_e);
  570. // create PTR record for type
  571. ptr_e = rr_create_ptr(type_nlabel, srv_e);
  572. // create services PTR record for type
  573. // this enables the type to show up as a "service"
  574. bptr_e = rr_create_ptr(dup_nlabel(SERVICES_DNS_SD_NLABEL), ptr_e);
  575. // modify lists here
  576. mutex_lock(svr->data_lock);
  577. if (txt_e)
  578. rr_group_add(&svr->group, txt_e);
  579. rr_group_add(&svr->group, srv_e);
  580. rr_group_add(&svr->group, ptr_e);
  581. rr_group_add(&svr->group, bptr_e);
  582. // append PTR entry to announce list
  583. rr_list_append(&svr->announce, ptr_e);
  584. rr_list_append(&svr->services, ptr_e);
  585. mutex_unlock(svr->data_lock);
  586. // don't free type_nlabel - it's with the PTR record
  587. free(nlabel);
  588. free(inst_nlabel);
  589. // notify server
  590. write_pipe(svr->notify_pipe[1], ".", 1);
  591. return service;
  592. }
  593. void mdns_service_remove(struct mdnsd *svr, struct mdns_service *svc) {
  594. struct rr_list *rr;
  595. assert(svr != NULL && svc != NULL);
  596. // modify lists here
  597. mutex_lock(svr->data_lock);
  598. for (rr = svc->entries; rr; rr = rr->next) {
  599. struct rr_group *g;
  600. struct rr_entry *ptr_e;
  601. // remove entry from groups and destroy entries that are not PTR
  602. if ((g = rr_group_find(svr->group, rr->e->name)) != NULL) {
  603. rr_list_remove(&g->rr, rr->e);
  604. }
  605. // remove PTR and BPTR related to this SVC
  606. if ((ptr_e = rr_entry_remove(svr->group, rr->e, RR_PTR)) != NULL) {
  607. struct rr_entry *bptr_e;
  608. // remove PTR from announce and services
  609. rr_list_remove(&svr->announce, ptr_e);
  610. rr_list_remove(&svr->services, ptr_e);
  611. // find BPTR and remove it from groups
  612. bptr_e = rr_entry_remove(svr->group, ptr_e, RR_PTR);
  613. rr_entry_destroy(bptr_e);
  614. // add PTR to list of announces for leaving
  615. rr_list_append(&svr->leave, ptr_e);
  616. } else {
  617. // destroy entries not needed for sending "leave" packet
  618. rr_entry_destroy(rr->e);
  619. }
  620. }
  621. // remove all empty groups
  622. rr_group_clean(&svr->group);
  623. // destroy this service entries
  624. rr_list_destroy(svc->entries, 0);
  625. free(svc);
  626. mutex_unlock(svr->data_lock);
  627. }
  628. void mdns_service_destroy(struct mdns_service *srv) {
  629. assert(srv != NULL);
  630. rr_list_destroy(srv->entries, 0);
  631. free(srv);
  632. }
  633. struct mdnsd *mdnsd_start(struct in_addr host, bool verbose) {
  634. #ifndef USE_WIN32_THREAD
  635. pthread_t tid;
  636. pthread_attr_t attr;
  637. #endif
  638. log_verbose = verbose;
  639. struct mdnsd *server = malloc(sizeof(struct mdnsd));
  640. memset(server, 0, sizeof(struct mdnsd));
  641. if (create_pipe(server->notify_pipe) != 0) {
  642. log_message(LOG_ERR, "pipe(): %m\n");
  643. free(server);
  644. return NULL;
  645. }
  646. server->sockfd = create_recv_sock(host.s_addr);
  647. if (server->sockfd < 0) {
  648. log_message(LOG_ERR, "unable to create recv socket\n");
  649. free(server);
  650. return NULL;
  651. }
  652. #ifdef USE_WIN32_THREAD
  653. server->data_lock = CreateMutex(NULL, FALSE, NULL);
  654. #else
  655. pthread_mutex_init(&server->data_lock, NULL);
  656. #endif
  657. #ifdef USE_WIN32_THREAD
  658. if (CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) main_loop, (void*) server, 0, NULL) == NULL) {
  659. CloseHandle(server->data_lock);
  660. #else
  661. // init thread
  662. pthread_attr_init(&attr);
  663. pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
  664. if (pthread_create(&tid, &attr, (void *(*)(void *)) main_loop, (void *) server) != 0) {
  665. pthread_mutex_destroy(&server->data_lock);
  666. #endif
  667. free(server);
  668. return NULL;
  669. }
  670. return server;
  671. }
  672. void mdnsd_stop(struct mdnsd *s) {
  673. struct timeval tv;
  674. if (!s) return;
  675. tv.tv_sec = 0;
  676. tv.tv_usec = 500*1000;
  677. assert(s != NULL);
  678. s->stop_flag = 1;
  679. write_pipe(s->notify_pipe[1], ".", 1);
  680. while (s->stop_flag != 2)
  681. select(0, NULL, NULL, NULL, &tv);
  682. close_pipe(s->notify_pipe[0]);
  683. close_pipe(s->notify_pipe[1]);
  684. #ifdef USE_WIN32_THREAD
  685. CloseHandle(s->data_lock);
  686. #else
  687. pthread_mutex_destroy(&s->data_lock);
  688. #endif
  689. rr_group_destroy(s->group);
  690. rr_list_destroy(s->announce, 0);
  691. rr_list_destroy(s->services, 0);
  692. rr_list_destroy(s->leave, 0);
  693. if (s->hostname)
  694. free(s->hostname);
  695. free(s);
  696. }