xref: /aosp_15_r20/external/mdnsresponder/mDNSPosix/nss_mdns.c (revision 48a54d368dc4fa860885eef7b70b6c53499e7c25)
1*48a54d36SAndroid Build Coastguard Worker /*
2*48a54d36SAndroid Build Coastguard Worker NICTA Public Software Licence
3*48a54d36SAndroid Build Coastguard Worker Version 1.0
4*48a54d36SAndroid Build Coastguard Worker 
5*48a54d36SAndroid Build Coastguard Worker Copyright © 2004 National ICT Australia Ltd
6*48a54d36SAndroid Build Coastguard Worker 
7*48a54d36SAndroid Build Coastguard Worker All rights reserved.
8*48a54d36SAndroid Build Coastguard Worker 
9*48a54d36SAndroid Build Coastguard Worker By this licence, National ICT Australia Ltd (NICTA) grants permission,
10*48a54d36SAndroid Build Coastguard Worker free of charge, to any person who obtains a copy of this software
11*48a54d36SAndroid Build Coastguard Worker and any associated documentation files ("the Software") to use and
12*48a54d36SAndroid Build Coastguard Worker deal with the Software in source code and binary forms without
13*48a54d36SAndroid Build Coastguard Worker restriction, with or without modification, and to permit persons
14*48a54d36SAndroid Build Coastguard Worker to whom the Software is furnished to do so, provided that the
15*48a54d36SAndroid Build Coastguard Worker following conditions are met:
16*48a54d36SAndroid Build Coastguard Worker 
17*48a54d36SAndroid Build Coastguard Worker - Redistributions of source code must retain the above copyright
18*48a54d36SAndroid Build Coastguard Worker   notice, this list of conditions and the following disclaimers.
19*48a54d36SAndroid Build Coastguard Worker - Redistributions in binary form must reproduce the above copyright
20*48a54d36SAndroid Build Coastguard Worker   notice, this list of conditions and the following disclaimers in
21*48a54d36SAndroid Build Coastguard Worker   the documentation and/or other materials provided with the
22*48a54d36SAndroid Build Coastguard Worker   distribution.
23*48a54d36SAndroid Build Coastguard Worker - The name of NICTA may not be used to endorse or promote products
24*48a54d36SAndroid Build Coastguard Worker   derived from this Software without specific prior written permission.
25*48a54d36SAndroid Build Coastguard Worker 
26*48a54d36SAndroid Build Coastguard Worker EXCEPT AS EXPRESSLY STATED IN THIS LICENCE AND TO THE FULL EXTENT
27*48a54d36SAndroid Build Coastguard Worker PERMITTED BY APPLICABLE LAW, THE SOFTWARE IS PROVIDED "AS-IS" AND
28*48a54d36SAndroid Build Coastguard Worker NICTA MAKES NO REPRESENTATIONS, WARRANTIES OR CONDITIONS OF ANY
29*48a54d36SAndroid Build Coastguard Worker KIND, EXPRESS OR IMPLIED, INCLUDING, WITHOUT LIMITATION, ANY
30*48a54d36SAndroid Build Coastguard Worker REPRESENTATIONS, WARRANTIES OR CONDITIONS REGARDING THE CONTENTS
31*48a54d36SAndroid Build Coastguard Worker OR ACCURACY OF THE SOFTWARE, OR OF TITLE, MERCHANTABILITY, FITNESS
32*48a54d36SAndroid Build Coastguard Worker FOR A PARTICULAR PURPOSE, NONINFRINGEMENT, THE ABSENCE OF LATENT
33*48a54d36SAndroid Build Coastguard Worker OR OTHER DEFECTS, OR THE PRESENCE OR ABSENCE OF ERRORS, WHETHER OR
34*48a54d36SAndroid Build Coastguard Worker NOT DISCOVERABLE.
35*48a54d36SAndroid Build Coastguard Worker 
36*48a54d36SAndroid Build Coastguard Worker TO THE FULL EXTENT PERMITTED BY APPLICABLE LAW, IN NO EVENT WILL
37*48a54d36SAndroid Build Coastguard Worker NICTA BE LIABLE ON ANY LEGAL THEORY (INCLUDING, WITHOUT LIMITATION,
38*48a54d36SAndroid Build Coastguard Worker NEGLIGENCE) FOR ANY LOSS OR DAMAGE WHATSOEVER, INCLUDING (WITHOUT
39*48a54d36SAndroid Build Coastguard Worker LIMITATION) LOSS OF PRODUCTION OR OPERATION TIME, LOSS, DAMAGE OR
40*48a54d36SAndroid Build Coastguard Worker CORRUPTION OF DATA OR RECORDS; OR LOSS OF ANTICIPATED SAVINGS,
41*48a54d36SAndroid Build Coastguard Worker OPPORTUNITY, REVENUE, PROFIT OR GOODWILL, OR OTHER ECONOMIC LOSS;
42*48a54d36SAndroid Build Coastguard Worker OR ANY SPECIAL, INCIDENTAL, INDIRECT, CONSEQUENTIAL, PUNITIVE OR
43*48a54d36SAndroid Build Coastguard Worker EXEMPLARY DAMAGES ARISING OUT OF OR IN CONNECTION WITH THIS LICENCE,
44*48a54d36SAndroid Build Coastguard Worker THE SOFTWARE OR THE USE OF THE SOFTWARE, EVEN IF NICTA HAS BEEN
45*48a54d36SAndroid Build Coastguard Worker ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
46*48a54d36SAndroid Build Coastguard Worker 
47*48a54d36SAndroid Build Coastguard Worker If applicable legislation implies warranties or conditions, or
48*48a54d36SAndroid Build Coastguard Worker imposes obligations or liability on NICTA in respect of the Software
49*48a54d36SAndroid Build Coastguard Worker that cannot be wholly or partly excluded, restricted or modified,
50*48a54d36SAndroid Build Coastguard Worker NICTA's liability is limited, to the full extent permitted by the
51*48a54d36SAndroid Build Coastguard Worker applicable legislation, at its option, to:
52*48a54d36SAndroid Build Coastguard Worker 
53*48a54d36SAndroid Build Coastguard Worker a. in the case of goods, any one or more of the following:
54*48a54d36SAndroid Build Coastguard Worker   i.   the replacement of the goods or the supply of equivalent goods;
55*48a54d36SAndroid Build Coastguard Worker   ii.  the repair of the goods;
56*48a54d36SAndroid Build Coastguard Worker   iii. the payment of the cost of replacing the goods or of acquiring
57*48a54d36SAndroid Build Coastguard Worker        equivalent goods;
58*48a54d36SAndroid Build Coastguard Worker   iv.  the payment of the cost of having the goods repaired; or
59*48a54d36SAndroid Build Coastguard Worker b. in the case of services:
60*48a54d36SAndroid Build Coastguard Worker   i.   the supplying of the services again; or
61*48a54d36SAndroid Build Coastguard Worker   ii.  the payment of the cost of having the services supplied
62*48a54d36SAndroid Build Coastguard Worker        again.
63*48a54d36SAndroid Build Coastguard Worker  */
64*48a54d36SAndroid Build Coastguard Worker 
65*48a54d36SAndroid Build Coastguard Worker /*
66*48a54d36SAndroid Build Coastguard Worker 	NSSwitch Implementation of mDNS interface.
67*48a54d36SAndroid Build Coastguard Worker 
68*48a54d36SAndroid Build Coastguard Worker 	Andrew White ([email protected])
69*48a54d36SAndroid Build Coastguard Worker 	May 2004
70*48a54d36SAndroid Build Coastguard Worker  */
71*48a54d36SAndroid Build Coastguard Worker 
72*48a54d36SAndroid Build Coastguard Worker #include <stdlib.h>
73*48a54d36SAndroid Build Coastguard Worker #include <stdio.h>
74*48a54d36SAndroid Build Coastguard Worker #include <string.h>
75*48a54d36SAndroid Build Coastguard Worker #include <errno.h>
76*48a54d36SAndroid Build Coastguard Worker #include <syslog.h>
77*48a54d36SAndroid Build Coastguard Worker #include <pthread.h>
78*48a54d36SAndroid Build Coastguard Worker #include <ctype.h>
79*48a54d36SAndroid Build Coastguard Worker 
80*48a54d36SAndroid Build Coastguard Worker #include <sys/types.h>
81*48a54d36SAndroid Build Coastguard Worker #include <sys/time.h>
82*48a54d36SAndroid Build Coastguard Worker #include <sys/socket.h>
83*48a54d36SAndroid Build Coastguard Worker 
84*48a54d36SAndroid Build Coastguard Worker #include <netinet/in.h>
85*48a54d36SAndroid Build Coastguard Worker 
86*48a54d36SAndroid Build Coastguard Worker #include <arpa/inet.h>
87*48a54d36SAndroid Build Coastguard Worker #define BIND_8_COMPAT 1
88*48a54d36SAndroid Build Coastguard Worker #include <arpa/nameser.h>
89*48a54d36SAndroid Build Coastguard Worker 
90*48a54d36SAndroid Build Coastguard Worker #include <dns_sd.h>
91*48a54d36SAndroid Build Coastguard Worker 
92*48a54d36SAndroid Build Coastguard Worker 
93*48a54d36SAndroid Build Coastguard Worker //----------
94*48a54d36SAndroid Build Coastguard Worker // Public functions
95*48a54d36SAndroid Build Coastguard Worker 
96*48a54d36SAndroid Build Coastguard Worker /*
97*48a54d36SAndroid Build Coastguard Worker 	Count the number of dots in a name string.
98*48a54d36SAndroid Build Coastguard Worker  */
99*48a54d36SAndroid Build Coastguard Worker int
100*48a54d36SAndroid Build Coastguard Worker count_dots (const char * name);
101*48a54d36SAndroid Build Coastguard Worker 
102*48a54d36SAndroid Build Coastguard Worker 
103*48a54d36SAndroid Build Coastguard Worker /*
104*48a54d36SAndroid Build Coastguard Worker 	Test whether a domain name is local.
105*48a54d36SAndroid Build Coastguard Worker 
106*48a54d36SAndroid Build Coastguard Worker 	Returns
107*48a54d36SAndroid Build Coastguard Worker 		1 if name ends with ".local" or ".local."
108*48a54d36SAndroid Build Coastguard Worker 		0 otherwise
109*48a54d36SAndroid Build Coastguard Worker  */
110*48a54d36SAndroid Build Coastguard Worker int
111*48a54d36SAndroid Build Coastguard Worker islocal (const char * name);
112*48a54d36SAndroid Build Coastguard Worker 
113*48a54d36SAndroid Build Coastguard Worker 
114*48a54d36SAndroid Build Coastguard Worker /*
115*48a54d36SAndroid Build Coastguard Worker 	Format an address structure as a string appropriate for DNS reverse (PTR)
116*48a54d36SAndroid Build Coastguard Worker 	lookup, based on address type.
117*48a54d36SAndroid Build Coastguard Worker 
118*48a54d36SAndroid Build Coastguard Worker 	Parameters
119*48a54d36SAndroid Build Coastguard Worker 		prefixlen
120*48a54d36SAndroid Build Coastguard Worker 			Prefix length, in bits.  When formatting, this will be rounded up
121*48a54d36SAndroid Build Coastguard Worker 			to the nearest appropriate size.  If -1, assume maximum.
122*48a54d36SAndroid Build Coastguard Worker 		buf
123*48a54d36SAndroid Build Coastguard Worker 			Output buffer.  Must be long enough to hold largest possible
124*48a54d36SAndroid Build Coastguard Worker 			output.
125*48a54d36SAndroid Build Coastguard Worker 	Returns
126*48a54d36SAndroid Build Coastguard Worker 		Pointer to (first character of) output buffer,
127*48a54d36SAndroid Build Coastguard Worker 		or NULL on error.
128*48a54d36SAndroid Build Coastguard Worker  */
129*48a54d36SAndroid Build Coastguard Worker char *
130*48a54d36SAndroid Build Coastguard Worker format_reverse_addr (int af, const void * addr, int prefixlen, char * buf);
131*48a54d36SAndroid Build Coastguard Worker 
132*48a54d36SAndroid Build Coastguard Worker 
133*48a54d36SAndroid Build Coastguard Worker /*
134*48a54d36SAndroid Build Coastguard Worker 	Format an address structure as a string appropriate for DNS reverse (PTR)
135*48a54d36SAndroid Build Coastguard Worker 	lookup for AF_INET.  Output is in .in-addr.arpa domain.
136*48a54d36SAndroid Build Coastguard Worker 
137*48a54d36SAndroid Build Coastguard Worker 	Parameters
138*48a54d36SAndroid Build Coastguard Worker 		prefixlen
139*48a54d36SAndroid Build Coastguard Worker 			Prefix length, in bits.  When formatting, this will be rounded up
140*48a54d36SAndroid Build Coastguard Worker 			to the nearest byte (8).  If -1, assume 32.
141*48a54d36SAndroid Build Coastguard Worker 		buf
142*48a54d36SAndroid Build Coastguard Worker 			Output buffer.  Must be long enough to hold largest possible
143*48a54d36SAndroid Build Coastguard Worker 			output.  For AF_INET, this is 29 characters (including null).
144*48a54d36SAndroid Build Coastguard Worker 	Returns
145*48a54d36SAndroid Build Coastguard Worker 		Pointer to (first character of) output buffer,
146*48a54d36SAndroid Build Coastguard Worker 		or NULL on error.
147*48a54d36SAndroid Build Coastguard Worker  */
148*48a54d36SAndroid Build Coastguard Worker char *
149*48a54d36SAndroid Build Coastguard Worker format_reverse_addr_in (
150*48a54d36SAndroid Build Coastguard Worker 	const struct in_addr * addr,
151*48a54d36SAndroid Build Coastguard Worker 	int prefixlen,
152*48a54d36SAndroid Build Coastguard Worker 	char * buf
153*48a54d36SAndroid Build Coastguard Worker );
154*48a54d36SAndroid Build Coastguard Worker #define DNS_PTR_AF_INET_SIZE 29
155*48a54d36SAndroid Build Coastguard Worker 
156*48a54d36SAndroid Build Coastguard Worker /*
157*48a54d36SAndroid Build Coastguard Worker 	Format an address structure as a string appropriate for DNS reverse (PTR)
158*48a54d36SAndroid Build Coastguard Worker 	lookup for AF_INET6.  Output is in .ip6.arpa domain.
159*48a54d36SAndroid Build Coastguard Worker 
160*48a54d36SAndroid Build Coastguard Worker 	Parameters
161*48a54d36SAndroid Build Coastguard Worker 		prefixlen
162*48a54d36SAndroid Build Coastguard Worker 			Prefix length, in bits.  When formatting, this will be rounded up
163*48a54d36SAndroid Build Coastguard Worker 			to the nearest nibble (4).  If -1, assume 128.
164*48a54d36SAndroid Build Coastguard Worker 		buf
165*48a54d36SAndroid Build Coastguard Worker 			Output buffer.  Must be long enough to hold largest possible
166*48a54d36SAndroid Build Coastguard Worker 			output.  For AF_INET6, this is 72 characters (including null).
167*48a54d36SAndroid Build Coastguard Worker 	Returns
168*48a54d36SAndroid Build Coastguard Worker 		Pointer to (first character of) output buffer,
169*48a54d36SAndroid Build Coastguard Worker 		or NULL on error.
170*48a54d36SAndroid Build Coastguard Worker  */
171*48a54d36SAndroid Build Coastguard Worker char *
172*48a54d36SAndroid Build Coastguard Worker format_reverse_addr_in6 (
173*48a54d36SAndroid Build Coastguard Worker 	const struct in6_addr * addr,
174*48a54d36SAndroid Build Coastguard Worker 	int prefixlen,
175*48a54d36SAndroid Build Coastguard Worker 	char * buf
176*48a54d36SAndroid Build Coastguard Worker );
177*48a54d36SAndroid Build Coastguard Worker #define DNS_PTR_AF_INET6_SIZE 72
178*48a54d36SAndroid Build Coastguard Worker 
179*48a54d36SAndroid Build Coastguard Worker 
180*48a54d36SAndroid Build Coastguard Worker /*
181*48a54d36SAndroid Build Coastguard Worker 	Compare whether the given dns name has the given domain suffix.
182*48a54d36SAndroid Build Coastguard Worker 	A single leading '.' on the name or leading or trailing '.' on the
183*48a54d36SAndroid Build Coastguard Worker 	domain is ignored for the purposes of the comparison.
184*48a54d36SAndroid Build Coastguard Worker 	Multiple leading or trailing '.'s are an error.  Other DNS syntax
185*48a54d36SAndroid Build Coastguard Worker 	errors are not checked for.  The comparison is case insensitive.
186*48a54d36SAndroid Build Coastguard Worker 
187*48a54d36SAndroid Build Coastguard Worker 	Returns
188*48a54d36SAndroid Build Coastguard Worker 		1 on success (match)
189*48a54d36SAndroid Build Coastguard Worker 		0 on failure (no match)
190*48a54d36SAndroid Build Coastguard Worker 		< 0 on error
191*48a54d36SAndroid Build Coastguard Worker  */
192*48a54d36SAndroid Build Coastguard Worker int
193*48a54d36SAndroid Build Coastguard Worker cmp_dns_suffix (const char * name, const char * domain);
194*48a54d36SAndroid Build Coastguard Worker enum
195*48a54d36SAndroid Build Coastguard Worker {
196*48a54d36SAndroid Build Coastguard Worker 	CMP_DNS_SUFFIX_SUCCESS = 1,
197*48a54d36SAndroid Build Coastguard Worker 	CMP_DNS_SUFFIX_FAILURE = 0,
198*48a54d36SAndroid Build Coastguard Worker 	CMP_DNS_SUFFIX_BAD_NAME = 1,
199*48a54d36SAndroid Build Coastguard Worker 	CMP_DNS_SUFFIX_BAD_DOMAIN = -2
200*48a54d36SAndroid Build Coastguard Worker };
201*48a54d36SAndroid Build Coastguard Worker 
202*48a54d36SAndroid Build Coastguard Worker typedef int ns_type_t;
203*48a54d36SAndroid Build Coastguard Worker typedef int ns_class_t;
204*48a54d36SAndroid Build Coastguard Worker 
205*48a54d36SAndroid Build Coastguard Worker /*
206*48a54d36SAndroid Build Coastguard Worker 	Convert a DNS resource record (RR) code to an address family (AF) code.
207*48a54d36SAndroid Build Coastguard Worker 
208*48a54d36SAndroid Build Coastguard Worker 	Parameters
209*48a54d36SAndroid Build Coastguard Worker 		rrtype
210*48a54d36SAndroid Build Coastguard Worker 			resource record type (from nameser.h)
211*48a54d36SAndroid Build Coastguard Worker 
212*48a54d36SAndroid Build Coastguard Worker 	Returns
213*48a54d36SAndroid Build Coastguard Worker 		Appropriate AF code (from socket.h), or AF_UNSPEC if an appropriate
214*48a54d36SAndroid Build Coastguard Worker 		mapping couldn't be determined
215*48a54d36SAndroid Build Coastguard Worker  */
216*48a54d36SAndroid Build Coastguard Worker int
217*48a54d36SAndroid Build Coastguard Worker rr_to_af (ns_type_t rrtype);
218*48a54d36SAndroid Build Coastguard Worker 
219*48a54d36SAndroid Build Coastguard Worker 
220*48a54d36SAndroid Build Coastguard Worker /*
221*48a54d36SAndroid Build Coastguard Worker 	Convert an address family (AF) code to a DNS resource record (RR) code.
222*48a54d36SAndroid Build Coastguard Worker 
223*48a54d36SAndroid Build Coastguard Worker 	Parameters
224*48a54d36SAndroid Build Coastguard Worker 		int
225*48a54d36SAndroid Build Coastguard Worker 			address family code (from socket.h)
226*48a54d36SAndroid Build Coastguard Worker 	Returns
227*48a54d36SAndroid Build Coastguard Worker 		Appropriate RR code (from nameser.h), or ns_t_invalid if an appropriate
228*48a54d36SAndroid Build Coastguard Worker 		mapping couldn't be determined
229*48a54d36SAndroid Build Coastguard Worker  */
230*48a54d36SAndroid Build Coastguard Worker ns_type_t
231*48a54d36SAndroid Build Coastguard Worker af_to_rr (int af);
232*48a54d36SAndroid Build Coastguard Worker 
233*48a54d36SAndroid Build Coastguard Worker 
234*48a54d36SAndroid Build Coastguard Worker /*
235*48a54d36SAndroid Build Coastguard Worker 	Convert a string to an address family (case insensitive).
236*48a54d36SAndroid Build Coastguard Worker 
237*48a54d36SAndroid Build Coastguard Worker 	Returns
238*48a54d36SAndroid Build Coastguard Worker 		Matching AF code, or AF_UNSPEC if no match found.
239*48a54d36SAndroid Build Coastguard Worker  */
240*48a54d36SAndroid Build Coastguard Worker int
241*48a54d36SAndroid Build Coastguard Worker str_to_af (const char * str);
242*48a54d36SAndroid Build Coastguard Worker 
243*48a54d36SAndroid Build Coastguard Worker 
244*48a54d36SAndroid Build Coastguard Worker /*
245*48a54d36SAndroid Build Coastguard Worker 	Convert a string to an ns_class_t (case insensitive).
246*48a54d36SAndroid Build Coastguard Worker 
247*48a54d36SAndroid Build Coastguard Worker 	Returns
248*48a54d36SAndroid Build Coastguard Worker 		Matching ns_class_t, or ns_c_invalid if no match found.
249*48a54d36SAndroid Build Coastguard Worker  */
250*48a54d36SAndroid Build Coastguard Worker ns_class_t
251*48a54d36SAndroid Build Coastguard Worker str_to_ns_class (const char * str);
252*48a54d36SAndroid Build Coastguard Worker 
253*48a54d36SAndroid Build Coastguard Worker 
254*48a54d36SAndroid Build Coastguard Worker /*
255*48a54d36SAndroid Build Coastguard Worker 	Convert a string to an ns_type_t (case insensitive).
256*48a54d36SAndroid Build Coastguard Worker 
257*48a54d36SAndroid Build Coastguard Worker 	Returns
258*48a54d36SAndroid Build Coastguard Worker 		Matching ns_type_t, or ns_t_invalid if no match found.
259*48a54d36SAndroid Build Coastguard Worker  */
260*48a54d36SAndroid Build Coastguard Worker ns_type_t
261*48a54d36SAndroid Build Coastguard Worker str_to_ns_type (const char * str);
262*48a54d36SAndroid Build Coastguard Worker 
263*48a54d36SAndroid Build Coastguard Worker 
264*48a54d36SAndroid Build Coastguard Worker /*
265*48a54d36SAndroid Build Coastguard Worker 	Convert an address family code to a string.
266*48a54d36SAndroid Build Coastguard Worker 
267*48a54d36SAndroid Build Coastguard Worker 	Returns
268*48a54d36SAndroid Build Coastguard Worker 		String representation of AF,
269*48a54d36SAndroid Build Coastguard Worker 		or NULL if address family unrecognised or invalid.
270*48a54d36SAndroid Build Coastguard Worker  */
271*48a54d36SAndroid Build Coastguard Worker const char *
272*48a54d36SAndroid Build Coastguard Worker af_to_str (int in);
273*48a54d36SAndroid Build Coastguard Worker 
274*48a54d36SAndroid Build Coastguard Worker 
275*48a54d36SAndroid Build Coastguard Worker /*
276*48a54d36SAndroid Build Coastguard Worker 	Convert an ns_class_t code to a string.
277*48a54d36SAndroid Build Coastguard Worker 
278*48a54d36SAndroid Build Coastguard Worker 	Returns
279*48a54d36SAndroid Build Coastguard Worker 		String representation of ns_class_t,
280*48a54d36SAndroid Build Coastguard Worker 		or NULL if ns_class_t unrecognised or invalid.
281*48a54d36SAndroid Build Coastguard Worker  */
282*48a54d36SAndroid Build Coastguard Worker const char *
283*48a54d36SAndroid Build Coastguard Worker ns_class_to_str (ns_class_t in);
284*48a54d36SAndroid Build Coastguard Worker 
285*48a54d36SAndroid Build Coastguard Worker 
286*48a54d36SAndroid Build Coastguard Worker /*
287*48a54d36SAndroid Build Coastguard Worker 	Convert an ns_type_t code to a string.
288*48a54d36SAndroid Build Coastguard Worker 
289*48a54d36SAndroid Build Coastguard Worker 	Returns
290*48a54d36SAndroid Build Coastguard Worker 		String representation of ns_type_t,
291*48a54d36SAndroid Build Coastguard Worker 		or NULL if ns_type_t unrecognised or invalid.
292*48a54d36SAndroid Build Coastguard Worker  */
293*48a54d36SAndroid Build Coastguard Worker const char *
294*48a54d36SAndroid Build Coastguard Worker ns_type_to_str (ns_type_t in);
295*48a54d36SAndroid Build Coastguard Worker 
296*48a54d36SAndroid Build Coastguard Worker 
297*48a54d36SAndroid Build Coastguard Worker /*
298*48a54d36SAndroid Build Coastguard Worker 	Convert DNS rdata in label format (RFC1034, RFC1035) to a name.
299*48a54d36SAndroid Build Coastguard Worker 
300*48a54d36SAndroid Build Coastguard Worker 	On error, partial data is written to name (as much as was successfully
301*48a54d36SAndroid Build Coastguard Worker 	processed) and an error code is returned.  Errors include a name too
302*48a54d36SAndroid Build Coastguard Worker 	long for the buffer and a pointer in the label (which cannot be
303*48a54d36SAndroid Build Coastguard Worker 	resolved).
304*48a54d36SAndroid Build Coastguard Worker 
305*48a54d36SAndroid Build Coastguard Worker 	Parameters
306*48a54d36SAndroid Build Coastguard Worker 		rdata
307*48a54d36SAndroid Build Coastguard Worker 			Rdata formatted as series of labels.
308*48a54d36SAndroid Build Coastguard Worker 		rdlen
309*48a54d36SAndroid Build Coastguard Worker 			Length of rdata buffer.
310*48a54d36SAndroid Build Coastguard Worker 		name
311*48a54d36SAndroid Build Coastguard Worker 			Buffer to store fully qualified result in.
312*48a54d36SAndroid Build Coastguard Worker 			By RFC1034 section 3.1, a 255 character buffer (256 characters
313*48a54d36SAndroid Build Coastguard Worker 			including null) is long enough for any legal name.
314*48a54d36SAndroid Build Coastguard Worker 		name_len
315*48a54d36SAndroid Build Coastguard Worker 			Number of characters available in name buffer, not including
316*48a54d36SAndroid Build Coastguard Worker 			trailing null.
317*48a54d36SAndroid Build Coastguard Worker 
318*48a54d36SAndroid Build Coastguard Worker 	Returns
319*48a54d36SAndroid Build Coastguard Worker 		Length of name buffer (not including trailing null).
320*48a54d36SAndroid Build Coastguard Worker 		< 0 on error.
321*48a54d36SAndroid Build Coastguard Worker 		A return of 0 implies the empty domain.
322*48a54d36SAndroid Build Coastguard Worker  */
323*48a54d36SAndroid Build Coastguard Worker int
324*48a54d36SAndroid Build Coastguard Worker dns_rdata_to_name (const char * rdata, int rdlen, char * name, int name_len);
325*48a54d36SAndroid Build Coastguard Worker enum
326*48a54d36SAndroid Build Coastguard Worker {
327*48a54d36SAndroid Build Coastguard Worker 	DNS_RDATA_TO_NAME_BAD_FORMAT = -1,
328*48a54d36SAndroid Build Coastguard Worker 		// Format is broken.  Usually because we ran out of data
329*48a54d36SAndroid Build Coastguard Worker 		// (according to rdata) before the labels said we should.
330*48a54d36SAndroid Build Coastguard Worker 	DNS_RDATA_TO_NAME_TOO_LONG = -2,
331*48a54d36SAndroid Build Coastguard Worker 		// The converted rdata is longer than the name buffer.
332*48a54d36SAndroid Build Coastguard Worker 	DNS_RDATA_TO_NAME_PTR = -3,
333*48a54d36SAndroid Build Coastguard Worker 		// The rdata contains a pointer.
334*48a54d36SAndroid Build Coastguard Worker };
335*48a54d36SAndroid Build Coastguard Worker 
336*48a54d36SAndroid Build Coastguard Worker #define DNS_LABEL_MAXLEN 63
337*48a54d36SAndroid Build Coastguard Worker 	// Maximum length of a single DNS label
338*48a54d36SAndroid Build Coastguard Worker #define DNS_NAME_MAXLEN 256
339*48a54d36SAndroid Build Coastguard Worker 	// Maximum length of a DNS name
340*48a54d36SAndroid Build Coastguard Worker 
341*48a54d36SAndroid Build Coastguard Worker //----------
342*48a54d36SAndroid Build Coastguard Worker // Public types
343*48a54d36SAndroid Build Coastguard Worker 
344*48a54d36SAndroid Build Coastguard Worker typedef int errcode_t;
345*48a54d36SAndroid Build Coastguard Worker 	// Used for 0 = success, non-zero = error code functions
346*48a54d36SAndroid Build Coastguard Worker 
347*48a54d36SAndroid Build Coastguard Worker 
348*48a54d36SAndroid Build Coastguard Worker //----------
349*48a54d36SAndroid Build Coastguard Worker // Public functions
350*48a54d36SAndroid Build Coastguard Worker 
351*48a54d36SAndroid Build Coastguard Worker /*
352*48a54d36SAndroid Build Coastguard Worker 	Test whether a domain name is in a domain covered by nss_mdns.
353*48a54d36SAndroid Build Coastguard Worker 	The name is assumed to be fully qualified (trailing dot optional);
354*48a54d36SAndroid Build Coastguard Worker 	unqualified names will be processed but may return unusual results
355*48a54d36SAndroid Build Coastguard Worker 	if the unqualified prefix happens to match a domain suffix.
356*48a54d36SAndroid Build Coastguard Worker 
357*48a54d36SAndroid Build Coastguard Worker 	Returns
358*48a54d36SAndroid Build Coastguard Worker 		 1 success
359*48a54d36SAndroid Build Coastguard Worker 		 0 failure
360*48a54d36SAndroid Build Coastguard Worker 		-1 error, check errno
361*48a54d36SAndroid Build Coastguard Worker  */
362*48a54d36SAndroid Build Coastguard Worker int
363*48a54d36SAndroid Build Coastguard Worker config_is_mdns_suffix (const char * name);
364*48a54d36SAndroid Build Coastguard Worker 
365*48a54d36SAndroid Build Coastguard Worker 
366*48a54d36SAndroid Build Coastguard Worker /*
367*48a54d36SAndroid Build Coastguard Worker 	Loads all relevant data from configuration file.  Other code should
368*48a54d36SAndroid Build Coastguard Worker 	rarely need to call this function, since all other public configuration
369*48a54d36SAndroid Build Coastguard Worker 	functions do so implicitly.  Once loaded, configuration info doesn't
370*48a54d36SAndroid Build Coastguard Worker 	change.
371*48a54d36SAndroid Build Coastguard Worker 
372*48a54d36SAndroid Build Coastguard Worker 	Returns
373*48a54d36SAndroid Build Coastguard Worker 		0 configuration ready
374*48a54d36SAndroid Build Coastguard Worker 		non-zero configuration error code
375*48a54d36SAndroid Build Coastguard Worker  */
376*48a54d36SAndroid Build Coastguard Worker errcode_t
377*48a54d36SAndroid Build Coastguard Worker init_config ();
378*48a54d36SAndroid Build Coastguard Worker 
379*48a54d36SAndroid Build Coastguard Worker #define ENTNAME  hostent
380*48a54d36SAndroid Build Coastguard Worker #define DATABASE "hosts"
381*48a54d36SAndroid Build Coastguard Worker 
382*48a54d36SAndroid Build Coastguard Worker #include <nss.h>
383*48a54d36SAndroid Build Coastguard Worker 	// For nss_status
384*48a54d36SAndroid Build Coastguard Worker #include <netdb.h>
385*48a54d36SAndroid Build Coastguard Worker 	// For hostent
386*48a54d36SAndroid Build Coastguard Worker #include <sys/types.h>
387*48a54d36SAndroid Build Coastguard Worker 	// For size_t
388*48a54d36SAndroid Build Coastguard Worker 
389*48a54d36SAndroid Build Coastguard Worker typedef enum nss_status nss_status;
390*48a54d36SAndroid Build Coastguard Worker typedef struct hostent hostent;
391*48a54d36SAndroid Build Coastguard Worker 
392*48a54d36SAndroid Build Coastguard Worker /*
393*48a54d36SAndroid Build Coastguard Worker gethostbyname implementation
394*48a54d36SAndroid Build Coastguard Worker 
395*48a54d36SAndroid Build Coastguard Worker 	name:
396*48a54d36SAndroid Build Coastguard Worker 		name to look up
397*48a54d36SAndroid Build Coastguard Worker 	result_buf:
398*48a54d36SAndroid Build Coastguard Worker 		resulting entry
399*48a54d36SAndroid Build Coastguard Worker 	buf:
400*48a54d36SAndroid Build Coastguard Worker 		auxillary buffer
401*48a54d36SAndroid Build Coastguard Worker 	buflen:
402*48a54d36SAndroid Build Coastguard Worker 		length of auxillary buffer
403*48a54d36SAndroid Build Coastguard Worker 	errnop:
404*48a54d36SAndroid Build Coastguard Worker 		pointer to errno
405*48a54d36SAndroid Build Coastguard Worker 	h_errnop:
406*48a54d36SAndroid Build Coastguard Worker 		pointer to h_errno
407*48a54d36SAndroid Build Coastguard Worker  */
408*48a54d36SAndroid Build Coastguard Worker nss_status
409*48a54d36SAndroid Build Coastguard Worker _nss_mdns_gethostbyname_r (
410*48a54d36SAndroid Build Coastguard Worker 	const char *name,
411*48a54d36SAndroid Build Coastguard Worker 	hostent * result_buf,
412*48a54d36SAndroid Build Coastguard Worker 	char *buf,
413*48a54d36SAndroid Build Coastguard Worker 	size_t buflen,
414*48a54d36SAndroid Build Coastguard Worker 	int *errnop,
415*48a54d36SAndroid Build Coastguard Worker 	int *h_errnop
416*48a54d36SAndroid Build Coastguard Worker );
417*48a54d36SAndroid Build Coastguard Worker 
418*48a54d36SAndroid Build Coastguard Worker 
419*48a54d36SAndroid Build Coastguard Worker /*
420*48a54d36SAndroid Build Coastguard Worker gethostbyname2 implementation
421*48a54d36SAndroid Build Coastguard Worker 
422*48a54d36SAndroid Build Coastguard Worker 	name:
423*48a54d36SAndroid Build Coastguard Worker 		name to look up
424*48a54d36SAndroid Build Coastguard Worker 	af:
425*48a54d36SAndroid Build Coastguard Worker 		address family
426*48a54d36SAndroid Build Coastguard Worker 	result_buf:
427*48a54d36SAndroid Build Coastguard Worker 		resulting entry
428*48a54d36SAndroid Build Coastguard Worker 	buf:
429*48a54d36SAndroid Build Coastguard Worker 		auxillary buffer
430*48a54d36SAndroid Build Coastguard Worker 	buflen:
431*48a54d36SAndroid Build Coastguard Worker 		length of auxillary buffer
432*48a54d36SAndroid Build Coastguard Worker 	errnop:
433*48a54d36SAndroid Build Coastguard Worker 		pointer to errno
434*48a54d36SAndroid Build Coastguard Worker 	h_errnop:
435*48a54d36SAndroid Build Coastguard Worker 		pointer to h_errno
436*48a54d36SAndroid Build Coastguard Worker  */
437*48a54d36SAndroid Build Coastguard Worker nss_status
438*48a54d36SAndroid Build Coastguard Worker _nss_mdns_gethostbyname2_r (
439*48a54d36SAndroid Build Coastguard Worker 	const char *name,
440*48a54d36SAndroid Build Coastguard Worker 	int af,
441*48a54d36SAndroid Build Coastguard Worker 	hostent * result_buf,
442*48a54d36SAndroid Build Coastguard Worker 	char *buf,
443*48a54d36SAndroid Build Coastguard Worker 	size_t buflen,
444*48a54d36SAndroid Build Coastguard Worker 	int *errnop,
445*48a54d36SAndroid Build Coastguard Worker 	int *h_errnop
446*48a54d36SAndroid Build Coastguard Worker );
447*48a54d36SAndroid Build Coastguard Worker 
448*48a54d36SAndroid Build Coastguard Worker 
449*48a54d36SAndroid Build Coastguard Worker /*
450*48a54d36SAndroid Build Coastguard Worker gethostbyaddr implementation
451*48a54d36SAndroid Build Coastguard Worker 
452*48a54d36SAndroid Build Coastguard Worker 	addr:
453*48a54d36SAndroid Build Coastguard Worker 		address structure to look up
454*48a54d36SAndroid Build Coastguard Worker 	len:
455*48a54d36SAndroid Build Coastguard Worker 		length of address structure
456*48a54d36SAndroid Build Coastguard Worker 	af:
457*48a54d36SAndroid Build Coastguard Worker 		address family
458*48a54d36SAndroid Build Coastguard Worker 	result_buf:
459*48a54d36SAndroid Build Coastguard Worker 		resulting entry
460*48a54d36SAndroid Build Coastguard Worker 	buf:
461*48a54d36SAndroid Build Coastguard Worker 		auxillary buffer
462*48a54d36SAndroid Build Coastguard Worker 	buflen:
463*48a54d36SAndroid Build Coastguard Worker 		length of auxillary buffer
464*48a54d36SAndroid Build Coastguard Worker 	errnop:
465*48a54d36SAndroid Build Coastguard Worker 		pointer to errno
466*48a54d36SAndroid Build Coastguard Worker 	h_errnop:
467*48a54d36SAndroid Build Coastguard Worker 		pointer to h_errno
468*48a54d36SAndroid Build Coastguard Worker  */
469*48a54d36SAndroid Build Coastguard Worker nss_status
470*48a54d36SAndroid Build Coastguard Worker _nss_mdns_gethostbyaddr_r (
471*48a54d36SAndroid Build Coastguard Worker 	const void *addr,
472*48a54d36SAndroid Build Coastguard Worker 	socklen_t len,
473*48a54d36SAndroid Build Coastguard Worker 	int af,
474*48a54d36SAndroid Build Coastguard Worker 	hostent * result_buf,
475*48a54d36SAndroid Build Coastguard Worker 	char *buf,
476*48a54d36SAndroid Build Coastguard Worker 	size_t buflen,
477*48a54d36SAndroid Build Coastguard Worker 	int *errnop,
478*48a54d36SAndroid Build Coastguard Worker 	int *h_errnop
479*48a54d36SAndroid Build Coastguard Worker );
480*48a54d36SAndroid Build Coastguard Worker 
481*48a54d36SAndroid Build Coastguard Worker 
482*48a54d36SAndroid Build Coastguard Worker //----------
483*48a54d36SAndroid Build Coastguard Worker // Types and Constants
484*48a54d36SAndroid Build Coastguard Worker 
485*48a54d36SAndroid Build Coastguard Worker const int MDNS_VERBOSE = 0;
486*48a54d36SAndroid Build Coastguard Worker 	// This enables verbose syslog messages
487*48a54d36SAndroid Build Coastguard Worker 	// If zero, only "imporant" messages will appear in syslog
488*48a54d36SAndroid Build Coastguard Worker 
489*48a54d36SAndroid Build Coastguard Worker #define k_hostname_maxlen 256
490*48a54d36SAndroid Build Coastguard Worker 	// As per RFC1034 and RFC1035
491*48a54d36SAndroid Build Coastguard Worker #define k_aliases_max 15
492*48a54d36SAndroid Build Coastguard Worker #define k_addrs_max 15
493*48a54d36SAndroid Build Coastguard Worker 
494*48a54d36SAndroid Build Coastguard Worker typedef struct buf_header
495*48a54d36SAndroid Build Coastguard Worker {
496*48a54d36SAndroid Build Coastguard Worker 	char hostname [k_hostname_maxlen + 1];
497*48a54d36SAndroid Build Coastguard Worker 	char * aliases [k_aliases_max + 1];
498*48a54d36SAndroid Build Coastguard Worker 	char * addrs [k_addrs_max + 1];
499*48a54d36SAndroid Build Coastguard Worker } buf_header_t;
500*48a54d36SAndroid Build Coastguard Worker 
501*48a54d36SAndroid Build Coastguard Worker typedef struct result_map
502*48a54d36SAndroid Build Coastguard Worker {
503*48a54d36SAndroid Build Coastguard Worker 	int done;
504*48a54d36SAndroid Build Coastguard Worker 	nss_status status;
505*48a54d36SAndroid Build Coastguard Worker 	hostent * hostent;
506*48a54d36SAndroid Build Coastguard Worker 	buf_header_t * header;
507*48a54d36SAndroid Build Coastguard Worker 	int aliases_count;
508*48a54d36SAndroid Build Coastguard Worker 	int addrs_count;
509*48a54d36SAndroid Build Coastguard Worker 	char * buffer;
510*48a54d36SAndroid Build Coastguard Worker 	int addr_idx;
511*48a54d36SAndroid Build Coastguard Worker 		// Index for addresses - grow from low end
512*48a54d36SAndroid Build Coastguard Worker 		// Index points to first empty space
513*48a54d36SAndroid Build Coastguard Worker 	int alias_idx;
514*48a54d36SAndroid Build Coastguard Worker 		// Index for aliases - grow from high end
515*48a54d36SAndroid Build Coastguard Worker 		// Index points to lowest entry
516*48a54d36SAndroid Build Coastguard Worker 	int r_errno;
517*48a54d36SAndroid Build Coastguard Worker 	int r_h_errno;
518*48a54d36SAndroid Build Coastguard Worker } result_map_t;
519*48a54d36SAndroid Build Coastguard Worker 
520*48a54d36SAndroid Build Coastguard Worker static const struct timeval
521*48a54d36SAndroid Build Coastguard Worker 	k_select_time = { 0, 500000 };
522*48a54d36SAndroid Build Coastguard Worker 		// 0 seconds, 500 milliseconds
523*48a54d36SAndroid Build Coastguard Worker 
524*48a54d36SAndroid Build Coastguard Worker //----------
525*48a54d36SAndroid Build Coastguard Worker // Local prototypes
526*48a54d36SAndroid Build Coastguard Worker 
527*48a54d36SAndroid Build Coastguard Worker static nss_status
528*48a54d36SAndroid Build Coastguard Worker mdns_gethostbyname2 (
529*48a54d36SAndroid Build Coastguard Worker 	const char *name,
530*48a54d36SAndroid Build Coastguard Worker 	int af,
531*48a54d36SAndroid Build Coastguard Worker 	hostent * result_buf,
532*48a54d36SAndroid Build Coastguard Worker 	char *buf,
533*48a54d36SAndroid Build Coastguard Worker 	size_t buflen,
534*48a54d36SAndroid Build Coastguard Worker 	int *errnop,
535*48a54d36SAndroid Build Coastguard Worker 	int *h_errnop
536*48a54d36SAndroid Build Coastguard Worker );
537*48a54d36SAndroid Build Coastguard Worker 
538*48a54d36SAndroid Build Coastguard Worker 
539*48a54d36SAndroid Build Coastguard Worker /*
540*48a54d36SAndroid Build Coastguard Worker 	Lookup name using mDNS server
541*48a54d36SAndroid Build Coastguard Worker  */
542*48a54d36SAndroid Build Coastguard Worker static nss_status
543*48a54d36SAndroid Build Coastguard Worker mdns_lookup_name (
544*48a54d36SAndroid Build Coastguard Worker 	const char * fullname,
545*48a54d36SAndroid Build Coastguard Worker 	int af,
546*48a54d36SAndroid Build Coastguard Worker 	result_map_t * result
547*48a54d36SAndroid Build Coastguard Worker );
548*48a54d36SAndroid Build Coastguard Worker 
549*48a54d36SAndroid Build Coastguard Worker /*
550*48a54d36SAndroid Build Coastguard Worker 	Lookup address using mDNS server
551*48a54d36SAndroid Build Coastguard Worker  */
552*48a54d36SAndroid Build Coastguard Worker static nss_status
553*48a54d36SAndroid Build Coastguard Worker mdns_lookup_addr (
554*48a54d36SAndroid Build Coastguard Worker 	const void * addr,
555*48a54d36SAndroid Build Coastguard Worker 	socklen_t len,
556*48a54d36SAndroid Build Coastguard Worker 	int af,
557*48a54d36SAndroid Build Coastguard Worker 	const char * addr_str,
558*48a54d36SAndroid Build Coastguard Worker 	result_map_t * result
559*48a54d36SAndroid Build Coastguard Worker );
560*48a54d36SAndroid Build Coastguard Worker 
561*48a54d36SAndroid Build Coastguard Worker 
562*48a54d36SAndroid Build Coastguard Worker /*
563*48a54d36SAndroid Build Coastguard Worker 	Handle incoming MDNS events
564*48a54d36SAndroid Build Coastguard Worker  */
565*48a54d36SAndroid Build Coastguard Worker static nss_status
566*48a54d36SAndroid Build Coastguard Worker handle_events (DNSServiceRef sdref, result_map_t * result, const char * str);
567*48a54d36SAndroid Build Coastguard Worker 
568*48a54d36SAndroid Build Coastguard Worker 
569*48a54d36SAndroid Build Coastguard Worker // Callback for mdns_lookup operations
570*48a54d36SAndroid Build Coastguard Worker //DNSServiceQueryRecordReply mdns_lookup_callback;
571*48a54d36SAndroid Build Coastguard Worker typedef void
572*48a54d36SAndroid Build Coastguard Worker mdns_lookup_callback_t
573*48a54d36SAndroid Build Coastguard Worker (
574*48a54d36SAndroid Build Coastguard Worker 	DNSServiceRef		sdref,
575*48a54d36SAndroid Build Coastguard Worker 	DNSServiceFlags		flags,
576*48a54d36SAndroid Build Coastguard Worker 	uint32_t			interface_index,
577*48a54d36SAndroid Build Coastguard Worker 	DNSServiceErrorType	error_code,
578*48a54d36SAndroid Build Coastguard Worker 	const char			*fullname,
579*48a54d36SAndroid Build Coastguard Worker 	uint16_t			rrtype,
580*48a54d36SAndroid Build Coastguard Worker 	uint16_t			rrclass,
581*48a54d36SAndroid Build Coastguard Worker 	uint16_t			rdlen,
582*48a54d36SAndroid Build Coastguard Worker 	const void			*rdata,
583*48a54d36SAndroid Build Coastguard Worker 	uint32_t			ttl,
584*48a54d36SAndroid Build Coastguard Worker 	void				*context
585*48a54d36SAndroid Build Coastguard Worker );
586*48a54d36SAndroid Build Coastguard Worker 
587*48a54d36SAndroid Build Coastguard Worker mdns_lookup_callback_t mdns_lookup_callback;
588*48a54d36SAndroid Build Coastguard Worker 
589*48a54d36SAndroid Build Coastguard Worker 
590*48a54d36SAndroid Build Coastguard Worker static int
591*48a54d36SAndroid Build Coastguard Worker init_result (
592*48a54d36SAndroid Build Coastguard Worker 	result_map_t * result,
593*48a54d36SAndroid Build Coastguard Worker 	hostent * result_buf,
594*48a54d36SAndroid Build Coastguard Worker 	char * buf,
595*48a54d36SAndroid Build Coastguard Worker 	size_t buflen
596*48a54d36SAndroid Build Coastguard Worker );
597*48a54d36SAndroid Build Coastguard Worker 
598*48a54d36SAndroid Build Coastguard Worker static int
599*48a54d36SAndroid Build Coastguard Worker callback_body_ptr (
600*48a54d36SAndroid Build Coastguard Worker 	const char * fullname,
601*48a54d36SAndroid Build Coastguard Worker 	result_map_t * result,
602*48a54d36SAndroid Build Coastguard Worker 	int rdlen,
603*48a54d36SAndroid Build Coastguard Worker 	const void * rdata
604*48a54d36SAndroid Build Coastguard Worker );
605*48a54d36SAndroid Build Coastguard Worker 
606*48a54d36SAndroid Build Coastguard Worker static void *
607*48a54d36SAndroid Build Coastguard Worker add_address_to_buffer (result_map_t * result, const void * data, int len);
608*48a54d36SAndroid Build Coastguard Worker static char *
609*48a54d36SAndroid Build Coastguard Worker add_alias_to_buffer (result_map_t * result, const char * data, int len);
610*48a54d36SAndroid Build Coastguard Worker static char *
611*48a54d36SAndroid Build Coastguard Worker add_hostname_len (result_map_t * result, const char * fullname, int len);
612*48a54d36SAndroid Build Coastguard Worker static char *
613*48a54d36SAndroid Build Coastguard Worker add_hostname_or_alias (result_map_t * result, const char * data, int len);
614*48a54d36SAndroid Build Coastguard Worker 
615*48a54d36SAndroid Build Coastguard Worker static void *
616*48a54d36SAndroid Build Coastguard Worker contains_address (result_map_t * result, const void * data, int len);
617*48a54d36SAndroid Build Coastguard Worker static char *
618*48a54d36SAndroid Build Coastguard Worker contains_alias (result_map_t * result, const char * data);
619*48a54d36SAndroid Build Coastguard Worker 
620*48a54d36SAndroid Build Coastguard Worker 
621*48a54d36SAndroid Build Coastguard Worker static const char *
622*48a54d36SAndroid Build Coastguard Worker is_applicable_name (
623*48a54d36SAndroid Build Coastguard Worker 	result_map_t * result,
624*48a54d36SAndroid Build Coastguard Worker 	const char * name,
625*48a54d36SAndroid Build Coastguard Worker 	char * lookup_name
626*48a54d36SAndroid Build Coastguard Worker );
627*48a54d36SAndroid Build Coastguard Worker 
628*48a54d36SAndroid Build Coastguard Worker static const char *
629*48a54d36SAndroid Build Coastguard Worker is_applicable_addr (
630*48a54d36SAndroid Build Coastguard Worker 	result_map_t * result,
631*48a54d36SAndroid Build Coastguard Worker 	const void * addr,
632*48a54d36SAndroid Build Coastguard Worker 	int af,
633*48a54d36SAndroid Build Coastguard Worker 	char * addr_str
634*48a54d36SAndroid Build Coastguard Worker );
635*48a54d36SAndroid Build Coastguard Worker 
636*48a54d36SAndroid Build Coastguard Worker 
637*48a54d36SAndroid Build Coastguard Worker // Error code functions
638*48a54d36SAndroid Build Coastguard Worker 
639*48a54d36SAndroid Build Coastguard Worker static nss_status
640*48a54d36SAndroid Build Coastguard Worker set_err (result_map_t * result, nss_status status, int err, int herr);
641*48a54d36SAndroid Build Coastguard Worker 
642*48a54d36SAndroid Build Coastguard Worker static nss_status set_err_notfound (result_map_t * result);
643*48a54d36SAndroid Build Coastguard Worker static nss_status set_err_bad_hostname (result_map_t * result);
644*48a54d36SAndroid Build Coastguard Worker static nss_status set_err_buf_too_small (result_map_t * result);
645*48a54d36SAndroid Build Coastguard Worker static nss_status set_err_internal_resource_full (result_map_t * result);
646*48a54d36SAndroid Build Coastguard Worker static nss_status set_err_system (result_map_t * result);
647*48a54d36SAndroid Build Coastguard Worker static nss_status set_err_mdns_failed (result_map_t * result);
648*48a54d36SAndroid Build Coastguard Worker static nss_status set_err_success (result_map_t * result);
649*48a54d36SAndroid Build Coastguard Worker 
650*48a54d36SAndroid Build Coastguard Worker 
651*48a54d36SAndroid Build Coastguard Worker //----------
652*48a54d36SAndroid Build Coastguard Worker // Global variables
653*48a54d36SAndroid Build Coastguard Worker 
654*48a54d36SAndroid Build Coastguard Worker 
655*48a54d36SAndroid Build Coastguard Worker //----------
656*48a54d36SAndroid Build Coastguard Worker // NSS functions
657*48a54d36SAndroid Build Coastguard Worker 
658*48a54d36SAndroid Build Coastguard Worker nss_status
_nss_mdns_gethostbyname_r(const char * name,hostent * result_buf,char * buf,size_t buflen,int * errnop,int * h_errnop)659*48a54d36SAndroid Build Coastguard Worker _nss_mdns_gethostbyname_r (
660*48a54d36SAndroid Build Coastguard Worker 	const char *name,
661*48a54d36SAndroid Build Coastguard Worker 	hostent * result_buf,
662*48a54d36SAndroid Build Coastguard Worker 	char *buf,
663*48a54d36SAndroid Build Coastguard Worker 	size_t buflen,
664*48a54d36SAndroid Build Coastguard Worker 	int *errnop,
665*48a54d36SAndroid Build Coastguard Worker 	int *h_errnop
666*48a54d36SAndroid Build Coastguard Worker )
667*48a54d36SAndroid Build Coastguard Worker {
668*48a54d36SAndroid Build Coastguard Worker 	if (MDNS_VERBOSE)
669*48a54d36SAndroid Build Coastguard Worker 		syslog (LOG_DEBUG,
670*48a54d36SAndroid Build Coastguard Worker 			"mdns: Called nss_mdns_gethostbyname with %s",
671*48a54d36SAndroid Build Coastguard Worker 			name
672*48a54d36SAndroid Build Coastguard Worker 		);
673*48a54d36SAndroid Build Coastguard Worker 
674*48a54d36SAndroid Build Coastguard Worker 	return
675*48a54d36SAndroid Build Coastguard Worker 		mdns_gethostbyname2 (
676*48a54d36SAndroid Build Coastguard Worker 			name, AF_INET, result_buf, buf, buflen, errnop, h_errnop
677*48a54d36SAndroid Build Coastguard Worker 		);
678*48a54d36SAndroid Build Coastguard Worker }
679*48a54d36SAndroid Build Coastguard Worker 
680*48a54d36SAndroid Build Coastguard Worker 
681*48a54d36SAndroid Build Coastguard Worker nss_status
_nss_mdns_gethostbyname2_r(const char * name,int af,hostent * result_buf,char * buf,size_t buflen,int * errnop,int * h_errnop)682*48a54d36SAndroid Build Coastguard Worker _nss_mdns_gethostbyname2_r (
683*48a54d36SAndroid Build Coastguard Worker 	const char *name,
684*48a54d36SAndroid Build Coastguard Worker 	int af,
685*48a54d36SAndroid Build Coastguard Worker 	hostent * result_buf,
686*48a54d36SAndroid Build Coastguard Worker 	char *buf,
687*48a54d36SAndroid Build Coastguard Worker 	size_t buflen,
688*48a54d36SAndroid Build Coastguard Worker 	int *errnop,
689*48a54d36SAndroid Build Coastguard Worker 	int *h_errnop
690*48a54d36SAndroid Build Coastguard Worker )
691*48a54d36SAndroid Build Coastguard Worker {
692*48a54d36SAndroid Build Coastguard Worker 	if (MDNS_VERBOSE)
693*48a54d36SAndroid Build Coastguard Worker 		syslog (LOG_DEBUG,
694*48a54d36SAndroid Build Coastguard Worker 			"mdns: Called nss_mdns_gethostbyname2 with %s",
695*48a54d36SAndroid Build Coastguard Worker 			name
696*48a54d36SAndroid Build Coastguard Worker 		);
697*48a54d36SAndroid Build Coastguard Worker 
698*48a54d36SAndroid Build Coastguard Worker 	return
699*48a54d36SAndroid Build Coastguard Worker 		mdns_gethostbyname2 (
700*48a54d36SAndroid Build Coastguard Worker 			name, af, result_buf, buf, buflen, errnop, h_errnop
701*48a54d36SAndroid Build Coastguard Worker 		);
702*48a54d36SAndroid Build Coastguard Worker }
703*48a54d36SAndroid Build Coastguard Worker 
704*48a54d36SAndroid Build Coastguard Worker 
705*48a54d36SAndroid Build Coastguard Worker nss_status
_nss_mdns_gethostbyaddr_r(const void * addr,socklen_t len,int af,hostent * result_buf,char * buf,size_t buflen,int * errnop,int * h_errnop)706*48a54d36SAndroid Build Coastguard Worker _nss_mdns_gethostbyaddr_r (
707*48a54d36SAndroid Build Coastguard Worker 	const void *addr,
708*48a54d36SAndroid Build Coastguard Worker 	socklen_t len,
709*48a54d36SAndroid Build Coastguard Worker 	int af,
710*48a54d36SAndroid Build Coastguard Worker 	hostent * result_buf,
711*48a54d36SAndroid Build Coastguard Worker 	char *buf,
712*48a54d36SAndroid Build Coastguard Worker 	size_t buflen,
713*48a54d36SAndroid Build Coastguard Worker 	int *errnop,
714*48a54d36SAndroid Build Coastguard Worker 	int *h_errnop
715*48a54d36SAndroid Build Coastguard Worker )
716*48a54d36SAndroid Build Coastguard Worker {
717*48a54d36SAndroid Build Coastguard Worker 	char addr_str [NI_MAXHOST + 1];
718*48a54d36SAndroid Build Coastguard Worker 	result_map_t result;
719*48a54d36SAndroid Build Coastguard Worker 	int err_status;
720*48a54d36SAndroid Build Coastguard Worker 
721*48a54d36SAndroid Build Coastguard Worker 	if (inet_ntop (af, addr, addr_str, NI_MAXHOST) == NULL)
722*48a54d36SAndroid Build Coastguard Worker 	{
723*48a54d36SAndroid Build Coastguard Worker 		const char * family = af_to_str (af);
724*48a54d36SAndroid Build Coastguard Worker 		if (family == NULL)
725*48a54d36SAndroid Build Coastguard Worker 		{
726*48a54d36SAndroid Build Coastguard Worker 			family = "Unknown";
727*48a54d36SAndroid Build Coastguard Worker 		}
728*48a54d36SAndroid Build Coastguard Worker 
729*48a54d36SAndroid Build Coastguard Worker 		syslog (LOG_WARNING,
730*48a54d36SAndroid Build Coastguard Worker 			"mdns: Couldn't covert address, family %d (%s) in nss_mdns_gethostbyaddr: %s",
731*48a54d36SAndroid Build Coastguard Worker 			af,
732*48a54d36SAndroid Build Coastguard Worker 			family,
733*48a54d36SAndroid Build Coastguard Worker 			strerror (errno)
734*48a54d36SAndroid Build Coastguard Worker 		);
735*48a54d36SAndroid Build Coastguard Worker 
736*48a54d36SAndroid Build Coastguard Worker 		// This address family never applicable to us, so return NOT_FOUND
737*48a54d36SAndroid Build Coastguard Worker 
738*48a54d36SAndroid Build Coastguard Worker 		*errnop = ENOENT;
739*48a54d36SAndroid Build Coastguard Worker 		*h_errnop = HOST_NOT_FOUND;
740*48a54d36SAndroid Build Coastguard Worker 		return NSS_STATUS_NOTFOUND;
741*48a54d36SAndroid Build Coastguard Worker 	}
742*48a54d36SAndroid Build Coastguard Worker 	if (MDNS_VERBOSE)
743*48a54d36SAndroid Build Coastguard Worker 	{
744*48a54d36SAndroid Build Coastguard Worker 		syslog (LOG_DEBUG,
745*48a54d36SAndroid Build Coastguard Worker 			"mdns: Called nss_mdns_gethostbyaddr with %s",
746*48a54d36SAndroid Build Coastguard Worker 			addr_str
747*48a54d36SAndroid Build Coastguard Worker 		);
748*48a54d36SAndroid Build Coastguard Worker 	}
749*48a54d36SAndroid Build Coastguard Worker 
750*48a54d36SAndroid Build Coastguard Worker 	// Initialise result
751*48a54d36SAndroid Build Coastguard Worker 	err_status = init_result (&result, result_buf, buf, buflen);
752*48a54d36SAndroid Build Coastguard Worker 	if (err_status)
753*48a54d36SAndroid Build Coastguard Worker 	{
754*48a54d36SAndroid Build Coastguard Worker 		*errnop = err_status;
755*48a54d36SAndroid Build Coastguard Worker 		*h_errnop = NETDB_INTERNAL;
756*48a54d36SAndroid Build Coastguard Worker 		return NSS_STATUS_TRYAGAIN;
757*48a54d36SAndroid Build Coastguard Worker 	}
758*48a54d36SAndroid Build Coastguard Worker 
759*48a54d36SAndroid Build Coastguard Worker 	if (is_applicable_addr (&result, addr, af, addr_str))
760*48a54d36SAndroid Build Coastguard Worker 	{
761*48a54d36SAndroid Build Coastguard Worker 		nss_status rv;
762*48a54d36SAndroid Build Coastguard Worker 
763*48a54d36SAndroid Build Coastguard Worker 		rv = mdns_lookup_addr (addr, len, af, addr_str, &result);
764*48a54d36SAndroid Build Coastguard Worker 		if (rv == NSS_STATUS_SUCCESS)
765*48a54d36SAndroid Build Coastguard Worker 		{
766*48a54d36SAndroid Build Coastguard Worker 			return rv;
767*48a54d36SAndroid Build Coastguard Worker 		}
768*48a54d36SAndroid Build Coastguard Worker 	}
769*48a54d36SAndroid Build Coastguard Worker 
770*48a54d36SAndroid Build Coastguard Worker 	// Return current error status (defaults to NOT_FOUND)
771*48a54d36SAndroid Build Coastguard Worker 
772*48a54d36SAndroid Build Coastguard Worker 	*errnop = result.r_errno;
773*48a54d36SAndroid Build Coastguard Worker 	*h_errnop = result.r_h_errno;
774*48a54d36SAndroid Build Coastguard Worker 	return result.status;
775*48a54d36SAndroid Build Coastguard Worker }
776*48a54d36SAndroid Build Coastguard Worker 
777*48a54d36SAndroid Build Coastguard Worker 
778*48a54d36SAndroid Build Coastguard Worker //----------
779*48a54d36SAndroid Build Coastguard Worker // Local functions
780*48a54d36SAndroid Build Coastguard Worker 
781*48a54d36SAndroid Build Coastguard Worker nss_status
mdns_gethostbyname2(const char * name,int af,hostent * result_buf,char * buf,size_t buflen,int * errnop,int * h_errnop)782*48a54d36SAndroid Build Coastguard Worker mdns_gethostbyname2 (
783*48a54d36SAndroid Build Coastguard Worker 	const char *name,
784*48a54d36SAndroid Build Coastguard Worker 	int af,
785*48a54d36SAndroid Build Coastguard Worker 	hostent * result_buf,
786*48a54d36SAndroid Build Coastguard Worker 	char *buf,
787*48a54d36SAndroid Build Coastguard Worker 	size_t buflen,
788*48a54d36SAndroid Build Coastguard Worker 	int *errnop,
789*48a54d36SAndroid Build Coastguard Worker 	int *h_errnop
790*48a54d36SAndroid Build Coastguard Worker )
791*48a54d36SAndroid Build Coastguard Worker {
792*48a54d36SAndroid Build Coastguard Worker 	char lookup_name [k_hostname_maxlen + 1];
793*48a54d36SAndroid Build Coastguard Worker 	result_map_t result;
794*48a54d36SAndroid Build Coastguard Worker 	int err_status;
795*48a54d36SAndroid Build Coastguard Worker 
796*48a54d36SAndroid Build Coastguard Worker 	// Initialise result
797*48a54d36SAndroid Build Coastguard Worker 	err_status = init_result (&result, result_buf, buf, buflen);
798*48a54d36SAndroid Build Coastguard Worker 	if (err_status)
799*48a54d36SAndroid Build Coastguard Worker 	{
800*48a54d36SAndroid Build Coastguard Worker 		*errnop = err_status;
801*48a54d36SAndroid Build Coastguard Worker 		*h_errnop = NETDB_INTERNAL;
802*48a54d36SAndroid Build Coastguard Worker 		return NSS_STATUS_TRYAGAIN;
803*48a54d36SAndroid Build Coastguard Worker 	}
804*48a54d36SAndroid Build Coastguard Worker 
805*48a54d36SAndroid Build Coastguard Worker 	if (is_applicable_name (&result, name, lookup_name))
806*48a54d36SAndroid Build Coastguard Worker 	{
807*48a54d36SAndroid Build Coastguard Worker 		// Try using mdns
808*48a54d36SAndroid Build Coastguard Worker 		nss_status rv;
809*48a54d36SAndroid Build Coastguard Worker 
810*48a54d36SAndroid Build Coastguard Worker 		if (MDNS_VERBOSE)
811*48a54d36SAndroid Build Coastguard Worker 			syslog (LOG_DEBUG,
812*48a54d36SAndroid Build Coastguard Worker 				"mdns: Local name: %s",
813*48a54d36SAndroid Build Coastguard Worker 				name
814*48a54d36SAndroid Build Coastguard Worker 			);
815*48a54d36SAndroid Build Coastguard Worker 
816*48a54d36SAndroid Build Coastguard Worker 		rv = mdns_lookup_name (name, af, &result);
817*48a54d36SAndroid Build Coastguard Worker 		if (rv == NSS_STATUS_SUCCESS)
818*48a54d36SAndroid Build Coastguard Worker 		{
819*48a54d36SAndroid Build Coastguard Worker 			return rv;
820*48a54d36SAndroid Build Coastguard Worker 		}
821*48a54d36SAndroid Build Coastguard Worker 	}
822*48a54d36SAndroid Build Coastguard Worker 
823*48a54d36SAndroid Build Coastguard Worker 	// Return current error status (defaults to NOT_FOUND)
824*48a54d36SAndroid Build Coastguard Worker 
825*48a54d36SAndroid Build Coastguard Worker 	*errnop = result.r_errno;
826*48a54d36SAndroid Build Coastguard Worker 	*h_errnop = result.r_h_errno;
827*48a54d36SAndroid Build Coastguard Worker 	return result.status;
828*48a54d36SAndroid Build Coastguard Worker }
829*48a54d36SAndroid Build Coastguard Worker 
830*48a54d36SAndroid Build Coastguard Worker 
831*48a54d36SAndroid Build Coastguard Worker /*
832*48a54d36SAndroid Build Coastguard Worker 	Lookup a fully qualified hostname using the default record type
833*48a54d36SAndroid Build Coastguard Worker 	for the specified address family.
834*48a54d36SAndroid Build Coastguard Worker 
835*48a54d36SAndroid Build Coastguard Worker 	Parameters
836*48a54d36SAndroid Build Coastguard Worker 		fullname
837*48a54d36SAndroid Build Coastguard Worker 			Fully qualified hostname.  If not fully qualified the code will
838*48a54d36SAndroid Build Coastguard Worker 			still 'work', but the lookup is unlikely to succeed.
839*48a54d36SAndroid Build Coastguard Worker 		af
840*48a54d36SAndroid Build Coastguard Worker 			Either AF_INET or AF_INET6.  Other families are not supported.
841*48a54d36SAndroid Build Coastguard Worker 		result
842*48a54d36SAndroid Build Coastguard Worker 			Initialised 'result' data structure.
843*48a54d36SAndroid Build Coastguard Worker  */
844*48a54d36SAndroid Build Coastguard Worker static nss_status
mdns_lookup_name(const char * fullname,int af,result_map_t * result)845*48a54d36SAndroid Build Coastguard Worker mdns_lookup_name (
846*48a54d36SAndroid Build Coastguard Worker 	const char * fullname,
847*48a54d36SAndroid Build Coastguard Worker 	int af,
848*48a54d36SAndroid Build Coastguard Worker 	result_map_t * result
849*48a54d36SAndroid Build Coastguard Worker )
850*48a54d36SAndroid Build Coastguard Worker {
851*48a54d36SAndroid Build Coastguard Worker 	// Lookup using mDNS.
852*48a54d36SAndroid Build Coastguard Worker 	DNSServiceErrorType errcode;
853*48a54d36SAndroid Build Coastguard Worker 	DNSServiceRef sdref;
854*48a54d36SAndroid Build Coastguard Worker 	ns_type_t rrtype;
855*48a54d36SAndroid Build Coastguard Worker 	nss_status status;
856*48a54d36SAndroid Build Coastguard Worker 
857*48a54d36SAndroid Build Coastguard Worker 	if (MDNS_VERBOSE)
858*48a54d36SAndroid Build Coastguard Worker 		syslog (LOG_DEBUG,
859*48a54d36SAndroid Build Coastguard Worker 			"mdns: Attempting lookup of %s",
860*48a54d36SAndroid Build Coastguard Worker 			fullname
861*48a54d36SAndroid Build Coastguard Worker 		);
862*48a54d36SAndroid Build Coastguard Worker 
863*48a54d36SAndroid Build Coastguard Worker 	switch (af)
864*48a54d36SAndroid Build Coastguard Worker 	{
865*48a54d36SAndroid Build Coastguard Worker 	  case AF_INET:
866*48a54d36SAndroid Build Coastguard Worker 		rrtype = kDNSServiceType_A;
867*48a54d36SAndroid Build Coastguard Worker 		result->hostent->h_length = 4;
868*48a54d36SAndroid Build Coastguard Worker 			// Length of an A record
869*48a54d36SAndroid Build Coastguard Worker 		break;
870*48a54d36SAndroid Build Coastguard Worker 
871*48a54d36SAndroid Build Coastguard Worker 	  case AF_INET6:
872*48a54d36SAndroid Build Coastguard Worker 		rrtype = kDNSServiceType_AAAA;
873*48a54d36SAndroid Build Coastguard Worker 		result->hostent->h_length = 16;
874*48a54d36SAndroid Build Coastguard Worker 			// Length of an AAAA record
875*48a54d36SAndroid Build Coastguard Worker 		break;
876*48a54d36SAndroid Build Coastguard Worker 
877*48a54d36SAndroid Build Coastguard Worker 	  default:
878*48a54d36SAndroid Build Coastguard Worker 		syslog (LOG_WARNING,
879*48a54d36SAndroid Build Coastguard Worker 			"mdns: Unsupported address family %d",
880*48a54d36SAndroid Build Coastguard Worker 			af
881*48a54d36SAndroid Build Coastguard Worker 		);
882*48a54d36SAndroid Build Coastguard Worker 		return set_err_bad_hostname (result);
883*48a54d36SAndroid Build Coastguard Worker 	}
884*48a54d36SAndroid Build Coastguard Worker 	result->hostent->h_addrtype = af;
885*48a54d36SAndroid Build Coastguard Worker 
886*48a54d36SAndroid Build Coastguard Worker 	errcode =
887*48a54d36SAndroid Build Coastguard Worker 		DNSServiceQueryRecord (
888*48a54d36SAndroid Build Coastguard Worker 			&sdref,
889*48a54d36SAndroid Build Coastguard Worker 			kDNSServiceFlagsForceMulticast,		// force multicast query
890*48a54d36SAndroid Build Coastguard Worker 			kDNSServiceInterfaceIndexAny,	// all interfaces
891*48a54d36SAndroid Build Coastguard Worker 			fullname,	// full name to query for
892*48a54d36SAndroid Build Coastguard Worker 			rrtype,		// resource record type
893*48a54d36SAndroid Build Coastguard Worker 			kDNSServiceClass_IN,	// internet class records
894*48a54d36SAndroid Build Coastguard Worker 			mdns_lookup_callback,	// callback
895*48a54d36SAndroid Build Coastguard Worker 			result		// Context - result buffer
896*48a54d36SAndroid Build Coastguard Worker 		);
897*48a54d36SAndroid Build Coastguard Worker 
898*48a54d36SAndroid Build Coastguard Worker 	if (errcode)
899*48a54d36SAndroid Build Coastguard Worker 	{
900*48a54d36SAndroid Build Coastguard Worker 		syslog (LOG_WARNING,
901*48a54d36SAndroid Build Coastguard Worker 			"mdns: Failed to initialise lookup, error %d",
902*48a54d36SAndroid Build Coastguard Worker 			errcode
903*48a54d36SAndroid Build Coastguard Worker 		);
904*48a54d36SAndroid Build Coastguard Worker 		return set_err_mdns_failed (result);
905*48a54d36SAndroid Build Coastguard Worker 	}
906*48a54d36SAndroid Build Coastguard Worker 
907*48a54d36SAndroid Build Coastguard Worker 	status = handle_events (sdref, result, fullname);
908*48a54d36SAndroid Build Coastguard Worker 	DNSServiceRefDeallocate (sdref);
909*48a54d36SAndroid Build Coastguard Worker 	return status;
910*48a54d36SAndroid Build Coastguard Worker }
911*48a54d36SAndroid Build Coastguard Worker 
912*48a54d36SAndroid Build Coastguard Worker 
913*48a54d36SAndroid Build Coastguard Worker /*
914*48a54d36SAndroid Build Coastguard Worker 	Reverse (PTR) lookup for the specified address.
915*48a54d36SAndroid Build Coastguard Worker 
916*48a54d36SAndroid Build Coastguard Worker 	Parameters
917*48a54d36SAndroid Build Coastguard Worker 		addr
918*48a54d36SAndroid Build Coastguard Worker 			Either a struct in_addr or a struct in6_addr
919*48a54d36SAndroid Build Coastguard Worker 		addr_len
920*48a54d36SAndroid Build Coastguard Worker 			size of the address
921*48a54d36SAndroid Build Coastguard Worker 		af
922*48a54d36SAndroid Build Coastguard Worker 			Either AF_INET or AF_INET6.  Other families are not supported.
923*48a54d36SAndroid Build Coastguard Worker 			Must match addr
924*48a54d36SAndroid Build Coastguard Worker 		addr_str
925*48a54d36SAndroid Build Coastguard Worker 			Address in format suitable for PTR lookup.
926*48a54d36SAndroid Build Coastguard Worker 			AF_INET: a.b.c.d -> d.c.b.a.in-addr.arpa
927*48a54d36SAndroid Build Coastguard Worker 			AF_INET6: reverse nibble format, x.x.x...x.ip6.arpa
928*48a54d36SAndroid Build Coastguard Worker 		result
929*48a54d36SAndroid Build Coastguard Worker 			Initialised 'result' data structure.
930*48a54d36SAndroid Build Coastguard Worker  */
931*48a54d36SAndroid Build Coastguard Worker static nss_status
mdns_lookup_addr(const void * addr,socklen_t addr_len,int af,const char * addr_str,result_map_t * result)932*48a54d36SAndroid Build Coastguard Worker mdns_lookup_addr (
933*48a54d36SAndroid Build Coastguard Worker 	const void * addr,
934*48a54d36SAndroid Build Coastguard Worker 	socklen_t addr_len,
935*48a54d36SAndroid Build Coastguard Worker 	int af,
936*48a54d36SAndroid Build Coastguard Worker 	const char * addr_str,
937*48a54d36SAndroid Build Coastguard Worker 	result_map_t * result
938*48a54d36SAndroid Build Coastguard Worker )
939*48a54d36SAndroid Build Coastguard Worker {
940*48a54d36SAndroid Build Coastguard Worker 	DNSServiceErrorType errcode;
941*48a54d36SAndroid Build Coastguard Worker 	DNSServiceRef sdref;
942*48a54d36SAndroid Build Coastguard Worker 	nss_status status;
943*48a54d36SAndroid Build Coastguard Worker 
944*48a54d36SAndroid Build Coastguard Worker 	if (MDNS_VERBOSE)
945*48a54d36SAndroid Build Coastguard Worker 		syslog (LOG_DEBUG,
946*48a54d36SAndroid Build Coastguard Worker 			"mdns: Attempting lookup of %s",
947*48a54d36SAndroid Build Coastguard Worker 			addr_str
948*48a54d36SAndroid Build Coastguard Worker 		);
949*48a54d36SAndroid Build Coastguard Worker 
950*48a54d36SAndroid Build Coastguard Worker 	result->hostent->h_addrtype = af;
951*48a54d36SAndroid Build Coastguard Worker 	result->hostent->h_length = addr_len;
952*48a54d36SAndroid Build Coastguard Worker 
953*48a54d36SAndroid Build Coastguard Worker 	// Query address becomes "address" in result.
954*48a54d36SAndroid Build Coastguard Worker 	if (! add_address_to_buffer (result, addr, addr_len))
955*48a54d36SAndroid Build Coastguard Worker 	{
956*48a54d36SAndroid Build Coastguard Worker 		return result->status;
957*48a54d36SAndroid Build Coastguard Worker 	}
958*48a54d36SAndroid Build Coastguard Worker 
959*48a54d36SAndroid Build Coastguard Worker 	result->hostent->h_name [0] = 0;
960*48a54d36SAndroid Build Coastguard Worker 
961*48a54d36SAndroid Build Coastguard Worker 	errcode =
962*48a54d36SAndroid Build Coastguard Worker 		DNSServiceQueryRecord (
963*48a54d36SAndroid Build Coastguard Worker 			&sdref,
964*48a54d36SAndroid Build Coastguard Worker 			kDNSServiceFlagsForceMulticast,		// force multicast query
965*48a54d36SAndroid Build Coastguard Worker 			kDNSServiceInterfaceIndexAny,	// all interfaces
966*48a54d36SAndroid Build Coastguard Worker 			addr_str,	// address string to query for
967*48a54d36SAndroid Build Coastguard Worker 			kDNSServiceType_PTR,	// pointer RRs
968*48a54d36SAndroid Build Coastguard Worker 			kDNSServiceClass_IN,	// internet class records
969*48a54d36SAndroid Build Coastguard Worker 			mdns_lookup_callback,	// callback
970*48a54d36SAndroid Build Coastguard Worker 			result		// Context - result buffer
971*48a54d36SAndroid Build Coastguard Worker 		);
972*48a54d36SAndroid Build Coastguard Worker 
973*48a54d36SAndroid Build Coastguard Worker 	if (errcode)
974*48a54d36SAndroid Build Coastguard Worker 	{
975*48a54d36SAndroid Build Coastguard Worker 		syslog (LOG_WARNING,
976*48a54d36SAndroid Build Coastguard Worker 			"mdns: Failed to initialise mdns lookup, error %d",
977*48a54d36SAndroid Build Coastguard Worker 			errcode
978*48a54d36SAndroid Build Coastguard Worker 		);
979*48a54d36SAndroid Build Coastguard Worker 		return set_err_mdns_failed (result);
980*48a54d36SAndroid Build Coastguard Worker 	}
981*48a54d36SAndroid Build Coastguard Worker 
982*48a54d36SAndroid Build Coastguard Worker 	status = handle_events (sdref, result, addr_str);
983*48a54d36SAndroid Build Coastguard Worker 	DNSServiceRefDeallocate (sdref);
984*48a54d36SAndroid Build Coastguard Worker 	return status;
985*48a54d36SAndroid Build Coastguard Worker }
986*48a54d36SAndroid Build Coastguard Worker 
987*48a54d36SAndroid Build Coastguard Worker 
988*48a54d36SAndroid Build Coastguard Worker /*
989*48a54d36SAndroid Build Coastguard Worker 	Wait on result of callback, and process it when it arrives.
990*48a54d36SAndroid Build Coastguard Worker 
991*48a54d36SAndroid Build Coastguard Worker 	Parameters
992*48a54d36SAndroid Build Coastguard Worker 		sdref
993*48a54d36SAndroid Build Coastguard Worker 			dns-sd reference
994*48a54d36SAndroid Build Coastguard Worker 		result
995*48a54d36SAndroid Build Coastguard Worker 			Initialised 'result' data structure.
996*48a54d36SAndroid Build Coastguard Worker 		str
997*48a54d36SAndroid Build Coastguard Worker 			lookup string, used for status/error reporting.
998*48a54d36SAndroid Build Coastguard Worker  */
999*48a54d36SAndroid Build Coastguard Worker static nss_status
handle_events(DNSServiceRef sdref,result_map_t * result,const char * str)1000*48a54d36SAndroid Build Coastguard Worker handle_events (DNSServiceRef sdref, result_map_t * result, const char * str)
1001*48a54d36SAndroid Build Coastguard Worker {
1002*48a54d36SAndroid Build Coastguard Worker 	int dns_sd_fd = DNSServiceRefSockFD(sdref);
1003*48a54d36SAndroid Build Coastguard Worker 	int nfds = dns_sd_fd + 1;
1004*48a54d36SAndroid Build Coastguard Worker 	fd_set readfds;
1005*48a54d36SAndroid Build Coastguard Worker 	struct timeval tv;
1006*48a54d36SAndroid Build Coastguard Worker 	int select_result;
1007*48a54d36SAndroid Build Coastguard Worker 
1008*48a54d36SAndroid Build Coastguard Worker 	while (! result->done)
1009*48a54d36SAndroid Build Coastguard Worker 	{
1010*48a54d36SAndroid Build Coastguard Worker 		FD_ZERO(&readfds);
1011*48a54d36SAndroid Build Coastguard Worker 		FD_SET(dns_sd_fd, &readfds);
1012*48a54d36SAndroid Build Coastguard Worker 
1013*48a54d36SAndroid Build Coastguard Worker 		tv = k_select_time;
1014*48a54d36SAndroid Build Coastguard Worker 
1015*48a54d36SAndroid Build Coastguard Worker 		select_result =
1016*48a54d36SAndroid Build Coastguard Worker 			select (nfds, &readfds, (fd_set*)NULL, (fd_set*)NULL, &tv);
1017*48a54d36SAndroid Build Coastguard Worker 		if (select_result > 0)
1018*48a54d36SAndroid Build Coastguard Worker 		{
1019*48a54d36SAndroid Build Coastguard Worker 			if (FD_ISSET(dns_sd_fd, &readfds))
1020*48a54d36SAndroid Build Coastguard Worker 			{
1021*48a54d36SAndroid Build Coastguard Worker 				if (MDNS_VERBOSE)
1022*48a54d36SAndroid Build Coastguard Worker 					syslog (LOG_DEBUG,
1023*48a54d36SAndroid Build Coastguard Worker 						"mdns: Reply received for %s",
1024*48a54d36SAndroid Build Coastguard Worker 						str
1025*48a54d36SAndroid Build Coastguard Worker 					);
1026*48a54d36SAndroid Build Coastguard Worker 				DNSServiceProcessResult(sdref);
1027*48a54d36SAndroid Build Coastguard Worker 			}
1028*48a54d36SAndroid Build Coastguard Worker 			else
1029*48a54d36SAndroid Build Coastguard Worker 			{
1030*48a54d36SAndroid Build Coastguard Worker 				syslog (LOG_WARNING,
1031*48a54d36SAndroid Build Coastguard Worker 					"mdns: Unexpected return from select on lookup of %s",
1032*48a54d36SAndroid Build Coastguard Worker 					str
1033*48a54d36SAndroid Build Coastguard Worker 				);
1034*48a54d36SAndroid Build Coastguard Worker 			}
1035*48a54d36SAndroid Build Coastguard Worker 		}
1036*48a54d36SAndroid Build Coastguard Worker 		else
1037*48a54d36SAndroid Build Coastguard Worker 		{
1038*48a54d36SAndroid Build Coastguard Worker 			// Terminate loop due to timer expiry
1039*48a54d36SAndroid Build Coastguard Worker 			if (MDNS_VERBOSE)
1040*48a54d36SAndroid Build Coastguard Worker 				syslog (LOG_DEBUG,
1041*48a54d36SAndroid Build Coastguard Worker 					"mdns: %s not found - timer expired",
1042*48a54d36SAndroid Build Coastguard Worker 					str
1043*48a54d36SAndroid Build Coastguard Worker 				);
1044*48a54d36SAndroid Build Coastguard Worker 			set_err_notfound (result);
1045*48a54d36SAndroid Build Coastguard Worker 			break;
1046*48a54d36SAndroid Build Coastguard Worker 		}
1047*48a54d36SAndroid Build Coastguard Worker 	}
1048*48a54d36SAndroid Build Coastguard Worker 
1049*48a54d36SAndroid Build Coastguard Worker 	return result->status;
1050*48a54d36SAndroid Build Coastguard Worker }
1051*48a54d36SAndroid Build Coastguard Worker 
1052*48a54d36SAndroid Build Coastguard Worker 
1053*48a54d36SAndroid Build Coastguard Worker /*
1054*48a54d36SAndroid Build Coastguard Worker 	Examine incoming data and add to relevant fields in result structure.
1055*48a54d36SAndroid Build Coastguard Worker 	This routine is called from DNSServiceProcessResult where appropriate.
1056*48a54d36SAndroid Build Coastguard Worker  */
1057*48a54d36SAndroid Build Coastguard Worker void
mdns_lookup_callback(DNSServiceRef sdref,DNSServiceFlags flags,uint32_t interface_index,DNSServiceErrorType error_code,const char * fullname,uint16_t rrtype,uint16_t rrclass,uint16_t rdlen,const void * rdata,uint32_t ttl,void * context)1058*48a54d36SAndroid Build Coastguard Worker mdns_lookup_callback
1059*48a54d36SAndroid Build Coastguard Worker (
1060*48a54d36SAndroid Build Coastguard Worker 	DNSServiceRef		sdref,
1061*48a54d36SAndroid Build Coastguard Worker 	DNSServiceFlags		flags,
1062*48a54d36SAndroid Build Coastguard Worker 	uint32_t			interface_index,
1063*48a54d36SAndroid Build Coastguard Worker 	DNSServiceErrorType	error_code,
1064*48a54d36SAndroid Build Coastguard Worker 	const char			*fullname,
1065*48a54d36SAndroid Build Coastguard Worker 	uint16_t			rrtype,
1066*48a54d36SAndroid Build Coastguard Worker 	uint16_t			rrclass,
1067*48a54d36SAndroid Build Coastguard Worker 	uint16_t			rdlen,
1068*48a54d36SAndroid Build Coastguard Worker 	const void			*rdata,
1069*48a54d36SAndroid Build Coastguard Worker 	uint32_t			ttl,
1070*48a54d36SAndroid Build Coastguard Worker 	void				*context
1071*48a54d36SAndroid Build Coastguard Worker )
1072*48a54d36SAndroid Build Coastguard Worker {
1073*48a54d36SAndroid Build Coastguard Worker 	// A single record is received
1074*48a54d36SAndroid Build Coastguard Worker 
1075*48a54d36SAndroid Build Coastguard Worker 	result_map_t * result = (result_map_t *) context;
1076*48a54d36SAndroid Build Coastguard Worker 
1077*48a54d36SAndroid Build Coastguard Worker 	(void)sdref; // Unused
1078*48a54d36SAndroid Build Coastguard Worker 	(void)interface_index; // Unused
1079*48a54d36SAndroid Build Coastguard Worker 	(void)ttl; // Unused
1080*48a54d36SAndroid Build Coastguard Worker 
1081*48a54d36SAndroid Build Coastguard Worker 	if (! (flags & kDNSServiceFlagsMoreComing) )
1082*48a54d36SAndroid Build Coastguard Worker 	{
1083*48a54d36SAndroid Build Coastguard Worker 		result->done = 1;
1084*48a54d36SAndroid Build Coastguard Worker 	}
1085*48a54d36SAndroid Build Coastguard Worker 
1086*48a54d36SAndroid Build Coastguard Worker 	if (error_code == kDNSServiceErr_NoError)
1087*48a54d36SAndroid Build Coastguard Worker 	{
1088*48a54d36SAndroid Build Coastguard Worker 		ns_type_t expected_rr_type =
1089*48a54d36SAndroid Build Coastguard Worker 			af_to_rr (result->hostent->h_addrtype);
1090*48a54d36SAndroid Build Coastguard Worker 
1091*48a54d36SAndroid Build Coastguard Worker 		// Idiot check class
1092*48a54d36SAndroid Build Coastguard Worker 		if (rrclass != C_IN)
1093*48a54d36SAndroid Build Coastguard Worker 		{
1094*48a54d36SAndroid Build Coastguard Worker 			syslog (LOG_WARNING,
1095*48a54d36SAndroid Build Coastguard Worker 				"mdns: Received bad RR class: expected %d (%s),"
1096*48a54d36SAndroid Build Coastguard Worker 				" got %d (%s), RR type %d (%s)",
1097*48a54d36SAndroid Build Coastguard Worker 				C_IN,
1098*48a54d36SAndroid Build Coastguard Worker 				ns_class_to_str (C_IN),
1099*48a54d36SAndroid Build Coastguard Worker 				rrclass,
1100*48a54d36SAndroid Build Coastguard Worker 				ns_class_to_str (rrclass),
1101*48a54d36SAndroid Build Coastguard Worker 				rrtype,
1102*48a54d36SAndroid Build Coastguard Worker 				ns_type_to_str (rrtype)
1103*48a54d36SAndroid Build Coastguard Worker 			);
1104*48a54d36SAndroid Build Coastguard Worker 			return;
1105*48a54d36SAndroid Build Coastguard Worker 		}
1106*48a54d36SAndroid Build Coastguard Worker 
1107*48a54d36SAndroid Build Coastguard Worker 		// If a PTR
1108*48a54d36SAndroid Build Coastguard Worker 		if (rrtype == kDNSServiceType_PTR)
1109*48a54d36SAndroid Build Coastguard Worker 		{
1110*48a54d36SAndroid Build Coastguard Worker 			if (callback_body_ptr (fullname, result, rdlen, rdata) < 0)
1111*48a54d36SAndroid Build Coastguard Worker 				return;
1112*48a54d36SAndroid Build Coastguard Worker 		}
1113*48a54d36SAndroid Build Coastguard Worker 		else if (rrtype == expected_rr_type)
1114*48a54d36SAndroid Build Coastguard Worker 		{
1115*48a54d36SAndroid Build Coastguard Worker 			if (!
1116*48a54d36SAndroid Build Coastguard Worker 				add_hostname_or_alias (
1117*48a54d36SAndroid Build Coastguard Worker 					result,
1118*48a54d36SAndroid Build Coastguard Worker 					fullname,
1119*48a54d36SAndroid Build Coastguard Worker 					strlen (fullname)
1120*48a54d36SAndroid Build Coastguard Worker 				)
1121*48a54d36SAndroid Build Coastguard Worker 			)
1122*48a54d36SAndroid Build Coastguard Worker 			{
1123*48a54d36SAndroid Build Coastguard Worker 				result->done = 1;
1124*48a54d36SAndroid Build Coastguard Worker 				return;
1125*48a54d36SAndroid Build Coastguard Worker 					// Abort on error
1126*48a54d36SAndroid Build Coastguard Worker 			}
1127*48a54d36SAndroid Build Coastguard Worker 
1128*48a54d36SAndroid Build Coastguard Worker 			if (! add_address_to_buffer (result, rdata, rdlen) )
1129*48a54d36SAndroid Build Coastguard Worker 			{
1130*48a54d36SAndroid Build Coastguard Worker 				result->done = 1;
1131*48a54d36SAndroid Build Coastguard Worker 				return;
1132*48a54d36SAndroid Build Coastguard Worker 					// Abort on error
1133*48a54d36SAndroid Build Coastguard Worker 			}
1134*48a54d36SAndroid Build Coastguard Worker 		}
1135*48a54d36SAndroid Build Coastguard Worker 		else
1136*48a54d36SAndroid Build Coastguard Worker 		{
1137*48a54d36SAndroid Build Coastguard Worker 			syslog (LOG_WARNING,
1138*48a54d36SAndroid Build Coastguard Worker 				"mdns: Received bad RR type: expected %d (%s),"
1139*48a54d36SAndroid Build Coastguard Worker 				" got %d (%s)",
1140*48a54d36SAndroid Build Coastguard Worker 				expected_rr_type,
1141*48a54d36SAndroid Build Coastguard Worker 				ns_type_to_str (expected_rr_type),
1142*48a54d36SAndroid Build Coastguard Worker 				rrtype,
1143*48a54d36SAndroid Build Coastguard Worker 				ns_type_to_str (rrtype)
1144*48a54d36SAndroid Build Coastguard Worker 			);
1145*48a54d36SAndroid Build Coastguard Worker 			return;
1146*48a54d36SAndroid Build Coastguard Worker 		}
1147*48a54d36SAndroid Build Coastguard Worker 
1148*48a54d36SAndroid Build Coastguard Worker 		if (result->status != NSS_STATUS_SUCCESS)
1149*48a54d36SAndroid Build Coastguard Worker 			set_err_success (result);
1150*48a54d36SAndroid Build Coastguard Worker 	}
1151*48a54d36SAndroid Build Coastguard Worker 	else
1152*48a54d36SAndroid Build Coastguard Worker 	{
1153*48a54d36SAndroid Build Coastguard Worker 		// For now, dump message to syslog and continue
1154*48a54d36SAndroid Build Coastguard Worker 		syslog (LOG_WARNING,
1155*48a54d36SAndroid Build Coastguard Worker 			"mdns: callback returned error %d",
1156*48a54d36SAndroid Build Coastguard Worker 			error_code
1157*48a54d36SAndroid Build Coastguard Worker 		);
1158*48a54d36SAndroid Build Coastguard Worker 	}
1159*48a54d36SAndroid Build Coastguard Worker }
1160*48a54d36SAndroid Build Coastguard Worker 
1161*48a54d36SAndroid Build Coastguard Worker static int
callback_body_ptr(const char * fullname,result_map_t * result,int rdlen,const void * rdata)1162*48a54d36SAndroid Build Coastguard Worker callback_body_ptr (
1163*48a54d36SAndroid Build Coastguard Worker 	const char * fullname,
1164*48a54d36SAndroid Build Coastguard Worker 	result_map_t * result,
1165*48a54d36SAndroid Build Coastguard Worker 	int rdlen,
1166*48a54d36SAndroid Build Coastguard Worker 	const void * rdata
1167*48a54d36SAndroid Build Coastguard Worker )
1168*48a54d36SAndroid Build Coastguard Worker {
1169*48a54d36SAndroid Build Coastguard Worker 	char result_name [k_hostname_maxlen + 1];
1170*48a54d36SAndroid Build Coastguard Worker 	int rv;
1171*48a54d36SAndroid Build Coastguard Worker 
1172*48a54d36SAndroid Build Coastguard Worker 	// Fullname should be .in-addr.arpa or equivalent, which we're
1173*48a54d36SAndroid Build Coastguard Worker 	// not interested in.  Ignore it.
1174*48a54d36SAndroid Build Coastguard Worker 
1175*48a54d36SAndroid Build Coastguard Worker 	rv = dns_rdata_to_name (rdata, rdlen, result_name, k_hostname_maxlen);
1176*48a54d36SAndroid Build Coastguard Worker 	if (rv < 0)
1177*48a54d36SAndroid Build Coastguard Worker 	{
1178*48a54d36SAndroid Build Coastguard Worker 		const char * errmsg;
1179*48a54d36SAndroid Build Coastguard Worker 
1180*48a54d36SAndroid Build Coastguard Worker 		switch (rv)
1181*48a54d36SAndroid Build Coastguard Worker 		{
1182*48a54d36SAndroid Build Coastguard Worker 		  case DNS_RDATA_TO_NAME_BAD_FORMAT:
1183*48a54d36SAndroid Build Coastguard Worker 			errmsg = "mdns: PTR '%s' result badly formatted ('%s...')";
1184*48a54d36SAndroid Build Coastguard Worker 			break;
1185*48a54d36SAndroid Build Coastguard Worker 
1186*48a54d36SAndroid Build Coastguard Worker 		  case DNS_RDATA_TO_NAME_TOO_LONG:
1187*48a54d36SAndroid Build Coastguard Worker 			errmsg = "mdns: PTR '%s' result too long ('%s...')";
1188*48a54d36SAndroid Build Coastguard Worker 			break;
1189*48a54d36SAndroid Build Coastguard Worker 
1190*48a54d36SAndroid Build Coastguard Worker 		  case DNS_RDATA_TO_NAME_PTR:
1191*48a54d36SAndroid Build Coastguard Worker 			errmsg = "mdns: PTR '%s' result contained pointer ('%s...')";
1192*48a54d36SAndroid Build Coastguard Worker 			break;
1193*48a54d36SAndroid Build Coastguard Worker 
1194*48a54d36SAndroid Build Coastguard Worker 		  default:
1195*48a54d36SAndroid Build Coastguard Worker 			errmsg = "mdns: PTR '%s' result conversion failed ('%s...')";
1196*48a54d36SAndroid Build Coastguard Worker 		}
1197*48a54d36SAndroid Build Coastguard Worker 
1198*48a54d36SAndroid Build Coastguard Worker 		syslog (LOG_WARNING,
1199*48a54d36SAndroid Build Coastguard Worker 			errmsg,
1200*48a54d36SAndroid Build Coastguard Worker 			fullname,
1201*48a54d36SAndroid Build Coastguard Worker 			result_name
1202*48a54d36SAndroid Build Coastguard Worker 		);
1203*48a54d36SAndroid Build Coastguard Worker 
1204*48a54d36SAndroid Build Coastguard Worker 		return -1;
1205*48a54d36SAndroid Build Coastguard Worker 	}
1206*48a54d36SAndroid Build Coastguard Worker 
1207*48a54d36SAndroid Build Coastguard Worker 	if (MDNS_VERBOSE)
1208*48a54d36SAndroid Build Coastguard Worker 	{
1209*48a54d36SAndroid Build Coastguard Worker 		syslog (LOG_DEBUG,
1210*48a54d36SAndroid Build Coastguard Worker 			"mdns: PTR '%s' resolved to '%s'",
1211*48a54d36SAndroid Build Coastguard Worker 			fullname,
1212*48a54d36SAndroid Build Coastguard Worker 			result_name
1213*48a54d36SAndroid Build Coastguard Worker 		);
1214*48a54d36SAndroid Build Coastguard Worker 	}
1215*48a54d36SAndroid Build Coastguard Worker 
1216*48a54d36SAndroid Build Coastguard Worker 	// Data should be a hostname
1217*48a54d36SAndroid Build Coastguard Worker 	if (!
1218*48a54d36SAndroid Build Coastguard Worker 		add_hostname_or_alias (
1219*48a54d36SAndroid Build Coastguard Worker 			result,
1220*48a54d36SAndroid Build Coastguard Worker 			result_name,
1221*48a54d36SAndroid Build Coastguard Worker 			rv
1222*48a54d36SAndroid Build Coastguard Worker 		)
1223*48a54d36SAndroid Build Coastguard Worker 	)
1224*48a54d36SAndroid Build Coastguard Worker 	{
1225*48a54d36SAndroid Build Coastguard Worker 		result->done = 1;
1226*48a54d36SAndroid Build Coastguard Worker 		return -1;
1227*48a54d36SAndroid Build Coastguard Worker 	}
1228*48a54d36SAndroid Build Coastguard Worker 
1229*48a54d36SAndroid Build Coastguard Worker 	return 0;
1230*48a54d36SAndroid Build Coastguard Worker }
1231*48a54d36SAndroid Build Coastguard Worker 
1232*48a54d36SAndroid Build Coastguard Worker 
1233*48a54d36SAndroid Build Coastguard Worker /*
1234*48a54d36SAndroid Build Coastguard Worker 	Add an address to the buffer.
1235*48a54d36SAndroid Build Coastguard Worker 
1236*48a54d36SAndroid Build Coastguard Worker 	Parameter
1237*48a54d36SAndroid Build Coastguard Worker 		result
1238*48a54d36SAndroid Build Coastguard Worker 			Result structure to write to
1239*48a54d36SAndroid Build Coastguard Worker 		data
1240*48a54d36SAndroid Build Coastguard Worker 			Incoming address data buffer
1241*48a54d36SAndroid Build Coastguard Worker 			Must be 'int' aligned
1242*48a54d36SAndroid Build Coastguard Worker 		len
1243*48a54d36SAndroid Build Coastguard Worker 			Length of data buffer (in bytes)
1244*48a54d36SAndroid Build Coastguard Worker 			Must match data alignment
1245*48a54d36SAndroid Build Coastguard Worker 
1246*48a54d36SAndroid Build Coastguard Worker 	Result
1247*48a54d36SAndroid Build Coastguard Worker 		Pointer to start of newly written data,
1248*48a54d36SAndroid Build Coastguard Worker 		or NULL on error.
1249*48a54d36SAndroid Build Coastguard Worker 		If address already exists in buffer, returns pointer to that instead.
1250*48a54d36SAndroid Build Coastguard Worker  */
1251*48a54d36SAndroid Build Coastguard Worker static void *
add_address_to_buffer(result_map_t * result,const void * data,int len)1252*48a54d36SAndroid Build Coastguard Worker add_address_to_buffer (result_map_t * result, const void * data, int len)
1253*48a54d36SAndroid Build Coastguard Worker {
1254*48a54d36SAndroid Build Coastguard Worker 	int new_addr;
1255*48a54d36SAndroid Build Coastguard Worker 	void * start;
1256*48a54d36SAndroid Build Coastguard Worker 	void * temp;
1257*48a54d36SAndroid Build Coastguard Worker 
1258*48a54d36SAndroid Build Coastguard Worker 	if ((temp = contains_address (result, data, len)))
1259*48a54d36SAndroid Build Coastguard Worker 	{
1260*48a54d36SAndroid Build Coastguard Worker 		return temp;
1261*48a54d36SAndroid Build Coastguard Worker 	}
1262*48a54d36SAndroid Build Coastguard Worker 
1263*48a54d36SAndroid Build Coastguard Worker 	if (result->addrs_count >= k_addrs_max)
1264*48a54d36SAndroid Build Coastguard Worker 	{
1265*48a54d36SAndroid Build Coastguard Worker 		// Not enough addr slots
1266*48a54d36SAndroid Build Coastguard Worker 		set_err_internal_resource_full (result);
1267*48a54d36SAndroid Build Coastguard Worker 		syslog (LOG_ERR,
1268*48a54d36SAndroid Build Coastguard Worker 			"mdns: Internal address buffer full; increase size"
1269*48a54d36SAndroid Build Coastguard Worker 		);
1270*48a54d36SAndroid Build Coastguard Worker 		return NULL;
1271*48a54d36SAndroid Build Coastguard Worker 	}
1272*48a54d36SAndroid Build Coastguard Worker 
1273*48a54d36SAndroid Build Coastguard Worker 	// Idiot check
1274*48a54d36SAndroid Build Coastguard Worker 	if (len != result->hostent->h_length)
1275*48a54d36SAndroid Build Coastguard Worker 	{
1276*48a54d36SAndroid Build Coastguard Worker 		syslog (LOG_WARNING,
1277*48a54d36SAndroid Build Coastguard Worker 			"mdns: Unexpected rdata length for address.  Expected %d, got %d",
1278*48a54d36SAndroid Build Coastguard Worker 			result->hostent->h_length,
1279*48a54d36SAndroid Build Coastguard Worker 			len
1280*48a54d36SAndroid Build Coastguard Worker 		);
1281*48a54d36SAndroid Build Coastguard Worker 		// XXX And continue for now.
1282*48a54d36SAndroid Build Coastguard Worker 	}
1283*48a54d36SAndroid Build Coastguard Worker 
1284*48a54d36SAndroid Build Coastguard Worker 	new_addr = result->addr_idx + len;
1285*48a54d36SAndroid Build Coastguard Worker 
1286*48a54d36SAndroid Build Coastguard Worker 	if (new_addr > result->alias_idx)
1287*48a54d36SAndroid Build Coastguard Worker 	{
1288*48a54d36SAndroid Build Coastguard Worker 		// Not enough room
1289*48a54d36SAndroid Build Coastguard Worker 		set_err_buf_too_small (result);
1290*48a54d36SAndroid Build Coastguard Worker 		if (MDNS_VERBOSE)
1291*48a54d36SAndroid Build Coastguard Worker 			syslog (LOG_DEBUG,
1292*48a54d36SAndroid Build Coastguard Worker 				"mdns: Ran out of buffer when adding address %d",
1293*48a54d36SAndroid Build Coastguard Worker 				result->addrs_count + 1
1294*48a54d36SAndroid Build Coastguard Worker 			);
1295*48a54d36SAndroid Build Coastguard Worker 		return NULL;
1296*48a54d36SAndroid Build Coastguard Worker 	}
1297*48a54d36SAndroid Build Coastguard Worker 
1298*48a54d36SAndroid Build Coastguard Worker 	start = result->buffer + result->addr_idx;
1299*48a54d36SAndroid Build Coastguard Worker 	memcpy (start, data, len);
1300*48a54d36SAndroid Build Coastguard Worker 	result->addr_idx = new_addr;
1301*48a54d36SAndroid Build Coastguard Worker 	result->header->addrs [result->addrs_count] = start;
1302*48a54d36SAndroid Build Coastguard Worker 	result->addrs_count ++;
1303*48a54d36SAndroid Build Coastguard Worker 	result->header->addrs [result->addrs_count] = NULL;
1304*48a54d36SAndroid Build Coastguard Worker 
1305*48a54d36SAndroid Build Coastguard Worker 	return start;
1306*48a54d36SAndroid Build Coastguard Worker }
1307*48a54d36SAndroid Build Coastguard Worker 
1308*48a54d36SAndroid Build Coastguard Worker 
1309*48a54d36SAndroid Build Coastguard Worker static void *
contains_address(result_map_t * result,const void * data,int len)1310*48a54d36SAndroid Build Coastguard Worker contains_address (result_map_t * result, const void * data, int len)
1311*48a54d36SAndroid Build Coastguard Worker {
1312*48a54d36SAndroid Build Coastguard Worker 	int i;
1313*48a54d36SAndroid Build Coastguard Worker 
1314*48a54d36SAndroid Build Coastguard Worker 	// Idiot check
1315*48a54d36SAndroid Build Coastguard Worker 	if (len != result->hostent->h_length)
1316*48a54d36SAndroid Build Coastguard Worker 	{
1317*48a54d36SAndroid Build Coastguard Worker 		syslog (LOG_WARNING,
1318*48a54d36SAndroid Build Coastguard Worker 			"mdns: Unexpected rdata length for address.  Expected %d, got %d",
1319*48a54d36SAndroid Build Coastguard Worker 			result->hostent->h_length,
1320*48a54d36SAndroid Build Coastguard Worker 			len
1321*48a54d36SAndroid Build Coastguard Worker 		);
1322*48a54d36SAndroid Build Coastguard Worker 		// XXX And continue for now.
1323*48a54d36SAndroid Build Coastguard Worker 	}
1324*48a54d36SAndroid Build Coastguard Worker 
1325*48a54d36SAndroid Build Coastguard Worker 	for (i = 0; result->header->addrs [i]; i++)
1326*48a54d36SAndroid Build Coastguard Worker 	{
1327*48a54d36SAndroid Build Coastguard Worker 		if (memcmp (result->header->addrs [i], data, len) == 0)
1328*48a54d36SAndroid Build Coastguard Worker 		{
1329*48a54d36SAndroid Build Coastguard Worker 			return result->header->addrs [i];
1330*48a54d36SAndroid Build Coastguard Worker 		}
1331*48a54d36SAndroid Build Coastguard Worker 	}
1332*48a54d36SAndroid Build Coastguard Worker 
1333*48a54d36SAndroid Build Coastguard Worker 	return NULL;
1334*48a54d36SAndroid Build Coastguard Worker }
1335*48a54d36SAndroid Build Coastguard Worker 
1336*48a54d36SAndroid Build Coastguard Worker 
1337*48a54d36SAndroid Build Coastguard Worker /*
1338*48a54d36SAndroid Build Coastguard Worker 	Add an alias to the buffer.
1339*48a54d36SAndroid Build Coastguard Worker 
1340*48a54d36SAndroid Build Coastguard Worker 	Parameter
1341*48a54d36SAndroid Build Coastguard Worker 		result
1342*48a54d36SAndroid Build Coastguard Worker 			Result structure to write to
1343*48a54d36SAndroid Build Coastguard Worker 		data
1344*48a54d36SAndroid Build Coastguard Worker 			Incoming alias (null terminated)
1345*48a54d36SAndroid Build Coastguard Worker 		len
1346*48a54d36SAndroid Build Coastguard Worker 			Length of data buffer (in bytes), including trailing null
1347*48a54d36SAndroid Build Coastguard Worker 
1348*48a54d36SAndroid Build Coastguard Worker 	Result
1349*48a54d36SAndroid Build Coastguard Worker 		Pointer to start of newly written data,
1350*48a54d36SAndroid Build Coastguard Worker 		or NULL on error
1351*48a54d36SAndroid Build Coastguard Worker 		If alias already exists in buffer, returns pointer to that instead.
1352*48a54d36SAndroid Build Coastguard Worker  */
1353*48a54d36SAndroid Build Coastguard Worker static char *
add_alias_to_buffer(result_map_t * result,const char * data,int len)1354*48a54d36SAndroid Build Coastguard Worker add_alias_to_buffer (result_map_t * result, const char * data, int len)
1355*48a54d36SAndroid Build Coastguard Worker {
1356*48a54d36SAndroid Build Coastguard Worker 	int new_alias;
1357*48a54d36SAndroid Build Coastguard Worker 	char * start;
1358*48a54d36SAndroid Build Coastguard Worker 	char * temp;
1359*48a54d36SAndroid Build Coastguard Worker 
1360*48a54d36SAndroid Build Coastguard Worker 	if ((temp = contains_alias (result, data)))
1361*48a54d36SAndroid Build Coastguard Worker 	{
1362*48a54d36SAndroid Build Coastguard Worker 		return temp;
1363*48a54d36SAndroid Build Coastguard Worker 	}
1364*48a54d36SAndroid Build Coastguard Worker 
1365*48a54d36SAndroid Build Coastguard Worker 	if (result->aliases_count >= k_aliases_max)
1366*48a54d36SAndroid Build Coastguard Worker 	{
1367*48a54d36SAndroid Build Coastguard Worker 		// Not enough alias slots
1368*48a54d36SAndroid Build Coastguard Worker 		set_err_internal_resource_full (result);
1369*48a54d36SAndroid Build Coastguard Worker 		syslog (LOG_ERR,
1370*48a54d36SAndroid Build Coastguard Worker 			"mdns: Internal alias buffer full; increase size"
1371*48a54d36SAndroid Build Coastguard Worker 		);
1372*48a54d36SAndroid Build Coastguard Worker 		return NULL;
1373*48a54d36SAndroid Build Coastguard Worker 	}
1374*48a54d36SAndroid Build Coastguard Worker 
1375*48a54d36SAndroid Build Coastguard Worker 	new_alias = result->alias_idx - len;
1376*48a54d36SAndroid Build Coastguard Worker 
1377*48a54d36SAndroid Build Coastguard Worker 	if (new_alias < result->addr_idx)
1378*48a54d36SAndroid Build Coastguard Worker 	{
1379*48a54d36SAndroid Build Coastguard Worker 		// Not enough room
1380*48a54d36SAndroid Build Coastguard Worker 		set_err_buf_too_small (result);
1381*48a54d36SAndroid Build Coastguard Worker 		if (MDNS_VERBOSE)
1382*48a54d36SAndroid Build Coastguard Worker 			syslog (LOG_DEBUG,
1383*48a54d36SAndroid Build Coastguard Worker 				"mdns: Ran out of buffer when adding alias %d",
1384*48a54d36SAndroid Build Coastguard Worker 				result->aliases_count + 1
1385*48a54d36SAndroid Build Coastguard Worker 			);
1386*48a54d36SAndroid Build Coastguard Worker 		return NULL;
1387*48a54d36SAndroid Build Coastguard Worker 	}
1388*48a54d36SAndroid Build Coastguard Worker 
1389*48a54d36SAndroid Build Coastguard Worker 	start = result->buffer + new_alias;
1390*48a54d36SAndroid Build Coastguard Worker 	memcpy (start, data, len);
1391*48a54d36SAndroid Build Coastguard Worker 	result->alias_idx = new_alias;
1392*48a54d36SAndroid Build Coastguard Worker 	result->header->aliases [result->aliases_count] = start;
1393*48a54d36SAndroid Build Coastguard Worker 	result->aliases_count ++;
1394*48a54d36SAndroid Build Coastguard Worker 	result->header->aliases [result->aliases_count] = NULL;
1395*48a54d36SAndroid Build Coastguard Worker 
1396*48a54d36SAndroid Build Coastguard Worker 	return start;
1397*48a54d36SAndroid Build Coastguard Worker }
1398*48a54d36SAndroid Build Coastguard Worker 
1399*48a54d36SAndroid Build Coastguard Worker 
1400*48a54d36SAndroid Build Coastguard Worker static char *
contains_alias(result_map_t * result,const char * alias)1401*48a54d36SAndroid Build Coastguard Worker contains_alias (result_map_t * result, const char * alias)
1402*48a54d36SAndroid Build Coastguard Worker {
1403*48a54d36SAndroid Build Coastguard Worker 	int i;
1404*48a54d36SAndroid Build Coastguard Worker 
1405*48a54d36SAndroid Build Coastguard Worker 	for (i = 0; result->header->aliases [i]; i++)
1406*48a54d36SAndroid Build Coastguard Worker 	{
1407*48a54d36SAndroid Build Coastguard Worker 		if (strcmp (result->header->aliases [i], alias) == 0)
1408*48a54d36SAndroid Build Coastguard Worker 		{
1409*48a54d36SAndroid Build Coastguard Worker 			return result->header->aliases [i];
1410*48a54d36SAndroid Build Coastguard Worker 		}
1411*48a54d36SAndroid Build Coastguard Worker 	}
1412*48a54d36SAndroid Build Coastguard Worker 
1413*48a54d36SAndroid Build Coastguard Worker 	return NULL;
1414*48a54d36SAndroid Build Coastguard Worker }
1415*48a54d36SAndroid Build Coastguard Worker 
1416*48a54d36SAndroid Build Coastguard Worker 
1417*48a54d36SAndroid Build Coastguard Worker /*
1418*48a54d36SAndroid Build Coastguard Worker 	Add fully qualified hostname to result.
1419*48a54d36SAndroid Build Coastguard Worker 
1420*48a54d36SAndroid Build Coastguard Worker 	Parameter
1421*48a54d36SAndroid Build Coastguard Worker 		result
1422*48a54d36SAndroid Build Coastguard Worker 			Result structure to write to
1423*48a54d36SAndroid Build Coastguard Worker 		fullname
1424*48a54d36SAndroid Build Coastguard Worker 			Fully qualified hostname
1425*48a54d36SAndroid Build Coastguard Worker 
1426*48a54d36SAndroid Build Coastguard Worker 	Result
1427*48a54d36SAndroid Build Coastguard Worker 		Pointer to start of hostname buffer,
1428*48a54d36SAndroid Build Coastguard Worker 		or NULL on error (usually hostname too long)
1429*48a54d36SAndroid Build Coastguard Worker  */
1430*48a54d36SAndroid Build Coastguard Worker 
1431*48a54d36SAndroid Build Coastguard Worker static char *
add_hostname_len(result_map_t * result,const char * fullname,int len)1432*48a54d36SAndroid Build Coastguard Worker add_hostname_len (result_map_t * result, const char * fullname, int len)
1433*48a54d36SAndroid Build Coastguard Worker {
1434*48a54d36SAndroid Build Coastguard Worker 	if (len >= k_hostname_maxlen)
1435*48a54d36SAndroid Build Coastguard Worker 	{
1436*48a54d36SAndroid Build Coastguard Worker 		set_err_bad_hostname (result);
1437*48a54d36SAndroid Build Coastguard Worker 		syslog (LOG_WARNING,
1438*48a54d36SAndroid Build Coastguard Worker 			"mdns: Hostname too long '%.*s': len %d, max %d",
1439*48a54d36SAndroid Build Coastguard Worker 			len,
1440*48a54d36SAndroid Build Coastguard Worker 			fullname,
1441*48a54d36SAndroid Build Coastguard Worker 			len,
1442*48a54d36SAndroid Build Coastguard Worker 			k_hostname_maxlen
1443*48a54d36SAndroid Build Coastguard Worker 		);
1444*48a54d36SAndroid Build Coastguard Worker 		return NULL;
1445*48a54d36SAndroid Build Coastguard Worker 	}
1446*48a54d36SAndroid Build Coastguard Worker 
1447*48a54d36SAndroid Build Coastguard Worker 	result->hostent->h_name =
1448*48a54d36SAndroid Build Coastguard Worker 		strcpy (result->header->hostname, fullname);
1449*48a54d36SAndroid Build Coastguard Worker 
1450*48a54d36SAndroid Build Coastguard Worker 	return result->header->hostname;
1451*48a54d36SAndroid Build Coastguard Worker }
1452*48a54d36SAndroid Build Coastguard Worker 
1453*48a54d36SAndroid Build Coastguard Worker 
1454*48a54d36SAndroid Build Coastguard Worker /*
1455*48a54d36SAndroid Build Coastguard Worker 	Add fully qualified name as hostname or alias.
1456*48a54d36SAndroid Build Coastguard Worker 
1457*48a54d36SAndroid Build Coastguard Worker 	If hostname is not fully qualified this is not an error, but the data
1458*48a54d36SAndroid Build Coastguard Worker 	returned may be not what the application wanted.
1459*48a54d36SAndroid Build Coastguard Worker 
1460*48a54d36SAndroid Build Coastguard Worker 	Parameter
1461*48a54d36SAndroid Build Coastguard Worker 		result
1462*48a54d36SAndroid Build Coastguard Worker 			Result structure to write to
1463*48a54d36SAndroid Build Coastguard Worker 		data
1464*48a54d36SAndroid Build Coastguard Worker 			Incoming alias (null terminated)
1465*48a54d36SAndroid Build Coastguard Worker 		len
1466*48a54d36SAndroid Build Coastguard Worker 			Length of data buffer (in bytes), including trailing null
1467*48a54d36SAndroid Build Coastguard Worker 
1468*48a54d36SAndroid Build Coastguard Worker 	Result
1469*48a54d36SAndroid Build Coastguard Worker 		Pointer to start of newly written data,
1470*48a54d36SAndroid Build Coastguard Worker 		or NULL on error
1471*48a54d36SAndroid Build Coastguard Worker 		If alias or hostname already exists, returns pointer to that instead.
1472*48a54d36SAndroid Build Coastguard Worker  */
1473*48a54d36SAndroid Build Coastguard Worker static char *
add_hostname_or_alias(result_map_t * result,const char * data,int len)1474*48a54d36SAndroid Build Coastguard Worker add_hostname_or_alias (result_map_t * result, const char * data, int len)
1475*48a54d36SAndroid Build Coastguard Worker {
1476*48a54d36SAndroid Build Coastguard Worker 	char * hostname = result->hostent->h_name;
1477*48a54d36SAndroid Build Coastguard Worker 
1478*48a54d36SAndroid Build Coastguard Worker 	if (*hostname)
1479*48a54d36SAndroid Build Coastguard Worker 	{
1480*48a54d36SAndroid Build Coastguard Worker 		if (strcmp (hostname, data) == 0)
1481*48a54d36SAndroid Build Coastguard Worker 		{
1482*48a54d36SAndroid Build Coastguard Worker 			return hostname;
1483*48a54d36SAndroid Build Coastguard Worker 		}
1484*48a54d36SAndroid Build Coastguard Worker 		else
1485*48a54d36SAndroid Build Coastguard Worker 		{
1486*48a54d36SAndroid Build Coastguard Worker 			return add_alias_to_buffer (result, data, len);
1487*48a54d36SAndroid Build Coastguard Worker 		}
1488*48a54d36SAndroid Build Coastguard Worker 	}
1489*48a54d36SAndroid Build Coastguard Worker 	else
1490*48a54d36SAndroid Build Coastguard Worker 	{
1491*48a54d36SAndroid Build Coastguard Worker 		return add_hostname_len (result, data, len);
1492*48a54d36SAndroid Build Coastguard Worker 	}
1493*48a54d36SAndroid Build Coastguard Worker }
1494*48a54d36SAndroid Build Coastguard Worker 
1495*48a54d36SAndroid Build Coastguard Worker 
1496*48a54d36SAndroid Build Coastguard Worker static int
init_result(result_map_t * result,hostent * result_buf,char * buf,size_t buflen)1497*48a54d36SAndroid Build Coastguard Worker init_result (
1498*48a54d36SAndroid Build Coastguard Worker 	result_map_t * result,
1499*48a54d36SAndroid Build Coastguard Worker 	hostent * result_buf,
1500*48a54d36SAndroid Build Coastguard Worker 	char * buf,
1501*48a54d36SAndroid Build Coastguard Worker 	size_t buflen
1502*48a54d36SAndroid Build Coastguard Worker )
1503*48a54d36SAndroid Build Coastguard Worker {
1504*48a54d36SAndroid Build Coastguard Worker 	if (buflen < sizeof (buf_header_t))
1505*48a54d36SAndroid Build Coastguard Worker 	{
1506*48a54d36SAndroid Build Coastguard Worker 		return ERANGE;
1507*48a54d36SAndroid Build Coastguard Worker 	}
1508*48a54d36SAndroid Build Coastguard Worker 
1509*48a54d36SAndroid Build Coastguard Worker 	result->hostent = result_buf;
1510*48a54d36SAndroid Build Coastguard Worker 	result->header = (buf_header_t *) buf;
1511*48a54d36SAndroid Build Coastguard Worker 	result->header->hostname[0] = 0;
1512*48a54d36SAndroid Build Coastguard Worker 	result->aliases_count = 0;
1513*48a54d36SAndroid Build Coastguard Worker 	result->header->aliases[0] = NULL;
1514*48a54d36SAndroid Build Coastguard Worker 	result->addrs_count = 0;
1515*48a54d36SAndroid Build Coastguard Worker 	result->header->addrs[0] = NULL;
1516*48a54d36SAndroid Build Coastguard Worker 	result->buffer = buf + sizeof (buf_header_t);
1517*48a54d36SAndroid Build Coastguard Worker 	result->addr_idx = 0;
1518*48a54d36SAndroid Build Coastguard Worker 	result->alias_idx = buflen - sizeof (buf_header_t);
1519*48a54d36SAndroid Build Coastguard Worker 	result->done = 0;
1520*48a54d36SAndroid Build Coastguard Worker 	set_err_notfound (result);
1521*48a54d36SAndroid Build Coastguard Worker 
1522*48a54d36SAndroid Build Coastguard Worker 	// Point hostent to the right buffers
1523*48a54d36SAndroid Build Coastguard Worker 	result->hostent->h_name = result->header->hostname;
1524*48a54d36SAndroid Build Coastguard Worker 	result->hostent->h_aliases = result->header->aliases;
1525*48a54d36SAndroid Build Coastguard Worker 	result->hostent->h_addr_list = result->header->addrs;
1526*48a54d36SAndroid Build Coastguard Worker 
1527*48a54d36SAndroid Build Coastguard Worker 	return 0;
1528*48a54d36SAndroid Build Coastguard Worker }
1529*48a54d36SAndroid Build Coastguard Worker 
1530*48a54d36SAndroid Build Coastguard Worker /*
1531*48a54d36SAndroid Build Coastguard Worker 	Set the status in the result.
1532*48a54d36SAndroid Build Coastguard Worker 
1533*48a54d36SAndroid Build Coastguard Worker 	Parameters
1534*48a54d36SAndroid Build Coastguard Worker 		result
1535*48a54d36SAndroid Build Coastguard Worker 			Result structure to update
1536*48a54d36SAndroid Build Coastguard Worker 		status
1537*48a54d36SAndroid Build Coastguard Worker 			New nss_status value
1538*48a54d36SAndroid Build Coastguard Worker 		err
1539*48a54d36SAndroid Build Coastguard Worker 			New errno value
1540*48a54d36SAndroid Build Coastguard Worker 		herr
1541*48a54d36SAndroid Build Coastguard Worker 			New h_errno value
1542*48a54d36SAndroid Build Coastguard Worker 
1543*48a54d36SAndroid Build Coastguard Worker 	Returns
1544*48a54d36SAndroid Build Coastguard Worker 		New status value
1545*48a54d36SAndroid Build Coastguard Worker  */
1546*48a54d36SAndroid Build Coastguard Worker static nss_status
set_err(result_map_t * result,nss_status status,int err,int herr)1547*48a54d36SAndroid Build Coastguard Worker set_err (result_map_t * result, nss_status status, int err, int herr)
1548*48a54d36SAndroid Build Coastguard Worker {
1549*48a54d36SAndroid Build Coastguard Worker 	result->status = status;
1550*48a54d36SAndroid Build Coastguard Worker 	result->r_errno = err;
1551*48a54d36SAndroid Build Coastguard Worker 	result->r_h_errno = herr;
1552*48a54d36SAndroid Build Coastguard Worker 
1553*48a54d36SAndroid Build Coastguard Worker 	return status;
1554*48a54d36SAndroid Build Coastguard Worker }
1555*48a54d36SAndroid Build Coastguard Worker 
1556*48a54d36SAndroid Build Coastguard Worker static nss_status
set_err_notfound(result_map_t * result)1557*48a54d36SAndroid Build Coastguard Worker set_err_notfound (result_map_t * result)
1558*48a54d36SAndroid Build Coastguard Worker {
1559*48a54d36SAndroid Build Coastguard Worker 	return set_err (result, NSS_STATUS_NOTFOUND, ENOENT, HOST_NOT_FOUND);
1560*48a54d36SAndroid Build Coastguard Worker }
1561*48a54d36SAndroid Build Coastguard Worker 
1562*48a54d36SAndroid Build Coastguard Worker static nss_status
set_err_bad_hostname(result_map_t * result)1563*48a54d36SAndroid Build Coastguard Worker set_err_bad_hostname (result_map_t * result)
1564*48a54d36SAndroid Build Coastguard Worker {
1565*48a54d36SAndroid Build Coastguard Worker 	return set_err (result, NSS_STATUS_TRYAGAIN, ENOENT, NO_RECOVERY);
1566*48a54d36SAndroid Build Coastguard Worker }
1567*48a54d36SAndroid Build Coastguard Worker 
1568*48a54d36SAndroid Build Coastguard Worker static nss_status
set_err_buf_too_small(result_map_t * result)1569*48a54d36SAndroid Build Coastguard Worker set_err_buf_too_small (result_map_t * result)
1570*48a54d36SAndroid Build Coastguard Worker {
1571*48a54d36SAndroid Build Coastguard Worker 	return set_err (result, NSS_STATUS_TRYAGAIN, ERANGE, NETDB_INTERNAL);
1572*48a54d36SAndroid Build Coastguard Worker }
1573*48a54d36SAndroid Build Coastguard Worker 
1574*48a54d36SAndroid Build Coastguard Worker static nss_status
set_err_internal_resource_full(result_map_t * result)1575*48a54d36SAndroid Build Coastguard Worker set_err_internal_resource_full (result_map_t * result)
1576*48a54d36SAndroid Build Coastguard Worker {
1577*48a54d36SAndroid Build Coastguard Worker 	return set_err (result, NSS_STATUS_RETURN, ERANGE, NO_RECOVERY);
1578*48a54d36SAndroid Build Coastguard Worker }
1579*48a54d36SAndroid Build Coastguard Worker 
1580*48a54d36SAndroid Build Coastguard Worker static nss_status
set_err_system(result_map_t * result)1581*48a54d36SAndroid Build Coastguard Worker set_err_system (result_map_t * result)
1582*48a54d36SAndroid Build Coastguard Worker {
1583*48a54d36SAndroid Build Coastguard Worker 	return set_err (result, NSS_STATUS_UNAVAIL, errno, NETDB_INTERNAL);
1584*48a54d36SAndroid Build Coastguard Worker }
1585*48a54d36SAndroid Build Coastguard Worker 
1586*48a54d36SAndroid Build Coastguard Worker static nss_status
set_err_mdns_failed(result_map_t * result)1587*48a54d36SAndroid Build Coastguard Worker set_err_mdns_failed (result_map_t * result)
1588*48a54d36SAndroid Build Coastguard Worker {
1589*48a54d36SAndroid Build Coastguard Worker 	return set_err (result, NSS_STATUS_TRYAGAIN, EAGAIN, TRY_AGAIN);
1590*48a54d36SAndroid Build Coastguard Worker }
1591*48a54d36SAndroid Build Coastguard Worker 
1592*48a54d36SAndroid Build Coastguard Worker static nss_status
set_err_success(result_map_t * result)1593*48a54d36SAndroid Build Coastguard Worker set_err_success (result_map_t * result)
1594*48a54d36SAndroid Build Coastguard Worker {
1595*48a54d36SAndroid Build Coastguard Worker 	result->status = NSS_STATUS_SUCCESS;
1596*48a54d36SAndroid Build Coastguard Worker 	return result->status;
1597*48a54d36SAndroid Build Coastguard Worker }
1598*48a54d36SAndroid Build Coastguard Worker 
1599*48a54d36SAndroid Build Coastguard Worker 
1600*48a54d36SAndroid Build Coastguard Worker /*
1601*48a54d36SAndroid Build Coastguard Worker 	Test whether name is applicable for mdns to process, and if so copy into
1602*48a54d36SAndroid Build Coastguard Worker 	lookup_name buffer (if non-NULL).
1603*48a54d36SAndroid Build Coastguard Worker 
1604*48a54d36SAndroid Build Coastguard Worker 	Returns
1605*48a54d36SAndroid Build Coastguard Worker 		Pointer to name to lookup up, if applicable, or NULL otherwise.
1606*48a54d36SAndroid Build Coastguard Worker  */
1607*48a54d36SAndroid Build Coastguard Worker static const char *
is_applicable_name(result_map_t * result,const char * name,char * lookup_name)1608*48a54d36SAndroid Build Coastguard Worker is_applicable_name (
1609*48a54d36SAndroid Build Coastguard Worker 	result_map_t * result,
1610*48a54d36SAndroid Build Coastguard Worker 	const char * name,
1611*48a54d36SAndroid Build Coastguard Worker 	char * lookup_name
1612*48a54d36SAndroid Build Coastguard Worker )
1613*48a54d36SAndroid Build Coastguard Worker {
1614*48a54d36SAndroid Build Coastguard Worker 	int match = config_is_mdns_suffix (name);
1615*48a54d36SAndroid Build Coastguard Worker 	if (match > 0)
1616*48a54d36SAndroid Build Coastguard Worker 	{
1617*48a54d36SAndroid Build Coastguard Worker 		if (lookup_name)
1618*48a54d36SAndroid Build Coastguard Worker 		{
1619*48a54d36SAndroid Build Coastguard Worker 			strncpy (lookup_name, name, k_hostname_maxlen + 1);
1620*48a54d36SAndroid Build Coastguard Worker 			return lookup_name;
1621*48a54d36SAndroid Build Coastguard Worker 		}
1622*48a54d36SAndroid Build Coastguard Worker 		else
1623*48a54d36SAndroid Build Coastguard Worker 		{
1624*48a54d36SAndroid Build Coastguard Worker 			return name;
1625*48a54d36SAndroid Build Coastguard Worker 		}
1626*48a54d36SAndroid Build Coastguard Worker 	}
1627*48a54d36SAndroid Build Coastguard Worker 	else
1628*48a54d36SAndroid Build Coastguard Worker 	{
1629*48a54d36SAndroid Build Coastguard Worker 		if (match < 0)
1630*48a54d36SAndroid Build Coastguard Worker 		{
1631*48a54d36SAndroid Build Coastguard Worker 			set_err_system (result);
1632*48a54d36SAndroid Build Coastguard Worker 		}
1633*48a54d36SAndroid Build Coastguard Worker 		return NULL;
1634*48a54d36SAndroid Build Coastguard Worker 	}
1635*48a54d36SAndroid Build Coastguard Worker }
1636*48a54d36SAndroid Build Coastguard Worker 
1637*48a54d36SAndroid Build Coastguard Worker /*
1638*48a54d36SAndroid Build Coastguard Worker 	Test whether address is applicable for mdns to process, and if so copy into
1639*48a54d36SAndroid Build Coastguard Worker 	addr_str buffer as an address suitable for ptr lookup.
1640*48a54d36SAndroid Build Coastguard Worker 
1641*48a54d36SAndroid Build Coastguard Worker 	Returns
1642*48a54d36SAndroid Build Coastguard Worker 		Pointer to name to lookup up, if applicable, or NULL otherwise.
1643*48a54d36SAndroid Build Coastguard Worker  */
1644*48a54d36SAndroid Build Coastguard Worker static const char *
is_applicable_addr(result_map_t * result,const void * addr,int af,char * addr_str)1645*48a54d36SAndroid Build Coastguard Worker is_applicable_addr (
1646*48a54d36SAndroid Build Coastguard Worker 	result_map_t * result,
1647*48a54d36SAndroid Build Coastguard Worker 	const void * addr,
1648*48a54d36SAndroid Build Coastguard Worker 	int af,
1649*48a54d36SAndroid Build Coastguard Worker 	char * addr_str
1650*48a54d36SAndroid Build Coastguard Worker )
1651*48a54d36SAndroid Build Coastguard Worker {
1652*48a54d36SAndroid Build Coastguard Worker 	int match;
1653*48a54d36SAndroid Build Coastguard Worker 
1654*48a54d36SAndroid Build Coastguard Worker 	if (! format_reverse_addr (af, addr, -1, addr_str))
1655*48a54d36SAndroid Build Coastguard Worker 	{
1656*48a54d36SAndroid Build Coastguard Worker 		if (MDNS_VERBOSE)
1657*48a54d36SAndroid Build Coastguard Worker 			syslog (LOG_DEBUG,
1658*48a54d36SAndroid Build Coastguard Worker 				"mdns: Failed to create reverse address"
1659*48a54d36SAndroid Build Coastguard Worker 			);
1660*48a54d36SAndroid Build Coastguard Worker 		return NULL;
1661*48a54d36SAndroid Build Coastguard Worker 	}
1662*48a54d36SAndroid Build Coastguard Worker 
1663*48a54d36SAndroid Build Coastguard Worker 	if (MDNS_VERBOSE)
1664*48a54d36SAndroid Build Coastguard Worker 		syslog (LOG_DEBUG,
1665*48a54d36SAndroid Build Coastguard Worker 			"mdns: Reverse address: %s",
1666*48a54d36SAndroid Build Coastguard Worker 			addr_str
1667*48a54d36SAndroid Build Coastguard Worker 		);
1668*48a54d36SAndroid Build Coastguard Worker 
1669*48a54d36SAndroid Build Coastguard Worker 	match = config_is_mdns_suffix (addr_str);
1670*48a54d36SAndroid Build Coastguard Worker 	if (match > 0)
1671*48a54d36SAndroid Build Coastguard Worker 	{
1672*48a54d36SAndroid Build Coastguard Worker 		return addr_str;
1673*48a54d36SAndroid Build Coastguard Worker 	}
1674*48a54d36SAndroid Build Coastguard Worker 	else
1675*48a54d36SAndroid Build Coastguard Worker 	{
1676*48a54d36SAndroid Build Coastguard Worker 		if (match < 0)
1677*48a54d36SAndroid Build Coastguard Worker 		{
1678*48a54d36SAndroid Build Coastguard Worker 			set_err_system (result);
1679*48a54d36SAndroid Build Coastguard Worker 		}
1680*48a54d36SAndroid Build Coastguard Worker 		return NULL;
1681*48a54d36SAndroid Build Coastguard Worker 	}
1682*48a54d36SAndroid Build Coastguard Worker }
1683*48a54d36SAndroid Build Coastguard Worker 
1684*48a54d36SAndroid Build Coastguard Worker //----------
1685*48a54d36SAndroid Build Coastguard Worker // Types and Constants
1686*48a54d36SAndroid Build Coastguard Worker 
1687*48a54d36SAndroid Build Coastguard Worker const char * k_conf_file = "/etc/nss_mdns.conf";
1688*48a54d36SAndroid Build Coastguard Worker #define CONF_LINE_SIZE 1024
1689*48a54d36SAndroid Build Coastguard Worker 
1690*48a54d36SAndroid Build Coastguard Worker const char k_comment_char = '#';
1691*48a54d36SAndroid Build Coastguard Worker 
1692*48a54d36SAndroid Build Coastguard Worker const char * k_keyword_domain = "domain";
1693*48a54d36SAndroid Build Coastguard Worker 
1694*48a54d36SAndroid Build Coastguard Worker const char * k_default_domains [] =
1695*48a54d36SAndroid Build Coastguard Worker 	{
1696*48a54d36SAndroid Build Coastguard Worker 		"local",
1697*48a54d36SAndroid Build Coastguard Worker 		"254.169.in-addr.arpa",
1698*48a54d36SAndroid Build Coastguard Worker 		"8.e.f.ip6.int",
1699*48a54d36SAndroid Build Coastguard Worker 		"8.e.f.ip6.arpa",
1700*48a54d36SAndroid Build Coastguard Worker 		"9.e.f.ip6.int",
1701*48a54d36SAndroid Build Coastguard Worker 		"9.e.f.ip6.arpa",
1702*48a54d36SAndroid Build Coastguard Worker 		"a.e.f.ip6.int",
1703*48a54d36SAndroid Build Coastguard Worker 		"a.e.f.ip6.arpa",
1704*48a54d36SAndroid Build Coastguard Worker 		"b.e.f.ip6.int",
1705*48a54d36SAndroid Build Coastguard Worker 		"b.e.f.ip6.arpa",
1706*48a54d36SAndroid Build Coastguard Worker 		NULL
1707*48a54d36SAndroid Build Coastguard Worker 			// Always null terminated
1708*48a54d36SAndroid Build Coastguard Worker 	};
1709*48a54d36SAndroid Build Coastguard Worker 
1710*48a54d36SAndroid Build Coastguard Worker // Linked list of domains
1711*48a54d36SAndroid Build Coastguard Worker typedef struct domain_entry
1712*48a54d36SAndroid Build Coastguard Worker {
1713*48a54d36SAndroid Build Coastguard Worker 	char * domain;
1714*48a54d36SAndroid Build Coastguard Worker 	struct domain_entry * next;
1715*48a54d36SAndroid Build Coastguard Worker } domain_entry_t;
1716*48a54d36SAndroid Build Coastguard Worker 
1717*48a54d36SAndroid Build Coastguard Worker 
1718*48a54d36SAndroid Build Coastguard Worker // Config
1719*48a54d36SAndroid Build Coastguard Worker typedef struct
1720*48a54d36SAndroid Build Coastguard Worker {
1721*48a54d36SAndroid Build Coastguard Worker 	domain_entry_t * domains;
1722*48a54d36SAndroid Build Coastguard Worker } config_t;
1723*48a54d36SAndroid Build Coastguard Worker 
1724*48a54d36SAndroid Build Coastguard Worker const config_t k_empty_config =
1725*48a54d36SAndroid Build Coastguard Worker 	{
1726*48a54d36SAndroid Build Coastguard Worker 		NULL
1727*48a54d36SAndroid Build Coastguard Worker 	};
1728*48a54d36SAndroid Build Coastguard Worker 
1729*48a54d36SAndroid Build Coastguard Worker 
1730*48a54d36SAndroid Build Coastguard Worker // Context - tracks position in config file, used for error reporting
1731*48a54d36SAndroid Build Coastguard Worker typedef struct
1732*48a54d36SAndroid Build Coastguard Worker {
1733*48a54d36SAndroid Build Coastguard Worker 	const char * filename;
1734*48a54d36SAndroid Build Coastguard Worker 	int linenum;
1735*48a54d36SAndroid Build Coastguard Worker } config_file_context_t;
1736*48a54d36SAndroid Build Coastguard Worker 
1737*48a54d36SAndroid Build Coastguard Worker 
1738*48a54d36SAndroid Build Coastguard Worker //----------
1739*48a54d36SAndroid Build Coastguard Worker // Local prototypes
1740*48a54d36SAndroid Build Coastguard Worker 
1741*48a54d36SAndroid Build Coastguard Worker static errcode_t
1742*48a54d36SAndroid Build Coastguard Worker load_config (config_t * conf);
1743*48a54d36SAndroid Build Coastguard Worker 
1744*48a54d36SAndroid Build Coastguard Worker static errcode_t
1745*48a54d36SAndroid Build Coastguard Worker process_config_line (
1746*48a54d36SAndroid Build Coastguard Worker 	config_t * conf,
1747*48a54d36SAndroid Build Coastguard Worker 	char * line,
1748*48a54d36SAndroid Build Coastguard Worker 	config_file_context_t * context
1749*48a54d36SAndroid Build Coastguard Worker );
1750*48a54d36SAndroid Build Coastguard Worker 
1751*48a54d36SAndroid Build Coastguard Worker static char *
1752*48a54d36SAndroid Build Coastguard Worker get_next_word (char * input, char **next);
1753*48a54d36SAndroid Build Coastguard Worker 
1754*48a54d36SAndroid Build Coastguard Worker static errcode_t
1755*48a54d36SAndroid Build Coastguard Worker default_config (config_t * conf);
1756*48a54d36SAndroid Build Coastguard Worker 
1757*48a54d36SAndroid Build Coastguard Worker static errcode_t
1758*48a54d36SAndroid Build Coastguard Worker add_domain (config_t * conf, const char * domain);
1759*48a54d36SAndroid Build Coastguard Worker 
1760*48a54d36SAndroid Build Coastguard Worker static int
1761*48a54d36SAndroid Build Coastguard Worker contains_domain (const config_t * conf, const char * domain);
1762*48a54d36SAndroid Build Coastguard Worker 
1763*48a54d36SAndroid Build Coastguard Worker static int
1764*48a54d36SAndroid Build Coastguard Worker contains_domain_suffix (const config_t * conf, const char * addr);
1765*48a54d36SAndroid Build Coastguard Worker 
1766*48a54d36SAndroid Build Coastguard Worker 
1767*48a54d36SAndroid Build Coastguard Worker //----------
1768*48a54d36SAndroid Build Coastguard Worker // Global variables
1769*48a54d36SAndroid Build Coastguard Worker 
1770*48a54d36SAndroid Build Coastguard Worker static config_t * g_config = NULL;
1771*48a54d36SAndroid Build Coastguard Worker 	// Configuration info
1772*48a54d36SAndroid Build Coastguard Worker 
1773*48a54d36SAndroid Build Coastguard Worker pthread_mutex_t g_config_mutex =
1774*48a54d36SAndroid Build Coastguard Worker #ifdef PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP
1775*48a54d36SAndroid Build Coastguard Worker 	PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP;
1776*48a54d36SAndroid Build Coastguard Worker #else
1777*48a54d36SAndroid Build Coastguard Worker 	PTHREAD_MUTEX_INITIALIZER;
1778*48a54d36SAndroid Build Coastguard Worker #endif
1779*48a54d36SAndroid Build Coastguard Worker 
1780*48a54d36SAndroid Build Coastguard Worker 
1781*48a54d36SAndroid Build Coastguard Worker //----------
1782*48a54d36SAndroid Build Coastguard Worker // Configuration functions
1783*48a54d36SAndroid Build Coastguard Worker 
1784*48a54d36SAndroid Build Coastguard Worker 
1785*48a54d36SAndroid Build Coastguard Worker /*
1786*48a54d36SAndroid Build Coastguard Worker 	Initialise the configuration from the config file.
1787*48a54d36SAndroid Build Coastguard Worker 
1788*48a54d36SAndroid Build Coastguard Worker 	Returns
1789*48a54d36SAndroid Build Coastguard Worker 		0 success
1790*48a54d36SAndroid Build Coastguard Worker 		non-zero error code on failure
1791*48a54d36SAndroid Build Coastguard Worker  */
1792*48a54d36SAndroid Build Coastguard Worker errcode_t
init_config()1793*48a54d36SAndroid Build Coastguard Worker init_config ()
1794*48a54d36SAndroid Build Coastguard Worker {
1795*48a54d36SAndroid Build Coastguard Worker 	if (g_config)
1796*48a54d36SAndroid Build Coastguard Worker 	{
1797*48a54d36SAndroid Build Coastguard Worker 		/*
1798*48a54d36SAndroid Build Coastguard Worker 			Safe to test outside mutex.
1799*48a54d36SAndroid Build Coastguard Worker 			If non-zero, initialisation is complete and g_config can be
1800*48a54d36SAndroid Build Coastguard Worker 			safely used read-only.  If zero, then we do proper mutex
1801*48a54d36SAndroid Build Coastguard Worker 			testing before initialisation.
1802*48a54d36SAndroid Build Coastguard Worker 		 */
1803*48a54d36SAndroid Build Coastguard Worker 		return 0;
1804*48a54d36SAndroid Build Coastguard Worker 	}
1805*48a54d36SAndroid Build Coastguard Worker 	else
1806*48a54d36SAndroid Build Coastguard Worker 	{
1807*48a54d36SAndroid Build Coastguard Worker 		int errcode = -1;
1808*48a54d36SAndroid Build Coastguard Worker 		int presult;
1809*48a54d36SAndroid Build Coastguard Worker 		config_t * temp_config;
1810*48a54d36SAndroid Build Coastguard Worker 
1811*48a54d36SAndroid Build Coastguard Worker 		// Acquire mutex
1812*48a54d36SAndroid Build Coastguard Worker 		presult = pthread_mutex_lock (&g_config_mutex);
1813*48a54d36SAndroid Build Coastguard Worker 		if (presult)
1814*48a54d36SAndroid Build Coastguard Worker 		{
1815*48a54d36SAndroid Build Coastguard Worker 			syslog (LOG_ERR,
1816*48a54d36SAndroid Build Coastguard Worker 				"mdns: Fatal mutex lock error in nss_mdns:init_config, %s:%d: %d: %s",
1817*48a54d36SAndroid Build Coastguard Worker 				__FILE__, __LINE__, presult, strerror (presult)
1818*48a54d36SAndroid Build Coastguard Worker 			);
1819*48a54d36SAndroid Build Coastguard Worker 			return presult;
1820*48a54d36SAndroid Build Coastguard Worker 		}
1821*48a54d36SAndroid Build Coastguard Worker 
1822*48a54d36SAndroid Build Coastguard Worker 		// Test again now we have mutex, in case initialisation occurred while
1823*48a54d36SAndroid Build Coastguard Worker 		// we were waiting
1824*48a54d36SAndroid Build Coastguard Worker 		if (! g_config)
1825*48a54d36SAndroid Build Coastguard Worker 		{
1826*48a54d36SAndroid Build Coastguard Worker 			temp_config = (config_t *) malloc (sizeof (config_t));
1827*48a54d36SAndroid Build Coastguard Worker 			if (temp_config)
1828*48a54d36SAndroid Build Coastguard Worker 			{
1829*48a54d36SAndroid Build Coastguard Worker 				// Note: This code will leak memory if initialisation fails
1830*48a54d36SAndroid Build Coastguard Worker 				// repeatedly.  This should only happen in the case of a memory
1831*48a54d36SAndroid Build Coastguard Worker 				// error, so I'm not sure if it's a meaningful problem. - AW
1832*48a54d36SAndroid Build Coastguard Worker 				*temp_config = k_empty_config;
1833*48a54d36SAndroid Build Coastguard Worker 				errcode = load_config (temp_config);
1834*48a54d36SAndroid Build Coastguard Worker 
1835*48a54d36SAndroid Build Coastguard Worker 				if (! errcode)
1836*48a54d36SAndroid Build Coastguard Worker 				{
1837*48a54d36SAndroid Build Coastguard Worker 					g_config = temp_config;
1838*48a54d36SAndroid Build Coastguard Worker 				}
1839*48a54d36SAndroid Build Coastguard Worker 			}
1840*48a54d36SAndroid Build Coastguard Worker 			else
1841*48a54d36SAndroid Build Coastguard Worker 			{
1842*48a54d36SAndroid Build Coastguard Worker 				syslog (LOG_ERR,
1843*48a54d36SAndroid Build Coastguard Worker 					"mdns: Can't allocate memory in nss_mdns:init_config, %s:%d",
1844*48a54d36SAndroid Build Coastguard Worker 					__FILE__, __LINE__
1845*48a54d36SAndroid Build Coastguard Worker 				);
1846*48a54d36SAndroid Build Coastguard Worker 				errcode = errno;
1847*48a54d36SAndroid Build Coastguard Worker 			}
1848*48a54d36SAndroid Build Coastguard Worker 		}
1849*48a54d36SAndroid Build Coastguard Worker 
1850*48a54d36SAndroid Build Coastguard Worker 		presult = pthread_mutex_unlock (&g_config_mutex);
1851*48a54d36SAndroid Build Coastguard Worker 		if (presult)
1852*48a54d36SAndroid Build Coastguard Worker 		{
1853*48a54d36SAndroid Build Coastguard Worker 			syslog (LOG_ERR,
1854*48a54d36SAndroid Build Coastguard Worker 				"mdns: Fatal mutex unlock error in nss_mdns:init_config, %s:%d: %d: %s",
1855*48a54d36SAndroid Build Coastguard Worker 				__FILE__, __LINE__, presult, strerror (presult)
1856*48a54d36SAndroid Build Coastguard Worker 			);
1857*48a54d36SAndroid Build Coastguard Worker 			errcode = presult;
1858*48a54d36SAndroid Build Coastguard Worker 		}
1859*48a54d36SAndroid Build Coastguard Worker 
1860*48a54d36SAndroid Build Coastguard Worker 		return errcode;
1861*48a54d36SAndroid Build Coastguard Worker 	}
1862*48a54d36SAndroid Build Coastguard Worker }
1863*48a54d36SAndroid Build Coastguard Worker 
1864*48a54d36SAndroid Build Coastguard Worker 
1865*48a54d36SAndroid Build Coastguard Worker int
config_is_mdns_suffix(const char * name)1866*48a54d36SAndroid Build Coastguard Worker config_is_mdns_suffix (const char * name)
1867*48a54d36SAndroid Build Coastguard Worker {
1868*48a54d36SAndroid Build Coastguard Worker 	int errcode = init_config ();
1869*48a54d36SAndroid Build Coastguard Worker 	if (! errcode)
1870*48a54d36SAndroid Build Coastguard Worker 	{
1871*48a54d36SAndroid Build Coastguard Worker 		return contains_domain_suffix (g_config, name);
1872*48a54d36SAndroid Build Coastguard Worker 	}
1873*48a54d36SAndroid Build Coastguard Worker 	else
1874*48a54d36SAndroid Build Coastguard Worker 	{
1875*48a54d36SAndroid Build Coastguard Worker 		errno = errcode;
1876*48a54d36SAndroid Build Coastguard Worker 		return -1;
1877*48a54d36SAndroid Build Coastguard Worker 	}
1878*48a54d36SAndroid Build Coastguard Worker }
1879*48a54d36SAndroid Build Coastguard Worker 
1880*48a54d36SAndroid Build Coastguard Worker 
1881*48a54d36SAndroid Build Coastguard Worker //----------
1882*48a54d36SAndroid Build Coastguard Worker // Local functions
1883*48a54d36SAndroid Build Coastguard Worker 
1884*48a54d36SAndroid Build Coastguard Worker static errcode_t
load_config(config_t * conf)1885*48a54d36SAndroid Build Coastguard Worker load_config (config_t * conf)
1886*48a54d36SAndroid Build Coastguard Worker {
1887*48a54d36SAndroid Build Coastguard Worker 	FILE * cf;
1888*48a54d36SAndroid Build Coastguard Worker 	char line [CONF_LINE_SIZE];
1889*48a54d36SAndroid Build Coastguard Worker 	config_file_context_t context;
1890*48a54d36SAndroid Build Coastguard Worker 
1891*48a54d36SAndroid Build Coastguard Worker 	context.filename = k_conf_file;
1892*48a54d36SAndroid Build Coastguard Worker 	context.linenum = 0;
1893*48a54d36SAndroid Build Coastguard Worker 
1894*48a54d36SAndroid Build Coastguard Worker 
1895*48a54d36SAndroid Build Coastguard Worker 	cf = fopen (context.filename, "r");
1896*48a54d36SAndroid Build Coastguard Worker 	if (! cf)
1897*48a54d36SAndroid Build Coastguard Worker 	{
1898*48a54d36SAndroid Build Coastguard Worker 		syslog (LOG_INFO,
1899*48a54d36SAndroid Build Coastguard Worker 			"mdns: Couldn't open nss_mdns configuration file %s, using default.",
1900*48a54d36SAndroid Build Coastguard Worker 			context.filename
1901*48a54d36SAndroid Build Coastguard Worker 		);
1902*48a54d36SAndroid Build Coastguard Worker 		return default_config (conf);
1903*48a54d36SAndroid Build Coastguard Worker 	}
1904*48a54d36SAndroid Build Coastguard Worker 
1905*48a54d36SAndroid Build Coastguard Worker 	while (fgets (line, CONF_LINE_SIZE, cf))
1906*48a54d36SAndroid Build Coastguard Worker 	{
1907*48a54d36SAndroid Build Coastguard Worker 		int errcode;
1908*48a54d36SAndroid Build Coastguard Worker 		context.linenum++;
1909*48a54d36SAndroid Build Coastguard Worker 		errcode = process_config_line (conf, line, &context);
1910*48a54d36SAndroid Build Coastguard Worker 		if (errcode)
1911*48a54d36SAndroid Build Coastguard Worker 		{
1912*48a54d36SAndroid Build Coastguard Worker 			// Critical error, give up
1913*48a54d36SAndroid Build Coastguard Worker 			fclose(cf);
1914*48a54d36SAndroid Build Coastguard Worker 			return errcode;
1915*48a54d36SAndroid Build Coastguard Worker 		}
1916*48a54d36SAndroid Build Coastguard Worker 	}
1917*48a54d36SAndroid Build Coastguard Worker 
1918*48a54d36SAndroid Build Coastguard Worker 	fclose (cf);
1919*48a54d36SAndroid Build Coastguard Worker 
1920*48a54d36SAndroid Build Coastguard Worker 	return 0;
1921*48a54d36SAndroid Build Coastguard Worker }
1922*48a54d36SAndroid Build Coastguard Worker 
1923*48a54d36SAndroid Build Coastguard Worker 
1924*48a54d36SAndroid Build Coastguard Worker /*
1925*48a54d36SAndroid Build Coastguard Worker 	Parse a line of the configuration file.
1926*48a54d36SAndroid Build Coastguard Worker 	For each keyword recognised, perform appropriate handling.
1927*48a54d36SAndroid Build Coastguard Worker 	If the keyword is not recognised, print a message to syslog
1928*48a54d36SAndroid Build Coastguard Worker 	and continue.
1929*48a54d36SAndroid Build Coastguard Worker 
1930*48a54d36SAndroid Build Coastguard Worker 	Returns
1931*48a54d36SAndroid Build Coastguard Worker 		0 success, or recoverable config file error
1932*48a54d36SAndroid Build Coastguard Worker 		non-zero serious system error, processing aborted
1933*48a54d36SAndroid Build Coastguard Worker  */
1934*48a54d36SAndroid Build Coastguard Worker static errcode_t
process_config_line(config_t * conf,char * line,config_file_context_t * context)1935*48a54d36SAndroid Build Coastguard Worker process_config_line (
1936*48a54d36SAndroid Build Coastguard Worker 	config_t * conf,
1937*48a54d36SAndroid Build Coastguard Worker 	char * line,
1938*48a54d36SAndroid Build Coastguard Worker 	config_file_context_t * context
1939*48a54d36SAndroid Build Coastguard Worker )
1940*48a54d36SAndroid Build Coastguard Worker {
1941*48a54d36SAndroid Build Coastguard Worker 	char * curr = line;
1942*48a54d36SAndroid Build Coastguard Worker 	char * word;
1943*48a54d36SAndroid Build Coastguard Worker 
1944*48a54d36SAndroid Build Coastguard Worker 	word = get_next_word (curr, &curr);
1945*48a54d36SAndroid Build Coastguard Worker 	if (! word || word [0] == k_comment_char)
1946*48a54d36SAndroid Build Coastguard Worker 	{
1947*48a54d36SAndroid Build Coastguard Worker 		// Nothing interesting on this line
1948*48a54d36SAndroid Build Coastguard Worker 		return 0;
1949*48a54d36SAndroid Build Coastguard Worker 	}
1950*48a54d36SAndroid Build Coastguard Worker 
1951*48a54d36SAndroid Build Coastguard Worker 	if (strcmp (word, k_keyword_domain) == 0)
1952*48a54d36SAndroid Build Coastguard Worker 	{
1953*48a54d36SAndroid Build Coastguard Worker 		word = get_next_word (curr, &curr);
1954*48a54d36SAndroid Build Coastguard Worker 		if (word)
1955*48a54d36SAndroid Build Coastguard Worker 		{
1956*48a54d36SAndroid Build Coastguard Worker 			int errcode = add_domain (conf, word);
1957*48a54d36SAndroid Build Coastguard Worker 			if (errcode)
1958*48a54d36SAndroid Build Coastguard Worker 			{
1959*48a54d36SAndroid Build Coastguard Worker 				// something badly wrong, bail
1960*48a54d36SAndroid Build Coastguard Worker 				return errcode;
1961*48a54d36SAndroid Build Coastguard Worker 			}
1962*48a54d36SAndroid Build Coastguard Worker 
1963*48a54d36SAndroid Build Coastguard Worker 			if (get_next_word (curr, NULL))
1964*48a54d36SAndroid Build Coastguard Worker 			{
1965*48a54d36SAndroid Build Coastguard Worker 				syslog (LOG_WARNING,
1966*48a54d36SAndroid Build Coastguard Worker 					"%s, line %d: ignored extra text found after domain",
1967*48a54d36SAndroid Build Coastguard Worker 					context->filename,
1968*48a54d36SAndroid Build Coastguard Worker 					context->linenum
1969*48a54d36SAndroid Build Coastguard Worker 				);
1970*48a54d36SAndroid Build Coastguard Worker 			}
1971*48a54d36SAndroid Build Coastguard Worker 		}
1972*48a54d36SAndroid Build Coastguard Worker 		else
1973*48a54d36SAndroid Build Coastguard Worker 		{
1974*48a54d36SAndroid Build Coastguard Worker 			syslog (LOG_WARNING,
1975*48a54d36SAndroid Build Coastguard Worker 				"%s, line %d: no domain specified",
1976*48a54d36SAndroid Build Coastguard Worker 				context->filename,
1977*48a54d36SAndroid Build Coastguard Worker 				context->linenum
1978*48a54d36SAndroid Build Coastguard Worker 			);
1979*48a54d36SAndroid Build Coastguard Worker 		}
1980*48a54d36SAndroid Build Coastguard Worker 	}
1981*48a54d36SAndroid Build Coastguard Worker 	else
1982*48a54d36SAndroid Build Coastguard Worker 	{
1983*48a54d36SAndroid Build Coastguard Worker 		syslog (LOG_WARNING,
1984*48a54d36SAndroid Build Coastguard Worker 			"%s, line %d: unknown keyword %s - skipping",
1985*48a54d36SAndroid Build Coastguard Worker 			context->filename,
1986*48a54d36SAndroid Build Coastguard Worker 			context->linenum,
1987*48a54d36SAndroid Build Coastguard Worker 			word
1988*48a54d36SAndroid Build Coastguard Worker 		);
1989*48a54d36SAndroid Build Coastguard Worker 	}
1990*48a54d36SAndroid Build Coastguard Worker 
1991*48a54d36SAndroid Build Coastguard Worker 	return 0;
1992*48a54d36SAndroid Build Coastguard Worker }
1993*48a54d36SAndroid Build Coastguard Worker 
1994*48a54d36SAndroid Build Coastguard Worker 
1995*48a54d36SAndroid Build Coastguard Worker /*
1996*48a54d36SAndroid Build Coastguard Worker 	Get next word (whitespace separated) from input string.
1997*48a54d36SAndroid Build Coastguard Worker 	A null character is written into the first whitespace character following
1998*48a54d36SAndroid Build Coastguard Worker 	the word.
1999*48a54d36SAndroid Build Coastguard Worker 
2000*48a54d36SAndroid Build Coastguard Worker 	Parameters
2001*48a54d36SAndroid Build Coastguard Worker 		input
2002*48a54d36SAndroid Build Coastguard Worker 			Input string.  This string is modified by get_next_word.
2003*48a54d36SAndroid Build Coastguard Worker 		next
2004*48a54d36SAndroid Build Coastguard Worker 			If non-NULL and the result is non-NULL, a pointer to the
2005*48a54d36SAndroid Build Coastguard Worker 			character following the end of the word (after the null)
2006*48a54d36SAndroid Build Coastguard Worker 			is written to 'next'.
2007*48a54d36SAndroid Build Coastguard Worker 			If no word is found, the original value is unchanged.
2008*48a54d36SAndroid Build Coastguard Worker 			If the word extended to the end of the string, 'next' points
2009*48a54d36SAndroid Build Coastguard Worker 			to the trailling NULL.
2010*48a54d36SAndroid Build Coastguard Worker 			It is safe to pass 'str' as 'input' and '&str' as 'next'.
2011*48a54d36SAndroid Build Coastguard Worker 	Returns
2012*48a54d36SAndroid Build Coastguard Worker 		Pointer to the first non-whitespace character (and thus word) found.
2013*48a54d36SAndroid Build Coastguard Worker 		if no word is found, returns NULL.
2014*48a54d36SAndroid Build Coastguard Worker  */
2015*48a54d36SAndroid Build Coastguard Worker static char *
get_next_word(char * input,char ** next)2016*48a54d36SAndroid Build Coastguard Worker get_next_word (char * input, char **next)
2017*48a54d36SAndroid Build Coastguard Worker {
2018*48a54d36SAndroid Build Coastguard Worker 	char * curr = input;
2019*48a54d36SAndroid Build Coastguard Worker 	char * result;
2020*48a54d36SAndroid Build Coastguard Worker 
2021*48a54d36SAndroid Build Coastguard Worker 	while (isspace (*curr))
2022*48a54d36SAndroid Build Coastguard Worker 	{
2023*48a54d36SAndroid Build Coastguard Worker 		curr ++;
2024*48a54d36SAndroid Build Coastguard Worker 	}
2025*48a54d36SAndroid Build Coastguard Worker 
2026*48a54d36SAndroid Build Coastguard Worker 	if (*curr == 0)
2027*48a54d36SAndroid Build Coastguard Worker 	{
2028*48a54d36SAndroid Build Coastguard Worker 		return NULL;
2029*48a54d36SAndroid Build Coastguard Worker 	}
2030*48a54d36SAndroid Build Coastguard Worker 
2031*48a54d36SAndroid Build Coastguard Worker 	result = curr;
2032*48a54d36SAndroid Build Coastguard Worker 	while (*curr && ! isspace (*curr))
2033*48a54d36SAndroid Build Coastguard Worker 	{
2034*48a54d36SAndroid Build Coastguard Worker 		curr++;
2035*48a54d36SAndroid Build Coastguard Worker 	}
2036*48a54d36SAndroid Build Coastguard Worker 	if (*curr)
2037*48a54d36SAndroid Build Coastguard Worker 	{
2038*48a54d36SAndroid Build Coastguard Worker 		*curr = 0;
2039*48a54d36SAndroid Build Coastguard Worker 		if (next)
2040*48a54d36SAndroid Build Coastguard Worker 		{
2041*48a54d36SAndroid Build Coastguard Worker 			*next = curr+1;
2042*48a54d36SAndroid Build Coastguard Worker 		}
2043*48a54d36SAndroid Build Coastguard Worker 	}
2044*48a54d36SAndroid Build Coastguard Worker 	else
2045*48a54d36SAndroid Build Coastguard Worker 	{
2046*48a54d36SAndroid Build Coastguard Worker 		if (next)
2047*48a54d36SAndroid Build Coastguard Worker 		{
2048*48a54d36SAndroid Build Coastguard Worker 			*next = curr;
2049*48a54d36SAndroid Build Coastguard Worker 		}
2050*48a54d36SAndroid Build Coastguard Worker 	}
2051*48a54d36SAndroid Build Coastguard Worker 
2052*48a54d36SAndroid Build Coastguard Worker 	return result;
2053*48a54d36SAndroid Build Coastguard Worker }
2054*48a54d36SAndroid Build Coastguard Worker 
2055*48a54d36SAndroid Build Coastguard Worker 
2056*48a54d36SAndroid Build Coastguard Worker static errcode_t
default_config(config_t * conf)2057*48a54d36SAndroid Build Coastguard Worker default_config (config_t * conf)
2058*48a54d36SAndroid Build Coastguard Worker {
2059*48a54d36SAndroid Build Coastguard Worker 	int i;
2060*48a54d36SAndroid Build Coastguard Worker 	for (i = 0; k_default_domains [i]; i++)
2061*48a54d36SAndroid Build Coastguard Worker 	{
2062*48a54d36SAndroid Build Coastguard Worker 		int errcode =
2063*48a54d36SAndroid Build Coastguard Worker 			add_domain (conf, k_default_domains [i]);
2064*48a54d36SAndroid Build Coastguard Worker 		if (errcode)
2065*48a54d36SAndroid Build Coastguard Worker 		{
2066*48a54d36SAndroid Build Coastguard Worker 			// Something has gone (badly) wrong - let's bail
2067*48a54d36SAndroid Build Coastguard Worker 			return errcode;
2068*48a54d36SAndroid Build Coastguard Worker 		}
2069*48a54d36SAndroid Build Coastguard Worker 	}
2070*48a54d36SAndroid Build Coastguard Worker 
2071*48a54d36SAndroid Build Coastguard Worker 	return 0;
2072*48a54d36SAndroid Build Coastguard Worker }
2073*48a54d36SAndroid Build Coastguard Worker 
2074*48a54d36SAndroid Build Coastguard Worker 
2075*48a54d36SAndroid Build Coastguard Worker static errcode_t
add_domain(config_t * conf,const char * domain)2076*48a54d36SAndroid Build Coastguard Worker add_domain (config_t * conf, const char * domain)
2077*48a54d36SAndroid Build Coastguard Worker {
2078*48a54d36SAndroid Build Coastguard Worker 	if (! contains_domain (conf, domain))
2079*48a54d36SAndroid Build Coastguard Worker 	{
2080*48a54d36SAndroid Build Coastguard Worker 		domain_entry_t * d =
2081*48a54d36SAndroid Build Coastguard Worker 			(domain_entry_t *) malloc (sizeof (domain_entry_t));
2082*48a54d36SAndroid Build Coastguard Worker 		if (! d)
2083*48a54d36SAndroid Build Coastguard Worker 		{
2084*48a54d36SAndroid Build Coastguard Worker 			syslog (LOG_ERR,
2085*48a54d36SAndroid Build Coastguard Worker 				"mdns: Can't allocate memory in nss_mdns:init_config, %s:%d",
2086*48a54d36SAndroid Build Coastguard Worker 				__FILE__, __LINE__
2087*48a54d36SAndroid Build Coastguard Worker 			);
2088*48a54d36SAndroid Build Coastguard Worker 			return ENOMEM;
2089*48a54d36SAndroid Build Coastguard Worker 		}
2090*48a54d36SAndroid Build Coastguard Worker 
2091*48a54d36SAndroid Build Coastguard Worker 		d->domain = strdup (domain);
2092*48a54d36SAndroid Build Coastguard Worker 		if (! d->domain)
2093*48a54d36SAndroid Build Coastguard Worker 		{
2094*48a54d36SAndroid Build Coastguard Worker 			syslog (LOG_ERR,
2095*48a54d36SAndroid Build Coastguard Worker 				"mdns: Can't allocate memory in nss_mdns:init_config, %s:%d",
2096*48a54d36SAndroid Build Coastguard Worker 				__FILE__, __LINE__
2097*48a54d36SAndroid Build Coastguard Worker 			);
2098*48a54d36SAndroid Build Coastguard Worker 			free (d);
2099*48a54d36SAndroid Build Coastguard Worker 			return ENOMEM;
2100*48a54d36SAndroid Build Coastguard Worker 		}
2101*48a54d36SAndroid Build Coastguard Worker 		d->next = conf->domains;
2102*48a54d36SAndroid Build Coastguard Worker 		conf->domains = d;
2103*48a54d36SAndroid Build Coastguard Worker 	}
2104*48a54d36SAndroid Build Coastguard Worker 
2105*48a54d36SAndroid Build Coastguard Worker 	return 0;
2106*48a54d36SAndroid Build Coastguard Worker }
2107*48a54d36SAndroid Build Coastguard Worker 
2108*48a54d36SAndroid Build Coastguard Worker 
2109*48a54d36SAndroid Build Coastguard Worker static int
contains_domain(const config_t * conf,const char * domain)2110*48a54d36SAndroid Build Coastguard Worker contains_domain (const config_t * conf, const char * domain)
2111*48a54d36SAndroid Build Coastguard Worker {
2112*48a54d36SAndroid Build Coastguard Worker 	const domain_entry_t * curr = conf->domains;
2113*48a54d36SAndroid Build Coastguard Worker 
2114*48a54d36SAndroid Build Coastguard Worker 	while (curr != NULL)
2115*48a54d36SAndroid Build Coastguard Worker 	{
2116*48a54d36SAndroid Build Coastguard Worker 		if (strcasecmp (curr->domain, domain) == 0)
2117*48a54d36SAndroid Build Coastguard Worker 		{
2118*48a54d36SAndroid Build Coastguard Worker 			return 1;
2119*48a54d36SAndroid Build Coastguard Worker 		}
2120*48a54d36SAndroid Build Coastguard Worker 
2121*48a54d36SAndroid Build Coastguard Worker 		curr = curr->next;
2122*48a54d36SAndroid Build Coastguard Worker 	}
2123*48a54d36SAndroid Build Coastguard Worker 
2124*48a54d36SAndroid Build Coastguard Worker 	return 0;
2125*48a54d36SAndroid Build Coastguard Worker }
2126*48a54d36SAndroid Build Coastguard Worker 
2127*48a54d36SAndroid Build Coastguard Worker 
2128*48a54d36SAndroid Build Coastguard Worker static int
contains_domain_suffix(const config_t * conf,const char * addr)2129*48a54d36SAndroid Build Coastguard Worker contains_domain_suffix (const config_t * conf, const char * addr)
2130*48a54d36SAndroid Build Coastguard Worker {
2131*48a54d36SAndroid Build Coastguard Worker 	const domain_entry_t * curr = conf->domains;
2132*48a54d36SAndroid Build Coastguard Worker 
2133*48a54d36SAndroid Build Coastguard Worker 	while (curr != NULL)
2134*48a54d36SAndroid Build Coastguard Worker 	{
2135*48a54d36SAndroid Build Coastguard Worker 		if (cmp_dns_suffix (addr, curr->domain) > 0)
2136*48a54d36SAndroid Build Coastguard Worker 		{
2137*48a54d36SAndroid Build Coastguard Worker 			return 1;
2138*48a54d36SAndroid Build Coastguard Worker 		}
2139*48a54d36SAndroid Build Coastguard Worker 
2140*48a54d36SAndroid Build Coastguard Worker 		curr = curr->next;
2141*48a54d36SAndroid Build Coastguard Worker 	}
2142*48a54d36SAndroid Build Coastguard Worker 
2143*48a54d36SAndroid Build Coastguard Worker 	return 0;
2144*48a54d36SAndroid Build Coastguard Worker }
2145*48a54d36SAndroid Build Coastguard Worker 
2146*48a54d36SAndroid Build Coastguard Worker //----------
2147*48a54d36SAndroid Build Coastguard Worker // Types and Constants
2148*48a54d36SAndroid Build Coastguard Worker 
2149*48a54d36SAndroid Build Coastguard Worker static const char * k_local_suffix = "local";
2150*48a54d36SAndroid Build Coastguard Worker static const char k_dns_separator = '.';
2151*48a54d36SAndroid Build Coastguard Worker 
2152*48a54d36SAndroid Build Coastguard Worker static const int k_label_maxlen = DNS_LABEL_MAXLEN;
2153*48a54d36SAndroid Build Coastguard Worker 	// Label entries longer than this are actually pointers.
2154*48a54d36SAndroid Build Coastguard Worker 
2155*48a54d36SAndroid Build Coastguard Worker typedef struct
2156*48a54d36SAndroid Build Coastguard Worker {
2157*48a54d36SAndroid Build Coastguard Worker 	int value;
2158*48a54d36SAndroid Build Coastguard Worker 	const char * name;
2159*48a54d36SAndroid Build Coastguard Worker 	const char * comment;
2160*48a54d36SAndroid Build Coastguard Worker } table_entry_t;
2161*48a54d36SAndroid Build Coastguard Worker 
2162*48a54d36SAndroid Build Coastguard Worker static const table_entry_t k_table_af [] =
2163*48a54d36SAndroid Build Coastguard Worker 	{
2164*48a54d36SAndroid Build Coastguard Worker 		{ AF_UNSPEC, NULL, NULL },
2165*48a54d36SAndroid Build Coastguard Worker 		{ AF_LOCAL, "LOCAL", NULL },
2166*48a54d36SAndroid Build Coastguard Worker 		{ AF_UNIX, "UNIX", NULL },
2167*48a54d36SAndroid Build Coastguard Worker 		{ AF_INET, "INET", NULL },
2168*48a54d36SAndroid Build Coastguard Worker 		{ AF_INET6, "INET6", NULL }
2169*48a54d36SAndroid Build Coastguard Worker 	};
2170*48a54d36SAndroid Build Coastguard Worker static const int k_table_af_size =
2171*48a54d36SAndroid Build Coastguard Worker 	sizeof (k_table_af) / sizeof (* k_table_af);
2172*48a54d36SAndroid Build Coastguard Worker 
2173*48a54d36SAndroid Build Coastguard Worker static const char * k_table_ns_class [] =
2174*48a54d36SAndroid Build Coastguard Worker 	{
2175*48a54d36SAndroid Build Coastguard Worker 		NULL,
2176*48a54d36SAndroid Build Coastguard Worker 		"IN"
2177*48a54d36SAndroid Build Coastguard Worker 	};
2178*48a54d36SAndroid Build Coastguard Worker static const int k_table_ns_class_size =
2179*48a54d36SAndroid Build Coastguard Worker 	sizeof (k_table_ns_class) / sizeof (* k_table_ns_class);
2180*48a54d36SAndroid Build Coastguard Worker 
2181*48a54d36SAndroid Build Coastguard Worker static const char * k_table_ns_type [] =
2182*48a54d36SAndroid Build Coastguard Worker 	{
2183*48a54d36SAndroid Build Coastguard Worker 		NULL,
2184*48a54d36SAndroid Build Coastguard Worker 		"A",
2185*48a54d36SAndroid Build Coastguard Worker 		"NS",
2186*48a54d36SAndroid Build Coastguard Worker 		"MD",
2187*48a54d36SAndroid Build Coastguard Worker 		"MF",
2188*48a54d36SAndroid Build Coastguard Worker 		"CNAME",
2189*48a54d36SAndroid Build Coastguard Worker 		"SOA",
2190*48a54d36SAndroid Build Coastguard Worker 		"MB",
2191*48a54d36SAndroid Build Coastguard Worker 		"MG",
2192*48a54d36SAndroid Build Coastguard Worker 		"MR",
2193*48a54d36SAndroid Build Coastguard Worker 		"NULL",
2194*48a54d36SAndroid Build Coastguard Worker 		"WKS",
2195*48a54d36SAndroid Build Coastguard Worker 		"PTR",
2196*48a54d36SAndroid Build Coastguard Worker 		"HINFO",
2197*48a54d36SAndroid Build Coastguard Worker 		"MINFO",
2198*48a54d36SAndroid Build Coastguard Worker 		"MX",
2199*48a54d36SAndroid Build Coastguard Worker 		"TXT",
2200*48a54d36SAndroid Build Coastguard Worker 		"RP",
2201*48a54d36SAndroid Build Coastguard Worker 		"AFSDB",
2202*48a54d36SAndroid Build Coastguard Worker 		"X25",
2203*48a54d36SAndroid Build Coastguard Worker 		"ISDN",
2204*48a54d36SAndroid Build Coastguard Worker 		"RT",
2205*48a54d36SAndroid Build Coastguard Worker 		"NSAP",
2206*48a54d36SAndroid Build Coastguard Worker 		NULL,
2207*48a54d36SAndroid Build Coastguard Worker 		"SIG",
2208*48a54d36SAndroid Build Coastguard Worker 		"KEY",
2209*48a54d36SAndroid Build Coastguard Worker 		"PX",
2210*48a54d36SAndroid Build Coastguard Worker 		"GPOS",
2211*48a54d36SAndroid Build Coastguard Worker 		"AAAA",
2212*48a54d36SAndroid Build Coastguard Worker 		"LOC",
2213*48a54d36SAndroid Build Coastguard Worker 		"NXT",
2214*48a54d36SAndroid Build Coastguard Worker 		"EID",
2215*48a54d36SAndroid Build Coastguard Worker 		"NIMLOC",
2216*48a54d36SAndroid Build Coastguard Worker 		"SRV",
2217*48a54d36SAndroid Build Coastguard Worker 		"ATMA",
2218*48a54d36SAndroid Build Coastguard Worker 		"NAPTR",
2219*48a54d36SAndroid Build Coastguard Worker 		"KX",
2220*48a54d36SAndroid Build Coastguard Worker 		"CERT",
2221*48a54d36SAndroid Build Coastguard Worker 		"A6",
2222*48a54d36SAndroid Build Coastguard Worker 		"DNAME",
2223*48a54d36SAndroid Build Coastguard Worker 		"SINK",
2224*48a54d36SAndroid Build Coastguard Worker 		"OPT"
2225*48a54d36SAndroid Build Coastguard Worker 	};
2226*48a54d36SAndroid Build Coastguard Worker static const int k_table_ns_type_size =
2227*48a54d36SAndroid Build Coastguard Worker 	sizeof (k_table_ns_type) / sizeof (* k_table_ns_type);
2228*48a54d36SAndroid Build Coastguard Worker 
2229*48a54d36SAndroid Build Coastguard Worker 
2230*48a54d36SAndroid Build Coastguard Worker //----------
2231*48a54d36SAndroid Build Coastguard Worker // Local prototypes
2232*48a54d36SAndroid Build Coastguard Worker 
2233*48a54d36SAndroid Build Coastguard Worker static int
2234*48a54d36SAndroid Build Coastguard Worker simple_table_index (const char * table [], int size, const char * str);
2235*48a54d36SAndroid Build Coastguard Worker 
2236*48a54d36SAndroid Build Coastguard Worker static int
2237*48a54d36SAndroid Build Coastguard Worker table_index_name (const table_entry_t table [], int size, const char * str);
2238*48a54d36SAndroid Build Coastguard Worker 
2239*48a54d36SAndroid Build Coastguard Worker static int
2240*48a54d36SAndroid Build Coastguard Worker table_index_value (const table_entry_t table [], int size, int n);
2241*48a54d36SAndroid Build Coastguard Worker 
2242*48a54d36SAndroid Build Coastguard Worker 
2243*48a54d36SAndroid Build Coastguard Worker //----------
2244*48a54d36SAndroid Build Coastguard Worker // Global variables
2245*48a54d36SAndroid Build Coastguard Worker 
2246*48a54d36SAndroid Build Coastguard Worker 
2247*48a54d36SAndroid Build Coastguard Worker //----------
2248*48a54d36SAndroid Build Coastguard Worker // Util functions
2249*48a54d36SAndroid Build Coastguard Worker 
2250*48a54d36SAndroid Build Coastguard Worker int
count_dots(const char * name)2251*48a54d36SAndroid Build Coastguard Worker count_dots (const char * name)
2252*48a54d36SAndroid Build Coastguard Worker {
2253*48a54d36SAndroid Build Coastguard Worker 	int count = 0;
2254*48a54d36SAndroid Build Coastguard Worker 	int i;
2255*48a54d36SAndroid Build Coastguard Worker 	for (i = 0; name[i]; i++)
2256*48a54d36SAndroid Build Coastguard Worker 	{
2257*48a54d36SAndroid Build Coastguard Worker 		if (name [i] == k_dns_separator)
2258*48a54d36SAndroid Build Coastguard Worker 			count++;
2259*48a54d36SAndroid Build Coastguard Worker 	}
2260*48a54d36SAndroid Build Coastguard Worker 
2261*48a54d36SAndroid Build Coastguard Worker 	return count;
2262*48a54d36SAndroid Build Coastguard Worker }
2263*48a54d36SAndroid Build Coastguard Worker 
2264*48a54d36SAndroid Build Coastguard Worker 
2265*48a54d36SAndroid Build Coastguard Worker int
islocal(const char * name)2266*48a54d36SAndroid Build Coastguard Worker islocal (const char * name)
2267*48a54d36SAndroid Build Coastguard Worker {
2268*48a54d36SAndroid Build Coastguard Worker 	return cmp_dns_suffix (name, k_local_suffix) > 0;
2269*48a54d36SAndroid Build Coastguard Worker }
2270*48a54d36SAndroid Build Coastguard Worker 
2271*48a54d36SAndroid Build Coastguard Worker 
2272*48a54d36SAndroid Build Coastguard Worker int
rr_to_af(ns_type_t rrtype)2273*48a54d36SAndroid Build Coastguard Worker rr_to_af (ns_type_t rrtype)
2274*48a54d36SAndroid Build Coastguard Worker {
2275*48a54d36SAndroid Build Coastguard Worker 	switch (rrtype)
2276*48a54d36SAndroid Build Coastguard Worker 	{
2277*48a54d36SAndroid Build Coastguard Worker 	  case kDNSServiceType_A:
2278*48a54d36SAndroid Build Coastguard Worker 		return AF_INET;
2279*48a54d36SAndroid Build Coastguard Worker 
2280*48a54d36SAndroid Build Coastguard Worker 	  case kDNSServiceType_AAAA:
2281*48a54d36SAndroid Build Coastguard Worker 		return AF_INET6;
2282*48a54d36SAndroid Build Coastguard Worker 
2283*48a54d36SAndroid Build Coastguard Worker 	  default:
2284*48a54d36SAndroid Build Coastguard Worker 		return AF_UNSPEC;
2285*48a54d36SAndroid Build Coastguard Worker 	}
2286*48a54d36SAndroid Build Coastguard Worker }
2287*48a54d36SAndroid Build Coastguard Worker 
2288*48a54d36SAndroid Build Coastguard Worker 
2289*48a54d36SAndroid Build Coastguard Worker ns_type_t
af_to_rr(int af)2290*48a54d36SAndroid Build Coastguard Worker af_to_rr (int af)
2291*48a54d36SAndroid Build Coastguard Worker {
2292*48a54d36SAndroid Build Coastguard Worker 	switch (af)
2293*48a54d36SAndroid Build Coastguard Worker 	{
2294*48a54d36SAndroid Build Coastguard Worker 	  case AF_INET:
2295*48a54d36SAndroid Build Coastguard Worker 		return kDNSServiceType_A;
2296*48a54d36SAndroid Build Coastguard Worker 
2297*48a54d36SAndroid Build Coastguard Worker 	  case AF_INET6:
2298*48a54d36SAndroid Build Coastguard Worker 		return kDNSServiceType_AAAA;
2299*48a54d36SAndroid Build Coastguard Worker 
2300*48a54d36SAndroid Build Coastguard Worker 	  default:
2301*48a54d36SAndroid Build Coastguard Worker 		//return ns_t_invalid;
2302*48a54d36SAndroid Build Coastguard Worker 		return 0;
2303*48a54d36SAndroid Build Coastguard Worker 	}
2304*48a54d36SAndroid Build Coastguard Worker }
2305*48a54d36SAndroid Build Coastguard Worker 
2306*48a54d36SAndroid Build Coastguard Worker 
2307*48a54d36SAndroid Build Coastguard Worker int
str_to_af(const char * str)2308*48a54d36SAndroid Build Coastguard Worker str_to_af (const char * str)
2309*48a54d36SAndroid Build Coastguard Worker {
2310*48a54d36SAndroid Build Coastguard Worker 	int result =
2311*48a54d36SAndroid Build Coastguard Worker 		table_index_name (k_table_af, k_table_af_size, str);
2312*48a54d36SAndroid Build Coastguard Worker 	if (result < 0)
2313*48a54d36SAndroid Build Coastguard Worker 		result = 0;
2314*48a54d36SAndroid Build Coastguard Worker 
2315*48a54d36SAndroid Build Coastguard Worker 	return k_table_af [result].value;
2316*48a54d36SAndroid Build Coastguard Worker }
2317*48a54d36SAndroid Build Coastguard Worker 
2318*48a54d36SAndroid Build Coastguard Worker 
2319*48a54d36SAndroid Build Coastguard Worker ns_class_t
str_to_ns_class(const char * str)2320*48a54d36SAndroid Build Coastguard Worker str_to_ns_class (const char * str)
2321*48a54d36SAndroid Build Coastguard Worker {
2322*48a54d36SAndroid Build Coastguard Worker 	return (ns_class_t)
2323*48a54d36SAndroid Build Coastguard Worker 		simple_table_index (k_table_ns_class, k_table_ns_class_size, str);
2324*48a54d36SAndroid Build Coastguard Worker }
2325*48a54d36SAndroid Build Coastguard Worker 
2326*48a54d36SAndroid Build Coastguard Worker 
2327*48a54d36SAndroid Build Coastguard Worker ns_type_t
str_to_ns_type(const char * str)2328*48a54d36SAndroid Build Coastguard Worker str_to_ns_type (const char * str)
2329*48a54d36SAndroid Build Coastguard Worker {
2330*48a54d36SAndroid Build Coastguard Worker 	return (ns_type_t)
2331*48a54d36SAndroid Build Coastguard Worker 		simple_table_index (k_table_ns_type, k_table_ns_type_size, str);
2332*48a54d36SAndroid Build Coastguard Worker }
2333*48a54d36SAndroid Build Coastguard Worker 
2334*48a54d36SAndroid Build Coastguard Worker 
2335*48a54d36SAndroid Build Coastguard Worker const char *
af_to_str(int in)2336*48a54d36SAndroid Build Coastguard Worker af_to_str (int in)
2337*48a54d36SAndroid Build Coastguard Worker {
2338*48a54d36SAndroid Build Coastguard Worker 	int result =
2339*48a54d36SAndroid Build Coastguard Worker 		table_index_value (k_table_af, k_table_af_size, in);
2340*48a54d36SAndroid Build Coastguard Worker 	if (result < 0)
2341*48a54d36SAndroid Build Coastguard Worker 		result = 0;
2342*48a54d36SAndroid Build Coastguard Worker 
2343*48a54d36SAndroid Build Coastguard Worker 	return k_table_af [result].name;
2344*48a54d36SAndroid Build Coastguard Worker }
2345*48a54d36SAndroid Build Coastguard Worker 
2346*48a54d36SAndroid Build Coastguard Worker 
2347*48a54d36SAndroid Build Coastguard Worker const char *
ns_class_to_str(ns_class_t in)2348*48a54d36SAndroid Build Coastguard Worker ns_class_to_str (ns_class_t in)
2349*48a54d36SAndroid Build Coastguard Worker {
2350*48a54d36SAndroid Build Coastguard Worker 	if (in < k_table_ns_class_size)
2351*48a54d36SAndroid Build Coastguard Worker 		return k_table_ns_class [in];
2352*48a54d36SAndroid Build Coastguard Worker 	else
2353*48a54d36SAndroid Build Coastguard Worker 		return NULL;
2354*48a54d36SAndroid Build Coastguard Worker }
2355*48a54d36SAndroid Build Coastguard Worker 
2356*48a54d36SAndroid Build Coastguard Worker 
2357*48a54d36SAndroid Build Coastguard Worker const char *
ns_type_to_str(ns_type_t in)2358*48a54d36SAndroid Build Coastguard Worker ns_type_to_str (ns_type_t in)
2359*48a54d36SAndroid Build Coastguard Worker {
2360*48a54d36SAndroid Build Coastguard Worker 	if (in < k_table_ns_type_size)
2361*48a54d36SAndroid Build Coastguard Worker 		return k_table_ns_type [in];
2362*48a54d36SAndroid Build Coastguard Worker 	else
2363*48a54d36SAndroid Build Coastguard Worker 		return NULL;
2364*48a54d36SAndroid Build Coastguard Worker }
2365*48a54d36SAndroid Build Coastguard Worker 
2366*48a54d36SAndroid Build Coastguard Worker 
2367*48a54d36SAndroid Build Coastguard Worker char *
format_reverse_addr_in(const struct in_addr * addr,int prefixlen,char * buf)2368*48a54d36SAndroid Build Coastguard Worker format_reverse_addr_in (
2369*48a54d36SAndroid Build Coastguard Worker 	const struct in_addr * addr,
2370*48a54d36SAndroid Build Coastguard Worker 	int prefixlen,
2371*48a54d36SAndroid Build Coastguard Worker 	char * buf
2372*48a54d36SAndroid Build Coastguard Worker )
2373*48a54d36SAndroid Build Coastguard Worker {
2374*48a54d36SAndroid Build Coastguard Worker 	char * curr = buf;
2375*48a54d36SAndroid Build Coastguard Worker 	int i;
2376*48a54d36SAndroid Build Coastguard Worker 
2377*48a54d36SAndroid Build Coastguard Worker 	const uint8_t * in_addr_a = (uint8_t *) addr;
2378*48a54d36SAndroid Build Coastguard Worker 
2379*48a54d36SAndroid Build Coastguard Worker 	if (prefixlen > 32)
2380*48a54d36SAndroid Build Coastguard Worker 		return NULL;
2381*48a54d36SAndroid Build Coastguard Worker 	if (prefixlen < 0)
2382*48a54d36SAndroid Build Coastguard Worker 		prefixlen = 32;
2383*48a54d36SAndroid Build Coastguard Worker 
2384*48a54d36SAndroid Build Coastguard Worker 	i = (prefixlen + 7) / 8;
2385*48a54d36SAndroid Build Coastguard Worker 		// divide prefixlen into bytes, rounding up
2386*48a54d36SAndroid Build Coastguard Worker 
2387*48a54d36SAndroid Build Coastguard Worker 	while (i > 0)
2388*48a54d36SAndroid Build Coastguard Worker 	{
2389*48a54d36SAndroid Build Coastguard Worker 		i--;
2390*48a54d36SAndroid Build Coastguard Worker 		curr += sprintf (curr, "%d.", in_addr_a [i]);
2391*48a54d36SAndroid Build Coastguard Worker 	}
2392*48a54d36SAndroid Build Coastguard Worker 	sprintf (curr, "in-addr.arpa");
2393*48a54d36SAndroid Build Coastguard Worker 
2394*48a54d36SAndroid Build Coastguard Worker 	return buf;
2395*48a54d36SAndroid Build Coastguard Worker }
2396*48a54d36SAndroid Build Coastguard Worker 
2397*48a54d36SAndroid Build Coastguard Worker 
2398*48a54d36SAndroid Build Coastguard Worker char *
format_reverse_addr_in6(const struct in6_addr * addr,int prefixlen,char * buf)2399*48a54d36SAndroid Build Coastguard Worker format_reverse_addr_in6 (
2400*48a54d36SAndroid Build Coastguard Worker 	const struct in6_addr * addr,
2401*48a54d36SAndroid Build Coastguard Worker 	int prefixlen,
2402*48a54d36SAndroid Build Coastguard Worker 	char * buf
2403*48a54d36SAndroid Build Coastguard Worker )
2404*48a54d36SAndroid Build Coastguard Worker {
2405*48a54d36SAndroid Build Coastguard Worker 	char * curr = buf;
2406*48a54d36SAndroid Build Coastguard Worker 	int i;
2407*48a54d36SAndroid Build Coastguard Worker 
2408*48a54d36SAndroid Build Coastguard Worker 	const uint8_t * in_addr_a = (uint8_t *) addr;
2409*48a54d36SAndroid Build Coastguard Worker 
2410*48a54d36SAndroid Build Coastguard Worker 	if (prefixlen > 128)
2411*48a54d36SAndroid Build Coastguard Worker 		return NULL;
2412*48a54d36SAndroid Build Coastguard Worker 	if (prefixlen < 0)
2413*48a54d36SAndroid Build Coastguard Worker 		prefixlen = 128;
2414*48a54d36SAndroid Build Coastguard Worker 
2415*48a54d36SAndroid Build Coastguard Worker 	i = (prefixlen + 3) / 4;
2416*48a54d36SAndroid Build Coastguard Worker 		// divide prefixlen into nibbles, rounding up
2417*48a54d36SAndroid Build Coastguard Worker 
2418*48a54d36SAndroid Build Coastguard Worker 	// Special handling for first
2419*48a54d36SAndroid Build Coastguard Worker 	if (i % 2)
2420*48a54d36SAndroid Build Coastguard Worker 	{
2421*48a54d36SAndroid Build Coastguard Worker 		curr += sprintf (curr, "%d.", (in_addr_a [i/2] >> 4) & 0x0F);
2422*48a54d36SAndroid Build Coastguard Worker 	}
2423*48a54d36SAndroid Build Coastguard Worker 	i >>= 1;
2424*48a54d36SAndroid Build Coastguard Worker 		// Convert i to bytes (divide by 2)
2425*48a54d36SAndroid Build Coastguard Worker 
2426*48a54d36SAndroid Build Coastguard Worker 	while (i > 0)
2427*48a54d36SAndroid Build Coastguard Worker 	{
2428*48a54d36SAndroid Build Coastguard Worker 		uint8_t val;
2429*48a54d36SAndroid Build Coastguard Worker 
2430*48a54d36SAndroid Build Coastguard Worker 		i--;
2431*48a54d36SAndroid Build Coastguard Worker 		val = in_addr_a [i];
2432*48a54d36SAndroid Build Coastguard Worker 		curr += sprintf (curr, "%x.%x.", val & 0x0F, (val >> 4) & 0x0F);
2433*48a54d36SAndroid Build Coastguard Worker 	}
2434*48a54d36SAndroid Build Coastguard Worker 	sprintf (curr, "ip6.arpa");
2435*48a54d36SAndroid Build Coastguard Worker 
2436*48a54d36SAndroid Build Coastguard Worker 	return buf;
2437*48a54d36SAndroid Build Coastguard Worker }
2438*48a54d36SAndroid Build Coastguard Worker 
2439*48a54d36SAndroid Build Coastguard Worker 
2440*48a54d36SAndroid Build Coastguard Worker char *
format_reverse_addr(int af,const void * addr,int prefixlen,char * buf)2441*48a54d36SAndroid Build Coastguard Worker format_reverse_addr (
2442*48a54d36SAndroid Build Coastguard Worker 	int af,
2443*48a54d36SAndroid Build Coastguard Worker 	const void * addr,
2444*48a54d36SAndroid Build Coastguard Worker 	int prefixlen,
2445*48a54d36SAndroid Build Coastguard Worker 	char * buf
2446*48a54d36SAndroid Build Coastguard Worker )
2447*48a54d36SAndroid Build Coastguard Worker {
2448*48a54d36SAndroid Build Coastguard Worker 	switch (af)
2449*48a54d36SAndroid Build Coastguard Worker 	{
2450*48a54d36SAndroid Build Coastguard Worker 	  case AF_INET:
2451*48a54d36SAndroid Build Coastguard Worker 		return
2452*48a54d36SAndroid Build Coastguard Worker 			format_reverse_addr_in (
2453*48a54d36SAndroid Build Coastguard Worker 				(struct in_addr *) addr, prefixlen, buf
2454*48a54d36SAndroid Build Coastguard Worker 			);
2455*48a54d36SAndroid Build Coastguard Worker 		break;
2456*48a54d36SAndroid Build Coastguard Worker 
2457*48a54d36SAndroid Build Coastguard Worker 	  case AF_INET6:
2458*48a54d36SAndroid Build Coastguard Worker 		return
2459*48a54d36SAndroid Build Coastguard Worker 			format_reverse_addr_in6 (
2460*48a54d36SAndroid Build Coastguard Worker 				(struct in6_addr *) addr, prefixlen, buf
2461*48a54d36SAndroid Build Coastguard Worker 			);
2462*48a54d36SAndroid Build Coastguard Worker 		break;
2463*48a54d36SAndroid Build Coastguard Worker 
2464*48a54d36SAndroid Build Coastguard Worker 	  default:
2465*48a54d36SAndroid Build Coastguard Worker 		return NULL;
2466*48a54d36SAndroid Build Coastguard Worker 	}
2467*48a54d36SAndroid Build Coastguard Worker }
2468*48a54d36SAndroid Build Coastguard Worker 
2469*48a54d36SAndroid Build Coastguard Worker 
2470*48a54d36SAndroid Build Coastguard Worker int
cmp_dns_suffix(const char * name,const char * domain)2471*48a54d36SAndroid Build Coastguard Worker cmp_dns_suffix (const char * name, const char * domain)
2472*48a54d36SAndroid Build Coastguard Worker {
2473*48a54d36SAndroid Build Coastguard Worker 	const char * nametail;
2474*48a54d36SAndroid Build Coastguard Worker 	const char * domaintail;
2475*48a54d36SAndroid Build Coastguard Worker 
2476*48a54d36SAndroid Build Coastguard Worker 	// Idiot checks
2477*48a54d36SAndroid Build Coastguard Worker 	if (*name == 0 || *name == k_dns_separator)
2478*48a54d36SAndroid Build Coastguard Worker 	{
2479*48a54d36SAndroid Build Coastguard Worker 		// Name can't be empty or start with separator
2480*48a54d36SAndroid Build Coastguard Worker 		return CMP_DNS_SUFFIX_BAD_NAME;
2481*48a54d36SAndroid Build Coastguard Worker 	}
2482*48a54d36SAndroid Build Coastguard Worker 
2483*48a54d36SAndroid Build Coastguard Worker 	if (*domain == 0)
2484*48a54d36SAndroid Build Coastguard Worker 	{
2485*48a54d36SAndroid Build Coastguard Worker 		return CMP_DNS_SUFFIX_SUCCESS;
2486*48a54d36SAndroid Build Coastguard Worker 			// trivially true
2487*48a54d36SAndroid Build Coastguard Worker 	}
2488*48a54d36SAndroid Build Coastguard Worker 
2489*48a54d36SAndroid Build Coastguard Worker 	if (*domain == k_dns_separator)
2490*48a54d36SAndroid Build Coastguard Worker 	{
2491*48a54d36SAndroid Build Coastguard Worker 		// drop leading separator from domain
2492*48a54d36SAndroid Build Coastguard Worker 		domain++;
2493*48a54d36SAndroid Build Coastguard Worker 		if (*domain == k_dns_separator)
2494*48a54d36SAndroid Build Coastguard Worker 		{
2495*48a54d36SAndroid Build Coastguard Worker 			return CMP_DNS_SUFFIX_BAD_DOMAIN;
2496*48a54d36SAndroid Build Coastguard Worker 		}
2497*48a54d36SAndroid Build Coastguard Worker 	}
2498*48a54d36SAndroid Build Coastguard Worker 
2499*48a54d36SAndroid Build Coastguard Worker 	// Find ends of strings
2500*48a54d36SAndroid Build Coastguard Worker 	for (nametail = name; *nametail; nametail++)
2501*48a54d36SAndroid Build Coastguard Worker 		;
2502*48a54d36SAndroid Build Coastguard Worker 	for (domaintail = domain; *domaintail; domaintail++)
2503*48a54d36SAndroid Build Coastguard Worker 		;
2504*48a54d36SAndroid Build Coastguard Worker 
2505*48a54d36SAndroid Build Coastguard Worker 	// Shuffle back to last real character, and drop any trailing '.'
2506*48a54d36SAndroid Build Coastguard Worker 	// while we're at it.
2507*48a54d36SAndroid Build Coastguard Worker 	nametail --;
2508*48a54d36SAndroid Build Coastguard Worker 	if (*nametail == k_dns_separator)
2509*48a54d36SAndroid Build Coastguard Worker 	{
2510*48a54d36SAndroid Build Coastguard Worker 		nametail --;
2511*48a54d36SAndroid Build Coastguard Worker 		if (*nametail == k_dns_separator)
2512*48a54d36SAndroid Build Coastguard Worker 		{
2513*48a54d36SAndroid Build Coastguard Worker 			return CMP_DNS_SUFFIX_BAD_NAME;
2514*48a54d36SAndroid Build Coastguard Worker 		}
2515*48a54d36SAndroid Build Coastguard Worker 	}
2516*48a54d36SAndroid Build Coastguard Worker 	domaintail --;
2517*48a54d36SAndroid Build Coastguard Worker 	if (*domaintail == k_dns_separator)
2518*48a54d36SAndroid Build Coastguard Worker 	{
2519*48a54d36SAndroid Build Coastguard Worker 		domaintail --;
2520*48a54d36SAndroid Build Coastguard Worker 		if (*domaintail == k_dns_separator)
2521*48a54d36SAndroid Build Coastguard Worker 		{
2522*48a54d36SAndroid Build Coastguard Worker 			return CMP_DNS_SUFFIX_BAD_DOMAIN;
2523*48a54d36SAndroid Build Coastguard Worker 		}
2524*48a54d36SAndroid Build Coastguard Worker 	}
2525*48a54d36SAndroid Build Coastguard Worker 
2526*48a54d36SAndroid Build Coastguard Worker 	// Compare.
2527*48a54d36SAndroid Build Coastguard Worker 	while (
2528*48a54d36SAndroid Build Coastguard Worker 		nametail >= name
2529*48a54d36SAndroid Build Coastguard Worker 		&& domaintail >= domain
2530*48a54d36SAndroid Build Coastguard Worker 		&& tolower(*nametail) == tolower(*domaintail))
2531*48a54d36SAndroid Build Coastguard Worker 	{
2532*48a54d36SAndroid Build Coastguard Worker 		nametail--;
2533*48a54d36SAndroid Build Coastguard Worker 		domaintail--;
2534*48a54d36SAndroid Build Coastguard Worker 	}
2535*48a54d36SAndroid Build Coastguard Worker 
2536*48a54d36SAndroid Build Coastguard Worker 	/* A successful finish will be one of the following:
2537*48a54d36SAndroid Build Coastguard Worker 		(leading and trailing . ignored)
2538*48a54d36SAndroid Build Coastguard Worker 
2539*48a54d36SAndroid Build Coastguard Worker 		name  :  domain2.domain1
2540*48a54d36SAndroid Build Coastguard Worker 		domain:  domain2.domain1
2541*48a54d36SAndroid Build Coastguard Worker 		        ^
2542*48a54d36SAndroid Build Coastguard Worker 
2543*48a54d36SAndroid Build Coastguard Worker 		name  : domain3.domain2.domain1
2544*48a54d36SAndroid Build Coastguard Worker 		domain:         domain2.domain1
2545*48a54d36SAndroid Build Coastguard Worker 		               ^
2546*48a54d36SAndroid Build Coastguard Worker 	 */
2547*48a54d36SAndroid Build Coastguard Worker 	if (
2548*48a54d36SAndroid Build Coastguard Worker 		domaintail < domain
2549*48a54d36SAndroid Build Coastguard Worker 		&& (nametail < name || *nametail == k_dns_separator)
2550*48a54d36SAndroid Build Coastguard Worker 	)
2551*48a54d36SAndroid Build Coastguard Worker 	{
2552*48a54d36SAndroid Build Coastguard Worker 		return CMP_DNS_SUFFIX_SUCCESS;
2553*48a54d36SAndroid Build Coastguard Worker 	}
2554*48a54d36SAndroid Build Coastguard Worker 	else
2555*48a54d36SAndroid Build Coastguard Worker 	{
2556*48a54d36SAndroid Build Coastguard Worker 		return CMP_DNS_SUFFIX_FAILURE;
2557*48a54d36SAndroid Build Coastguard Worker 	}
2558*48a54d36SAndroid Build Coastguard Worker }
2559*48a54d36SAndroid Build Coastguard Worker 
2560*48a54d36SAndroid Build Coastguard Worker 
2561*48a54d36SAndroid Build Coastguard Worker int
dns_rdata_to_name(const char * rdata,int rdlen,char * name,int name_len)2562*48a54d36SAndroid Build Coastguard Worker dns_rdata_to_name (const char * rdata, int rdlen, char * name, int name_len)
2563*48a54d36SAndroid Build Coastguard Worker {
2564*48a54d36SAndroid Build Coastguard Worker 	int i = 0;
2565*48a54d36SAndroid Build Coastguard Worker 		// Index into 'name'
2566*48a54d36SAndroid Build Coastguard Worker 	const char * rdata_curr = rdata;
2567*48a54d36SAndroid Build Coastguard Worker 
2568*48a54d36SAndroid Build Coastguard Worker 	if (rdlen == 0) return DNS_RDATA_TO_NAME_BAD_FORMAT;
2569*48a54d36SAndroid Build Coastguard Worker 
2570*48a54d36SAndroid Build Coastguard Worker 	/*
2571*48a54d36SAndroid Build Coastguard Worker 		In RDATA, a DNS name is stored as a series of labels.
2572*48a54d36SAndroid Build Coastguard Worker 		Each label consists of a length octet (max value 63)
2573*48a54d36SAndroid Build Coastguard Worker 		followed by the data for that label.
2574*48a54d36SAndroid Build Coastguard Worker 		The series is terminated with a length 0 octet.
2575*48a54d36SAndroid Build Coastguard Worker 		A length octet beginning with bits 11 is a pointer to
2576*48a54d36SAndroid Build Coastguard Worker 		somewhere else in the payload, but we don't support these
2577*48a54d36SAndroid Build Coastguard Worker 		since we don't have access to the entire payload.
2578*48a54d36SAndroid Build Coastguard Worker 
2579*48a54d36SAndroid Build Coastguard Worker 		See RFC1034 section 3.1 and RFC1035 section 3.1.
2580*48a54d36SAndroid Build Coastguard Worker 	 */
2581*48a54d36SAndroid Build Coastguard Worker 	while (1)
2582*48a54d36SAndroid Build Coastguard Worker 	{
2583*48a54d36SAndroid Build Coastguard Worker 		int term_len = *rdata_curr;
2584*48a54d36SAndroid Build Coastguard Worker 		rdata_curr++;
2585*48a54d36SAndroid Build Coastguard Worker 
2586*48a54d36SAndroid Build Coastguard Worker 		if (term_len == 0)
2587*48a54d36SAndroid Build Coastguard Worker 		{
2588*48a54d36SAndroid Build Coastguard Worker 			break;
2589*48a54d36SAndroid Build Coastguard Worker 				// 0 length record terminates label
2590*48a54d36SAndroid Build Coastguard Worker 		}
2591*48a54d36SAndroid Build Coastguard Worker 		else if (term_len > k_label_maxlen)
2592*48a54d36SAndroid Build Coastguard Worker 		{
2593*48a54d36SAndroid Build Coastguard Worker 			name [i] = 0;
2594*48a54d36SAndroid Build Coastguard Worker 			return DNS_RDATA_TO_NAME_PTR;
2595*48a54d36SAndroid Build Coastguard Worker 		}
2596*48a54d36SAndroid Build Coastguard Worker 		else if (rdata_curr + term_len > rdata + rdlen)
2597*48a54d36SAndroid Build Coastguard Worker 		{
2598*48a54d36SAndroid Build Coastguard Worker 			name [i] = 0;
2599*48a54d36SAndroid Build Coastguard Worker 			return DNS_RDATA_TO_NAME_BAD_FORMAT;
2600*48a54d36SAndroid Build Coastguard Worker 		}
2601*48a54d36SAndroid Build Coastguard Worker 
2602*48a54d36SAndroid Build Coastguard Worker 		if (name_len < i + term_len + 1)
2603*48a54d36SAndroid Build Coastguard Worker 			// +1 is separator
2604*48a54d36SAndroid Build Coastguard Worker 		{
2605*48a54d36SAndroid Build Coastguard Worker 			name [i] = 0;
2606*48a54d36SAndroid Build Coastguard Worker 			return DNS_RDATA_TO_NAME_TOO_LONG;
2607*48a54d36SAndroid Build Coastguard Worker 		}
2608*48a54d36SAndroid Build Coastguard Worker 
2609*48a54d36SAndroid Build Coastguard Worker 		memcpy (name + i, rdata_curr, term_len);
2610*48a54d36SAndroid Build Coastguard Worker 
2611*48a54d36SAndroid Build Coastguard Worker 		i += term_len;
2612*48a54d36SAndroid Build Coastguard Worker 		rdata_curr += term_len;
2613*48a54d36SAndroid Build Coastguard Worker 
2614*48a54d36SAndroid Build Coastguard Worker 		name [i] = k_dns_separator;
2615*48a54d36SAndroid Build Coastguard Worker 		i++;
2616*48a54d36SAndroid Build Coastguard Worker 	}
2617*48a54d36SAndroid Build Coastguard Worker 
2618*48a54d36SAndroid Build Coastguard Worker 	name [i] = 0;
2619*48a54d36SAndroid Build Coastguard Worker 	return i;
2620*48a54d36SAndroid Build Coastguard Worker }
2621*48a54d36SAndroid Build Coastguard Worker 
2622*48a54d36SAndroid Build Coastguard Worker 
2623*48a54d36SAndroid Build Coastguard Worker //----------
2624*48a54d36SAndroid Build Coastguard Worker // Local functions
2625*48a54d36SAndroid Build Coastguard Worker 
2626*48a54d36SAndroid Build Coastguard Worker /*
2627*48a54d36SAndroid Build Coastguard Worker 	Find the index of an string entry in a table.  A case insenitive match
2628*48a54d36SAndroid Build Coastguard Worker 	is performed.  If no entry is found, 0 is returned.
2629*48a54d36SAndroid Build Coastguard Worker 
2630*48a54d36SAndroid Build Coastguard Worker 	Parameters
2631*48a54d36SAndroid Build Coastguard Worker 		table
2632*48a54d36SAndroid Build Coastguard Worker 			Lookup table
2633*48a54d36SAndroid Build Coastguard Worker 			Table entries may be NULL.  NULL entries will never match.
2634*48a54d36SAndroid Build Coastguard Worker 		size
2635*48a54d36SAndroid Build Coastguard Worker 			number of entries in table
2636*48a54d36SAndroid Build Coastguard Worker 		str
2637*48a54d36SAndroid Build Coastguard Worker 			lookup string
2638*48a54d36SAndroid Build Coastguard Worker 
2639*48a54d36SAndroid Build Coastguard Worker 	Result
2640*48a54d36SAndroid Build Coastguard Worker 		index of first matching entry, or 0 if no matches
2641*48a54d36SAndroid Build Coastguard Worker  */
2642*48a54d36SAndroid Build Coastguard Worker static int
simple_table_index(const char * table[],int size,const char * str)2643*48a54d36SAndroid Build Coastguard Worker simple_table_index (const char * table [], int size, const char * str)
2644*48a54d36SAndroid Build Coastguard Worker {
2645*48a54d36SAndroid Build Coastguard Worker 	int i;
2646*48a54d36SAndroid Build Coastguard Worker 	for (i = 0; i < size; i++)
2647*48a54d36SAndroid Build Coastguard Worker 	{
2648*48a54d36SAndroid Build Coastguard Worker 		if (
2649*48a54d36SAndroid Build Coastguard Worker 			table [i]
2650*48a54d36SAndroid Build Coastguard Worker 			&& (strcasecmp (table [i], str) == 0)
2651*48a54d36SAndroid Build Coastguard Worker 		)
2652*48a54d36SAndroid Build Coastguard Worker 		{
2653*48a54d36SAndroid Build Coastguard Worker 			return i;
2654*48a54d36SAndroid Build Coastguard Worker 		}
2655*48a54d36SAndroid Build Coastguard Worker 	}
2656*48a54d36SAndroid Build Coastguard Worker 
2657*48a54d36SAndroid Build Coastguard Worker 	return 0;
2658*48a54d36SAndroid Build Coastguard Worker }
2659*48a54d36SAndroid Build Coastguard Worker 
2660*48a54d36SAndroid Build Coastguard Worker 
2661*48a54d36SAndroid Build Coastguard Worker /*
2662*48a54d36SAndroid Build Coastguard Worker 	Find the index of a name in a table.
2663*48a54d36SAndroid Build Coastguard Worker 
2664*48a54d36SAndroid Build Coastguard Worker 	Parameters
2665*48a54d36SAndroid Build Coastguard Worker 		table
2666*48a54d36SAndroid Build Coastguard Worker 			array of table_entry_t records.  The name field is compared
2667*48a54d36SAndroid Build Coastguard Worker 			(ignoring case) to the input string.
2668*48a54d36SAndroid Build Coastguard Worker 		size
2669*48a54d36SAndroid Build Coastguard Worker 			number of entries in table
2670*48a54d36SAndroid Build Coastguard Worker 		str
2671*48a54d36SAndroid Build Coastguard Worker 			lookup string
2672*48a54d36SAndroid Build Coastguard Worker 
2673*48a54d36SAndroid Build Coastguard Worker 	Result
2674*48a54d36SAndroid Build Coastguard Worker 		index of first matching entry, or -1 if no matches
2675*48a54d36SAndroid Build Coastguard Worker  */
2676*48a54d36SAndroid Build Coastguard Worker static int
table_index_name(const table_entry_t table[],int size,const char * str)2677*48a54d36SAndroid Build Coastguard Worker table_index_name (const table_entry_t table [], int size, const char * str)
2678*48a54d36SAndroid Build Coastguard Worker {
2679*48a54d36SAndroid Build Coastguard Worker 	int i;
2680*48a54d36SAndroid Build Coastguard Worker 	for (i = 0; i < size; i++)
2681*48a54d36SAndroid Build Coastguard Worker 	{
2682*48a54d36SAndroid Build Coastguard Worker 		if (
2683*48a54d36SAndroid Build Coastguard Worker 			table [i].name
2684*48a54d36SAndroid Build Coastguard Worker 			&& (strcasecmp (table [i].name, str) == 0)
2685*48a54d36SAndroid Build Coastguard Worker 		)
2686*48a54d36SAndroid Build Coastguard Worker 		{
2687*48a54d36SAndroid Build Coastguard Worker 			return i;
2688*48a54d36SAndroid Build Coastguard Worker 		}
2689*48a54d36SAndroid Build Coastguard Worker 	}
2690*48a54d36SAndroid Build Coastguard Worker 
2691*48a54d36SAndroid Build Coastguard Worker 	return -1;
2692*48a54d36SAndroid Build Coastguard Worker }
2693*48a54d36SAndroid Build Coastguard Worker 
2694*48a54d36SAndroid Build Coastguard Worker 
2695*48a54d36SAndroid Build Coastguard Worker /*
2696*48a54d36SAndroid Build Coastguard Worker 	Find the index of a value a table.
2697*48a54d36SAndroid Build Coastguard Worker 
2698*48a54d36SAndroid Build Coastguard Worker 	Parameters
2699*48a54d36SAndroid Build Coastguard Worker 		table
2700*48a54d36SAndroid Build Coastguard Worker 			array of table_entry_t records.  The value field is compared to
2701*48a54d36SAndroid Build Coastguard Worker 			the input value
2702*48a54d36SAndroid Build Coastguard Worker 		size
2703*48a54d36SAndroid Build Coastguard Worker 			number of entries in table
2704*48a54d36SAndroid Build Coastguard Worker 		n
2705*48a54d36SAndroid Build Coastguard Worker 			lookup value
2706*48a54d36SAndroid Build Coastguard Worker 
2707*48a54d36SAndroid Build Coastguard Worker 	Result
2708*48a54d36SAndroid Build Coastguard Worker 		index of first matching entry, or -1 if no matches
2709*48a54d36SAndroid Build Coastguard Worker  */
2710*48a54d36SAndroid Build Coastguard Worker static int
table_index_value(const table_entry_t table[],int size,int n)2711*48a54d36SAndroid Build Coastguard Worker table_index_value (const table_entry_t table [], int size, int n)
2712*48a54d36SAndroid Build Coastguard Worker {
2713*48a54d36SAndroid Build Coastguard Worker 	int i;
2714*48a54d36SAndroid Build Coastguard Worker 	for (i = 0; i < size; i++)
2715*48a54d36SAndroid Build Coastguard Worker 	{
2716*48a54d36SAndroid Build Coastguard Worker 		if (table [i].value == n)
2717*48a54d36SAndroid Build Coastguard Worker 		{
2718*48a54d36SAndroid Build Coastguard Worker 			return i;
2719*48a54d36SAndroid Build Coastguard Worker 		}
2720*48a54d36SAndroid Build Coastguard Worker 	}
2721*48a54d36SAndroid Build Coastguard Worker 
2722*48a54d36SAndroid Build Coastguard Worker 	return -1;
2723*48a54d36SAndroid Build Coastguard Worker }
2724