]>
Commit | Line | Data |
---|---|---|
592119bc PL |
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. | |
82518dc3 | 9 | * |
592119bc PL |
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 | ||
87a0475c MB |
48 | #define MALLOC_ZERO_STRUCT(x, type) \ |
49 | x = malloc(sizeof(struct type)); \ | |
3001f39b MB |
50 | if (x) \ |
51 | memset(x, 0, sizeof(struct type)); | |
592119bc | 52 | |
87a0475c | 53 | #define DECL_MALLOC_ZERO_STRUCT(x, type) struct type *MALLOC_ZERO_STRUCT(x, type) |
592119bc PL |
54 | |
55 | struct rr_data_srv { | |
87a0475c MB |
56 | uint16_t priority; |
57 | uint16_t weight; | |
58 | uint16_t port; | |
59 | uint8_t *target; // host | |
592119bc PL |
60 | }; |
61 | ||
62 | struct rr_data_txt { | |
87a0475c MB |
63 | struct rr_data_txt *next; |
64 | uint8_t *txt; | |
592119bc PL |
65 | }; |
66 | ||
67 | struct rr_data_nsec { | |
87a0475c | 68 | // uint8_t *name; // same as record |
592119bc | 69 | |
87a0475c MB |
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 | |
592119bc PL |
73 | }; |
74 | ||
75 | struct rr_data_ptr { | |
87a0475c MB |
76 | uint8_t *name; // NULL if entry is to be used |
77 | struct rr_entry *entry; | |
592119bc PL |
78 | }; |
79 | ||
80 | struct rr_data_a { | |
87a0475c | 81 | uint32_t addr; |
592119bc PL |
82 | }; |
83 | ||
84 | struct rr_data_aaaa { | |
87a0475c | 85 | struct in6_addr *addr; |
592119bc PL |
86 | }; |
87 | ||
88 | struct rr_entry { | |
87a0475c MB |
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; | |
592119bc PL |
120 | }; |
121 | ||
122 | struct rr_list { | |
87a0475c MB |
123 | struct rr_entry *e; |
124 | struct rr_list *next; | |
592119bc PL |
125 | }; |
126 | ||
127 | struct rr_group { | |
87a0475c | 128 | uint8_t *name; |
592119bc | 129 | |
87a0475c | 130 | struct rr_list *rr; |
592119bc | 131 | |
87a0475c | 132 | struct rr_group *next; |
592119bc PL |
133 | }; |
134 | ||
87a0475c MB |
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) | |
592119bc | 141 | |
87a0475c | 142 | #define MDNS_FLAG_GET_RCODE(x) (x & 0x0F) |
592119bc PL |
143 | #define MDNS_FLAG_GET_OPCODE(x) ((x >> 11) & 0x0F) |
144 | ||
145 | // gets the PTR target name, either from "name" member or "entry" member | |
87a0475c MB |
146 | #define MDNS_RR_GET_PTR_NAME(rr) \ |
147 | (rr->data.PTR.name != NULL ? rr->data.PTR.name : rr->data.PTR.entry->name) | |
592119bc PL |
148 | |
149 | struct mdns_pkt { | |
87a0475c MB |
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 | |
592119bc PL |
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) { | |
87a0475c | 199 | return strcmp((char *)L1, (char *)L2); |
592119bc PL |
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 | |
82518dc3 | 226 | struct mdns_service *mdnsd_register_svc(struct mdnsd *svr, const char *instance_name, |
87a0475c MB |
227 | const char *type, uint16_t port, const char *hostname, |
228 | const char *txt[]); | |
592119bc PL |
229 | |
230 | // destroys the mdns_service struct returned by mdnsd_register_svc() | |
231 | void mdns_service_destroy(struct mdns_service *srv); | |
232 | ||
592119bc | 233 | #endif // _TINYSVCMDNS_H |