]> git.ipfire.org Git - thirdparty/shairport-sync.git/blame - mdns_tinysvcmdns.c
Update check_classic_mac_basic.yml
[thirdparty/shairport-sync.git] / mdns_tinysvcmdns.c
CommitLineData
592119bc
PL
1/*
2 * mDNS registration handler. This file is part of Shairport.
3 * Copyright (c) Paul Lietar 2013
4 * All rights reserved.
5 *
6 * Permission is hereby granted, free of charge, to any person
7 * obtaining a copy of this software and associated documentation
8 * files (the "Software"), to deal in the Software without
9 * restriction, including without limitation the rights to use,
10 * copy, modify, merge, publish, distribute, sublicense, and/or
11 * sell copies of the Software, and to permit persons to whom the
12 * Software is furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be
15 * included in all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
19 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
20 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
21 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
22 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
23 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
24 * OTHER DEALINGS IN THE SOFTWARE.
25 */
26
064bd293
MB
27#include "mdns.h"
28#include "common.h"
29#include <ifaddrs.h>
30#include <net/if.h>
31#include <netinet/in.h>
592119bc 32#include <string.h>
592119bc 33#include <sys/socket.h>
064bd293 34#include <sys/types.h>
592119bc 35#include <unistd.h>
592119bc
PL
36
37#include "tinysvcmdns.h"
38
39static struct mdnsd *svr = NULL;
40
6c1625e6 41static int mdns_tinysvcmdns_register(char *ap1name, __attribute__((unused)) char *ap2name, int port,
fd880056
MB
42 __attribute__((unused)) char **txt_records,
43 __attribute__((unused)) char **secondary_txt_records) {
87a0475c
MB
44 struct ifaddrs *ifalist;
45 struct ifaddrs *ifa;
46
47 svr = mdnsd_start();
48 if (svr == NULL) {
49 warn("tinysvcmdns: mdnsd_start() failed");
50 return -1;
51 }
52
53 // Thanks to Paul Lietar for this
54 // room for name + .local + NULL
55 char hostname[100 + 6];
56 gethostname(hostname, 99);
57 // according to POSIX, this may be truncated without a final NULL !
58 hostname[99] = 0;
59
60 // will not work if the hostname doesn't end in .local
61 char *hostend = hostname + strlen(hostname);
62 if ((strlen(hostname) < strlen(".local")) || (strcmp(hostend - 6, ".local") != 0)) {
63 strcat(hostname, ".local");
64 }
65
66 if (getifaddrs(&ifalist) < 0) {
67 warn("tinysvcmdns: getifaddrs() failed");
68 return -1;
69 }
70
71 ifa = ifalist;
72
73 // Look for an ipv4/ipv6 non-loopback interface to use as the main one.
74 for (ifa = ifalist; ifa != NULL; ifa = ifa->ifa_next) {
2cab35cd 75 // only check for the named interface, if specified
cf29625d
MB
76 if ((config.interface == NULL) || (strcmp(config.interface, ifa->ifa_name) == 0)) {
77
78 if (!(ifa->ifa_flags & IFF_LOOPBACK) && ifa->ifa_addr &&
79 ifa->ifa_addr->sa_family == AF_INET) {
2cab35cd
MB
80 uint32_t main_ip = ((struct sockaddr_in *)ifa->ifa_addr)->sin_addr.s_addr;
81
82 mdnsd_set_hostname(svr, hostname, main_ip); // TTL should be 120 seconds
83 break;
84 } else if (!(ifa->ifa_flags & IFF_LOOPBACK) && ifa->ifa_addr &&
85 ifa->ifa_addr->sa_family == AF_INET6) {
86 struct in6_addr *addr = &((struct sockaddr_in6 *)ifa->ifa_addr)->sin6_addr;
87
88 mdnsd_set_hostname_v6(svr, hostname, addr); // TTL should be 120 seconds
89 break;
90 }
592119bc 91 }
87a0475c
MB
92 }
93
94 if (ifa == NULL) {
95 warn("tinysvcmdns: no non-loopback ipv4 or ipv6 interface found");
96 return -1;
97 }
98
99 // Skip the first one, it was already added by set_hostname
100 for (ifa = ifa->ifa_next; ifa != NULL; ifa = ifa->ifa_next) {
101 if (ifa->ifa_flags & IFF_LOOPBACK) // Skip loop-back interfaces
cf29625d 102 continue;
2cab35cd 103 // only check for the named interface, if specified
cf29625d 104 if ((config.interface == NULL) || (strcmp(config.interface, ifa->ifa_name) == 0)) {
2cab35cd 105 switch (ifa->ifa_addr->sa_family) {
cf29625d
MB
106 case AF_INET: { // ipv4
107 uint32_t ip = ((struct sockaddr_in *)ifa->ifa_addr)->sin_addr.s_addr;
108 struct rr_entry *a_e =
109 rr_create_a(create_nlabel(hostname), ip); // TTL should be 120 seconds
110 mdnsd_add_rr(svr, a_e);
111 } break;
112 case AF_INET6: { // ipv6
113 struct in6_addr *addr = &((struct sockaddr_in6 *)ifa->ifa_addr)->sin6_addr;
114 struct rr_entry *aaaa_e =
115 rr_create_aaaa(create_nlabel(hostname), addr); // TTL should be 120 seconds
116 mdnsd_add_rr(svr, aaaa_e);
117 } break;
2cab35cd 118 }
592119bc 119 }
87a0475c 120 }
592119bc 121
87a0475c 122 freeifaddrs(ifa);
592119bc 123
87a0475c
MB
124 char *txtwithoutmetadata[] = {MDNS_RECORD_WITHOUT_METADATA, NULL};
125#ifdef CONFIG_METADATA
126 char *txtwithmetadata[] = {MDNS_RECORD_WITH_METADATA, NULL};
127#endif
128 char **txt;
592119bc 129
75f3f912 130#ifdef CONFIG_METADATA
6ae067af 131 if (config.metadata_enabled)
87a0475c
MB
132 txt = txtwithmetadata;
133 else
75f3f912
MB
134#endif
135
87a0475c 136 txt = txtwithoutmetadata;
064bd293 137
52376ff4 138 if (config.regtype == NULL)
139 die("tinysvcmdns: regtype is null");
140
064bd293 141 char *extendedregtype = malloc(strlen(config.regtype) + strlen(".local") + 1);
46412eb1 142
064bd293 143 if (extendedregtype == NULL)
bfadbf38 144 die("tinysvcmdns: could not allocated memory to request a Zeroconf service");
592119bc 145
064bd293
MB
146 strcpy(extendedregtype, config.regtype);
147 strcat(extendedregtype, ".local");
148
149 struct mdns_service *svc =
6c1625e6 150 mdnsd_register_svc(svr, ap1name, extendedregtype, port, NULL,
bfadbf38 151 (const char **)txt); // TTL should be 75 minutes, i.e. 4500 seconds
87a0475c 152 mdns_service_destroy(svc);
064bd293 153
bfadbf38 154 free(extendedregtype);
592119bc 155
87a0475c 156 return 0;
592119bc
PL
157}
158
159static void mdns_tinysvcmdns_unregister(void) {
87a0475c
MB
160 if (svr) {
161 mdnsd_stop(svr);
162 svr = NULL;
163 }
592119bc
PL
164}
165
87a0475c
MB
166mdns_backend mdns_tinysvcmdns = {.name = "tinysvcmdns",
167 .mdns_register = mdns_tinysvcmdns_register,
139c18bf 168 .mdns_unregister = mdns_tinysvcmdns_unregister,
72079ada
MB
169 .mdns_dacp_monitor_start = NULL,
170 .mdns_dacp_monitor_set_id = NULL,
171 .mdns_dacp_monitor_stop = NULL};