]> git.ipfire.org Git - thirdparty/shairport-sync.git/blob - tinysvcmdns.h
Update check_classic_mac_basic.yml
[thirdparty/shairport-sync.git] / tinysvcmdns.h
1 // This file is the concatenation of mdnsd.h and mdns.h
2 // from tinysvcmdns with minor modifications
3 // The code was taken from https://bitbucket.org/geekman/tinysvcmdns at revision e34b562
4
5 /*
6 * tinysvcmdns - a tiny MDNS implementation for publishing services
7 * Copyright (C) 2011 Darell Tan
8 * All rights reserved.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 * 3. The name of the author may not be used to endorse or promote products
19 * derived from this software without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
22 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
23 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
24 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
25 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
26 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
30 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 */
32
33 #ifndef _TINYSVCMDNS_H
34
35 //******************************************************//
36 // mdns.h //
37 //******************************************************//
38 #include <stdint.h>
39 #include <stdlib.h>
40 #include <string.h>
41
42 #ifdef _WIN32
43 #include <winsock.h>
44 #else
45 #include <arpa/inet.h>
46 #endif
47
48 #define MALLOC_ZERO_STRUCT(x, type) \
49 x = malloc(sizeof(struct type)); \
50 if (x) \
51 memset(x, 0, sizeof(struct type));
52
53 #define DECL_MALLOC_ZERO_STRUCT(x, type) struct type *MALLOC_ZERO_STRUCT(x, type)
54
55 struct rr_data_srv {
56 uint16_t priority;
57 uint16_t weight;
58 uint16_t port;
59 uint8_t *target; // host
60 };
61
62 struct rr_data_txt {
63 struct rr_data_txt *next;
64 uint8_t *txt;
65 };
66
67 struct rr_data_nsec {
68 // uint8_t *name; // same as record
69
70 // NSEC occupies the 47th bit, 5 bytes
71 // uint8_t bitmap_len; // = 5
72 uint8_t bitmap[5]; // network order: first byte contains LSB
73 };
74
75 struct rr_data_ptr {
76 uint8_t *name; // NULL if entry is to be used
77 struct rr_entry *entry;
78 };
79
80 struct rr_data_a {
81 uint32_t addr;
82 };
83
84 struct rr_data_aaaa {
85 struct in6_addr *addr;
86 };
87
88 struct rr_entry {
89 uint8_t *name;
90
91 enum rr_type {
92 RR_A = 0x01,
93 RR_PTR = 0x0C,
94 RR_TXT = 0x10,
95 RR_AAAA = 0x1C,
96 RR_SRV = 0x21,
97 RR_NSEC = 0x2F,
98 RR_ANY = 0xFF,
99 } type;
100
101 uint32_t ttl;
102
103 // for use in Questions only
104 char unicast_query;
105
106 // for use in Answers only
107 char cache_flush;
108
109 uint16_t rr_class;
110
111 // RR data
112 union {
113 struct rr_data_nsec NSEC;
114 struct rr_data_srv SRV;
115 struct rr_data_txt TXT;
116 struct rr_data_ptr PTR;
117 struct rr_data_a A;
118 struct rr_data_aaaa AAAA;
119 } data;
120 };
121
122 struct rr_list {
123 struct rr_entry *e;
124 struct rr_list *next;
125 };
126
127 struct rr_group {
128 uint8_t *name;
129
130 struct rr_list *rr;
131
132 struct rr_group *next;
133 };
134
135 #define MDNS_FLAG_RESP (1 << 15) // Query=0 / Response=1
136 #define MDNS_FLAG_AA (1 << 10) // Authoritative
137 #define MDNS_FLAG_TC (1 << 9) // TrunCation
138 #define MDNS_FLAG_RD (1 << 8) // Recursion Desired
139 #define MDNS_FLAG_RA (1 << 7) // Recursion Available
140 #define MDNS_FLAG_Z (1 << 6) // Reserved (zero)
141
142 #define MDNS_FLAG_GET_RCODE(x) (x & 0x0F)
143 #define MDNS_FLAG_GET_OPCODE(x) ((x >> 11) & 0x0F)
144
145 // gets the PTR target name, either from "name" member or "entry" member
146 #define MDNS_RR_GET_PTR_NAME(rr) \
147 (rr->data.PTR.name != NULL ? rr->data.PTR.name : rr->data.PTR.entry->name)
148
149 struct mdns_pkt {
150 uint16_t id; // transaction ID
151 uint16_t flags;
152 uint16_t num_qn;
153 uint16_t num_ans_rr;
154 uint16_t num_auth_rr;
155 uint16_t num_add_rr;
156
157 struct rr_list *rr_qn; // questions
158 struct rr_list *rr_ans; // answer RRs
159 struct rr_list *rr_auth; // authority RRs
160 struct rr_list *rr_add; // additional RRs
161 };
162
163 struct mdns_pkt *mdns_parse_pkt(uint8_t *pkt_buf, size_t pkt_len);
164
165 void mdns_init_reply(struct mdns_pkt *pkt, uint16_t id);
166 size_t mdns_encode_pkt(struct mdns_pkt *answer, uint8_t *pkt_buf, size_t pkt_len);
167
168 void mdns_pkt_destroy(struct mdns_pkt *p);
169 void rr_group_destroy(struct rr_group *group);
170 struct rr_group *rr_group_find(struct rr_group *g, uint8_t *name);
171 struct rr_entry *rr_entry_find(struct rr_list *rr_list, uint8_t *name, uint16_t type);
172 struct rr_entry *rr_entry_match(struct rr_list *rr_list, struct rr_entry *entry);
173 void rr_group_add(struct rr_group **group, struct rr_entry *rr);
174
175 int rr_list_count(struct rr_list *rr);
176 int rr_list_append(struct rr_list **rr_head, struct rr_entry *rr);
177 struct rr_entry *rr_list_remove(struct rr_list **rr_head, struct rr_entry *rr);
178 void rr_list_destroy(struct rr_list *rr, char destroy_items);
179
180 struct rr_entry *rr_create_ptr(uint8_t *name, struct rr_entry *d_rr);
181 struct rr_entry *rr_create_srv(uint8_t *name, uint16_t port, uint8_t *target);
182 struct rr_entry *rr_create_aaaa(uint8_t *name, struct in6_addr *addr);
183 struct rr_entry *rr_create_a(uint8_t *name, uint32_t addr);
184 struct rr_entry *rr_create(uint8_t *name, enum rr_type type);
185 void rr_set_nsec(struct rr_entry *rr_nsec, enum rr_type type);
186 void rr_add_txt(struct rr_entry *rr_txt, const char *txt);
187
188 const char *rr_get_type_name(enum rr_type type);
189
190 uint8_t *create_label(const char *txt);
191 uint8_t *create_nlabel(const char *name);
192 char *nlabel_to_str(const uint8_t *name);
193 uint8_t *dup_label(const uint8_t *label);
194 uint8_t *dup_nlabel(const uint8_t *n);
195 uint8_t *join_nlabel(const uint8_t *n1, const uint8_t *n2);
196
197 // compares 2 names
198 static inline int cmp_nlabel(const uint8_t *L1, const uint8_t *L2) {
199 return strcmp((char *)L1, (char *)L2);
200 }
201
202 //******************************************************//
203 // mdnsd.h //
204 //******************************************************//
205
206 struct mdnsd;
207 struct mdns_service;
208
209 // starts a MDNS responder instance
210 // returns NULL if unsuccessful
211 struct mdnsd *mdnsd_start();
212
213 // stops the given MDNS responder instance
214 void mdnsd_stop(struct mdnsd *s);
215
216 // sets the hostname for the given MDNS responder instance
217 void mdnsd_set_hostname(struct mdnsd *svr, const char *hostname, uint32_t ip);
218
219 // sets the hostname for the given MDNS responder instance, with an ipv6 address
220 void mdnsd_set_hostname_v6(struct mdnsd *svr, const char *hostname, struct in6_addr *addr);
221
222 // adds an additional RR
223 void mdnsd_add_rr(struct mdnsd *svr, struct rr_entry *rr);
224
225 // registers a service with the MDNS responder instance
226 struct mdns_service *mdnsd_register_svc(struct mdnsd *svr, const char *instance_name,
227 const char *type, uint16_t port, const char *hostname,
228 const char *txt[]);
229
230 // destroys the mdns_service struct returned by mdnsd_register_svc()
231 void mdns_service_destroy(struct mdns_service *srv);
232
233 #endif // _TINYSVCMDNS_H