147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt/*
247e4cebad7397422144bb03a21f3f7682c062c4aRobert GreenwaltNICTA Public Software Licence
347e4cebad7397422144bb03a21f3f7682c062c4aRobert GreenwaltVersion 1.0
447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
547e4cebad7397422144bb03a21f3f7682c062c4aRobert GreenwaltCopyright © 2004 National ICT Australia Ltd
647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
747e4cebad7397422144bb03a21f3f7682c062c4aRobert GreenwaltAll rights reserved.
847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
947e4cebad7397422144bb03a21f3f7682c062c4aRobert GreenwaltBy this licence, National ICT Australia Ltd (NICTA) grants permission,
1047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltfree of charge, to any person who obtains a copy of this software
1147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltand any associated documentation files ("the Software") to use and
1247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltdeal with the Software in source code and binary forms without
1347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltrestriction, with or without modification, and to permit persons
1447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltto whom the Software is furnished to do so, provided that the
1547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltfollowing conditions are met:
1647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
1747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt- Redistributions of source code must retain the above copyright
1847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt  notice, this list of conditions and the following disclaimers.
1947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt- Redistributions in binary form must reproduce the above copyright
2047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt  notice, this list of conditions and the following disclaimers in
2147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt  the documentation and/or other materials provided with the
2247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt  distribution.
2347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt- The name of NICTA may not be used to endorse or promote products
2447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt  derived from this Software without specific prior written permission.
2547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
2647e4cebad7397422144bb03a21f3f7682c062c4aRobert GreenwaltEXCEPT AS EXPRESSLY STATED IN THIS LICENCE AND TO THE FULL EXTENT
2747e4cebad7397422144bb03a21f3f7682c062c4aRobert GreenwaltPERMITTED BY APPLICABLE LAW, THE SOFTWARE IS PROVIDED "AS-IS" AND
2847e4cebad7397422144bb03a21f3f7682c062c4aRobert GreenwaltNICTA MAKES NO REPRESENTATIONS, WARRANTIES OR CONDITIONS OF ANY
2947e4cebad7397422144bb03a21f3f7682c062c4aRobert GreenwaltKIND, EXPRESS OR IMPLIED, INCLUDING, WITHOUT LIMITATION, ANY
3047e4cebad7397422144bb03a21f3f7682c062c4aRobert GreenwaltREPRESENTATIONS, WARRANTIES OR CONDITIONS REGARDING THE CONTENTS
3147e4cebad7397422144bb03a21f3f7682c062c4aRobert GreenwaltOR ACCURACY OF THE SOFTWARE, OR OF TITLE, MERCHANTABILITY, FITNESS
3247e4cebad7397422144bb03a21f3f7682c062c4aRobert GreenwaltFOR A PARTICULAR PURPOSE, NONINFRINGEMENT, THE ABSENCE OF LATENT
3347e4cebad7397422144bb03a21f3f7682c062c4aRobert GreenwaltOR OTHER DEFECTS, OR THE PRESENCE OR ABSENCE OF ERRORS, WHETHER OR
3447e4cebad7397422144bb03a21f3f7682c062c4aRobert GreenwaltNOT DISCOVERABLE.
3547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
3647e4cebad7397422144bb03a21f3f7682c062c4aRobert GreenwaltTO THE FULL EXTENT PERMITTED BY APPLICABLE LAW, IN NO EVENT WILL
3747e4cebad7397422144bb03a21f3f7682c062c4aRobert GreenwaltNICTA BE LIABLE ON ANY LEGAL THEORY (INCLUDING, WITHOUT LIMITATION,
3847e4cebad7397422144bb03a21f3f7682c062c4aRobert GreenwaltNEGLIGENCE) FOR ANY LOSS OR DAMAGE WHATSOEVER, INCLUDING (WITHOUT
3947e4cebad7397422144bb03a21f3f7682c062c4aRobert GreenwaltLIMITATION) LOSS OF PRODUCTION OR OPERATION TIME, LOSS, DAMAGE OR
4047e4cebad7397422144bb03a21f3f7682c062c4aRobert GreenwaltCORRUPTION OF DATA OR RECORDS; OR LOSS OF ANTICIPATED SAVINGS,
4147e4cebad7397422144bb03a21f3f7682c062c4aRobert GreenwaltOPPORTUNITY, REVENUE, PROFIT OR GOODWILL, OR OTHER ECONOMIC LOSS;
4247e4cebad7397422144bb03a21f3f7682c062c4aRobert GreenwaltOR ANY SPECIAL, INCIDENTAL, INDIRECT, CONSEQUENTIAL, PUNITIVE OR
4347e4cebad7397422144bb03a21f3f7682c062c4aRobert GreenwaltEXEMPLARY DAMAGES ARISING OUT OF OR IN CONNECTION WITH THIS LICENCE,
4447e4cebad7397422144bb03a21f3f7682c062c4aRobert GreenwaltTHE SOFTWARE OR THE USE OF THE SOFTWARE, EVEN IF NICTA HAS BEEN
4547e4cebad7397422144bb03a21f3f7682c062c4aRobert GreenwaltADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
4647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
4747e4cebad7397422144bb03a21f3f7682c062c4aRobert GreenwaltIf applicable legislation implies warranties or conditions, or
4847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltimposes obligations or liability on NICTA in respect of the Software
4947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltthat cannot be wholly or partly excluded, restricted or modified,
5047e4cebad7397422144bb03a21f3f7682c062c4aRobert GreenwaltNICTA's liability is limited, to the full extent permitted by the
5147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltapplicable legislation, at its option, to:
5247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
5347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalta. in the case of goods, any one or more of the following:
5447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt  i.   the replacement of the goods or the supply of equivalent goods;
5547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt  ii.  the repair of the goods;
5647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt  iii. the payment of the cost of replacing the goods or of acquiring
5747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt       equivalent goods;
5847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt  iv.  the payment of the cost of having the goods repaired; or
5947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltb. in the case of services:
6047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt  i.   the supplying of the services again; or
6147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt  ii.  the payment of the cost of having the services supplied
6247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt       again.
6347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt */
6447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
6547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt/*
6647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	NSSwitch Implementation of mDNS interface.
6747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
6847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	Andrew White (Andrew.White@nicta.com.au)
6947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	May 2004
7047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt */
7147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
7247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#include <stdlib.h>
7347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#include <stdio.h>
7447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#include <string.h>
7547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#include <errno.h>
7647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#include <syslog.h>
7747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#include <pthread.h>
7847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#include <ctype.h>
7947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
8047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#include <sys/types.h>
8147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#include <sys/time.h>
8247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#include <sys/socket.h>
8347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
8447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#include <netinet/in.h>
8547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
8647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#include <arpa/inet.h>
8747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#define BIND_8_COMPAT 1
8847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#include <arpa/nameser.h>
8947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
9047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#include <dns_sd.h>
9147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
9247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
9347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt//----------
9447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt// Public functions
9547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
9647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt/*
9747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	Count the number of dots in a name string.
9847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt */
9947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltint
10047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltcount_dots (const char * name);
10147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
10247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
10347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt/*
10447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	Test whether a domain name is local.
10547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
10647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	Returns
10747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		1 if name ends with ".local" or ".local."
10847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		0 otherwise
10947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt */
11047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltint
11147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltislocal (const char * name);
11247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
11347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
11447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt/*
11547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	Format an address structure as a string appropriate for DNS reverse (PTR)
11647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	lookup, based on address type.
11747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
11847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	Parameters
11947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		prefixlen
12047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			Prefix length, in bits.  When formatting, this will be rounded up
12147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			to the nearest appropriate size.  If -1, assume maximum.
12247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		buf
12347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			Output buffer.  Must be long enough to hold largest possible
12447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			output.
12547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	Returns
12647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		Pointer to (first character of) output buffer,
12747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		or NULL on error.
12847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt */
12947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltchar *
13047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltformat_reverse_addr (int af, const void * addr, int prefixlen, char * buf);
13147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
13247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
13347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt/*
13447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	Format an address structure as a string appropriate for DNS reverse (PTR)
13547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	lookup for AF_INET.  Output is in .in-addr.arpa domain.
13647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
13747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	Parameters
13847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		prefixlen
13947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			Prefix length, in bits.  When formatting, this will be rounded up
14047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			to the nearest byte (8).  If -1, assume 32.
14147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		buf
14247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			Output buffer.  Must be long enough to hold largest possible
14347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			output.  For AF_INET, this is 29 characters (including null).
14447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	Returns
14547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		Pointer to (first character of) output buffer,
14647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		or NULL on error.
14747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt */
14847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltchar *
14947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltformat_reverse_addr_in (
15047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	const struct in_addr * addr,
15147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	int prefixlen,
15247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	char * buf
15347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt);
15447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#define DNS_PTR_AF_INET_SIZE 29
15547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
15647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt/*
15747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	Format an address structure as a string appropriate for DNS reverse (PTR)
15847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	lookup for AF_INET6.  Output is in .ip6.arpa domain.
15947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
16047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	Parameters
16147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		prefixlen
16247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			Prefix length, in bits.  When formatting, this will be rounded up
16347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			to the nearest nibble (4).  If -1, assume 128.
16447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		buf
16547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			Output buffer.  Must be long enough to hold largest possible
16647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			output.  For AF_INET6, this is 72 characters (including null).
16747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	Returns
16847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		Pointer to (first character of) output buffer,
16947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		or NULL on error.
17047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt */
17147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltchar *
17247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltformat_reverse_addr_in6 (
17347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	const struct in6_addr * addr,
17447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	int prefixlen,
17547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	char * buf
17647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt);
17747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#define DNS_PTR_AF_INET6_SIZE 72
17847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
17947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
18047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt/*
18147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	Compare whether the given dns name has the given domain suffix.
18247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	A single leading '.' on the name or leading or trailing '.' on the
18347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	domain is ignored for the purposes of the comparison.
18447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	Multiple leading or trailing '.'s are an error.  Other DNS syntax
18547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	errors are not checked for.  The comparison is case insensitive.
18647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
18747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	Returns
18847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		1 on success (match)
18947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		0 on failure (no match)
19047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		< 0 on error
19147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt */
19247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltint
19347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltcmp_dns_suffix (const char * name, const char * domain);
19447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltenum
19547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt{
19647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	CMP_DNS_SUFFIX_SUCCESS = 1,
19747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	CMP_DNS_SUFFIX_FAILURE = 0,
19847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	CMP_DNS_SUFFIX_BAD_NAME = 1,
19947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	CMP_DNS_SUFFIX_BAD_DOMAIN = -2
20047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt};
20147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
20247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalttypedef int ns_type_t;
20347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalttypedef int ns_class_t;
20447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
20547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt/*
20647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	Convert a DNS resource record (RR) code to an address family (AF) code.
20747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
20847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	Parameters
20947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		rrtype
21047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			resource record type (from nameser.h)
21147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
21247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	Returns
21347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		Appropriate AF code (from socket.h), or AF_UNSPEC if an appropriate
21447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		mapping couldn't be determined
21547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt */
21647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltint
21747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltrr_to_af (ns_type_t rrtype);
21847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
21947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
22047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt/*
22147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	Convert an address family (AF) code to a DNS resource record (RR) code.
22247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
22347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	Parameters
22447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		int
22547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			address family code (from socket.h)
22647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	Returns
22747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		Appropriate RR code (from nameser.h), or ns_t_invalid if an appropriate
22847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		mapping couldn't be determined
22947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt */
23047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltns_type_t
23147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltaf_to_rr (int af);
23247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
23347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
23447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt/*
23547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	Convert a string to an address family (case insensitive).
23647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
23747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	Returns
23847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		Matching AF code, or AF_UNSPEC if no match found.
23947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt */
24047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltint
24147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltstr_to_af (const char * str);
24247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
24347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
24447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt/*
24547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	Convert a string to an ns_class_t (case insensitive).
24647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
24747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	Returns
24847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		Matching ns_class_t, or ns_c_invalid if no match found.
24947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt */
25047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltns_class_t
25147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltstr_to_ns_class (const char * str);
25247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
25347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
25447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt/*
25547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	Convert a string to an ns_type_t (case insensitive).
25647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
25747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	Returns
25847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		Matching ns_type_t, or ns_t_invalid if no match found.
25947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt */
26047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltns_type_t
26147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltstr_to_ns_type (const char * str);
26247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
26347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
26447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt/*
26547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	Convert an address family code to a string.
26647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
26747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	Returns
26847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		String representation of AF,
26947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		or NULL if address family unrecognised or invalid.
27047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt */
27147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltconst char *
27247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltaf_to_str (int in);
27347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
27447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
27547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt/*
27647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	Convert an ns_class_t code to a string.
27747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
27847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	Returns
27947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		String representation of ns_class_t,
28047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		or NULL if ns_class_t unrecognised or invalid.
28147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt */
28247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltconst char *
28347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltns_class_to_str (ns_class_t in);
28447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
28547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
28647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt/*
28747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	Convert an ns_type_t code to a string.
28847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
28947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	Returns
29047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		String representation of ns_type_t,
29147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		or NULL if ns_type_t unrecognised or invalid.
29247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt */
29347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltconst char *
29447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltns_type_to_str (ns_type_t in);
29547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
29647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
29747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt/*
29847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	Convert DNS rdata in label format (RFC1034, RFC1035) to a name.
29947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
30047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	On error, partial data is written to name (as much as was successfully
30147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	processed) and an error code is returned.  Errors include a name too
30247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	long for the buffer and a pointer in the label (which cannot be
30347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	resolved).
30447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
30547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	Parameters
30647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		rdata
30747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			Rdata formatted as series of labels.
30847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		rdlen
30947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			Length of rdata buffer.
31047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		name
31147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			Buffer to store fully qualified result in.
31247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			By RFC1034 section 3.1, a 255 character buffer (256 characters
31347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			including null) is long enough for any legal name.
31447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		name_len
31547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			Number of characters available in name buffer, not including
31647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			trailing null.
31747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
31847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	Returns
31947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		Length of name buffer (not including trailing null).
32047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		< 0 on error.
32147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		A return of 0 implies the empty domain.
32247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt */
32347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltint
32447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltdns_rdata_to_name (const char * rdata, int rdlen, char * name, int name_len);
32547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltenum
32647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt{
32747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	DNS_RDATA_TO_NAME_BAD_FORMAT = -1,
32847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		// Format is broken.  Usually because we ran out of data
32947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		// (according to rdata) before the labels said we should.
33047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	DNS_RDATA_TO_NAME_TOO_LONG = -2,
33147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		// The converted rdata is longer than the name buffer.
33247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	DNS_RDATA_TO_NAME_PTR = -3,
33347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		// The rdata contains a pointer.
33447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt};
33547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
33647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#define DNS_LABEL_MAXLEN 63
33747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	// Maximum length of a single DNS label
33847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#define DNS_NAME_MAXLEN 256
33947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	// Maximum length of a DNS name
34047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
34147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt//----------
34247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt// Public types
34347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
34447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalttypedef int errcode_t;
34547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	// Used for 0 = success, non-zero = error code functions
34647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
34747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
34847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt//----------
34947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt// Public functions
35047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
35147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt/*
35247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	Test whether a domain name is in a domain covered by nss_mdns.
35347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	The name is assumed to be fully qualified (trailing dot optional);
35447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	unqualified names will be processed but may return unusual results
35547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	if the unqualified prefix happens to match a domain suffix.
35647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
35747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	Returns
35847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		 1 success
35947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		 0 failure
36047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		-1 error, check errno
36147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt */
36247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltint
36347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltconfig_is_mdns_suffix (const char * name);
36447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
36547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
36647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt/*
36747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	Loads all relevant data from configuration file.  Other code should
36847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	rarely need to call this function, since all other public configuration
36947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	functions do so implicitly.  Once loaded, configuration info doesn't
37047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	change.
37147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
37247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	Returns
37347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		0 configuration ready
37447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		non-zero configuration error code
37547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt */
37647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalterrcode_t
37747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltinit_config ();
37847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
37947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#define ENTNAME  hostent
38047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#define DATABASE "hosts"
38147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
38247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#include <nss.h>
38347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	// For nss_status
38447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#include <netdb.h>
38547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	// For hostent
38647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#include <sys/types.h>
38747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	// For size_t
38847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
38947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalttypedef enum nss_status nss_status;
39047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalttypedef struct hostent hostent;
39147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
39247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt/*
39347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltgethostbyname implementation
39447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
39547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	name:
39647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		name to look up
39747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	result_buf:
39847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		resulting entry
39947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	buf:
40047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		auxillary buffer
40147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	buflen:
40247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		length of auxillary buffer
40347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	errnop:
40447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		pointer to errno
40547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	h_errnop:
40647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		pointer to h_errno
40747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt */
40847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltnss_status
40947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt_nss_mdns_gethostbyname_r (
41047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	const char *name,
41147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	hostent * result_buf,
41247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	char *buf,
41347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	size_t buflen,
41447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	int *errnop,
41547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	int *h_errnop
41647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt);
41747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
41847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
41947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt/*
42047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltgethostbyname2 implementation
42147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
42247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	name:
42347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		name to look up
42447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	af:
42547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		address family
42647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	result_buf:
42747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		resulting entry
42847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	buf:
42947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		auxillary buffer
43047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	buflen:
43147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		length of auxillary buffer
43247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	errnop:
43347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		pointer to errno
43447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	h_errnop:
43547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		pointer to h_errno
43647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt */
43747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltnss_status
43847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt_nss_mdns_gethostbyname2_r (
43947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	const char *name,
44047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	int af,
44147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	hostent * result_buf,
44247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	char *buf,
44347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	size_t buflen,
44447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	int *errnop,
44547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	int *h_errnop
44647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt);
44747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
44847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
44947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt/*
45047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltgethostbyaddr implementation
45147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
45247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	addr:
45347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		address structure to look up
45447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	len:
45547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		length of address structure
45647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	af:
45747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		address family
45847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	result_buf:
45947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		resulting entry
46047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	buf:
46147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		auxillary buffer
46247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	buflen:
46347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		length of auxillary buffer
46447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	errnop:
46547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		pointer to errno
46647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	h_errnop:
46747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		pointer to h_errno
46847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt */
46947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltnss_status
47047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt_nss_mdns_gethostbyaddr_r (
47147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	const void *addr,
47247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	socklen_t len,
47347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	int af,
47447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	hostent * result_buf,
47547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	char *buf,
47647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	size_t buflen,
47747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	int *errnop,
47847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	int *h_errnop
47947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt);
48047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
48147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
48247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt//----------
48347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt// Types and Constants
48447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
48547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltconst int MDNS_VERBOSE = 0;
48647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	// This enables verbose syslog messages
48747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	// If zero, only "imporant" messages will appear in syslog
48847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
48947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#define k_hostname_maxlen 256
49047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	// As per RFC1034 and RFC1035
49147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#define k_aliases_max 15
49247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#define k_addrs_max 15
49347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
49447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalttypedef struct buf_header
49547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt{
49647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	char hostname [k_hostname_maxlen + 1];
49747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	char * aliases [k_aliases_max + 1];
49847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	char * addrs [k_addrs_max + 1];
49947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt} buf_header_t;
50047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
50147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalttypedef struct result_map
50247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt{
50347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	int done;
50447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	nss_status status;
50547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	hostent * hostent;
50647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	buf_header_t * header;
50747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	int aliases_count;
50847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	int addrs_count;
50947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	char * buffer;
51047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	int addr_idx;
51147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		// Index for addresses - grow from low end
51247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		// Index points to first empty space
51347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	int alias_idx;
51447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		// Index for aliases - grow from high end
51547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		// Index points to lowest entry
51647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	int r_errno;
51747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	int r_h_errno;
51847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt} result_map_t;
51947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
52047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltstatic const struct timeval
52147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	k_select_time = { 0, 500000 };
52247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		// 0 seconds, 500 milliseconds
52347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
52447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt//----------
52547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt// Local prototypes
52647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
52747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltstatic nss_status
52847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltmdns_gethostbyname2 (
52947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	const char *name,
53047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	int af,
53147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	hostent * result_buf,
53247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	char *buf,
53347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	size_t buflen,
53447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	int *errnop,
53547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	int *h_errnop
53647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt);
53747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
53847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
53947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt/*
54047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	Lookup name using mDNS server
54147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt */
54247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltstatic nss_status
54347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltmdns_lookup_name (
54447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	const char * fullname,
54547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	int af,
54647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	result_map_t * result
54747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt);
54847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
54947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt/*
55047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	Lookup address using mDNS server
55147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt */
55247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltstatic nss_status
55347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltmdns_lookup_addr (
55447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	const void * addr,
55547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	socklen_t len,
55647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	int af,
55747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	const char * addr_str,
55847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	result_map_t * result
55947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt);
56047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
56147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
56247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt/*
56347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	Handle incoming MDNS events
56447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt */
56547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltstatic nss_status
56647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalthandle_events (DNSServiceRef sdref, result_map_t * result, const char * str);
56747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
56847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
56947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt// Callback for mdns_lookup operations
57047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt//DNSServiceQueryRecordReply mdns_lookup_callback;
57147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalttypedef void
57247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltmdns_lookup_callback_t
57347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt(
57447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	DNSServiceRef		sdref,
57547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	DNSServiceFlags		flags,
57647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	uint32_t			interface_index,
57747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	DNSServiceErrorType	error_code,
57847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	const char			*fullname,
57947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	uint16_t			rrtype,
58047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	uint16_t			rrclass,
58147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	uint16_t			rdlen,
58247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	const void			*rdata,
58347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	uint32_t			ttl,
58447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	void				*context
58547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt);
58647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
58747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltmdns_lookup_callback_t mdns_lookup_callback;
58847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
58947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
59047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltstatic int
59147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltinit_result (
59247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	result_map_t * result,
59347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	hostent * result_buf,
59447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	char * buf,
59547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	size_t buflen
59647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt);
59747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
59847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltstatic int
59947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltcallback_body_ptr (
60047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	const char * fullname,
60147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	result_map_t * result,
60247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	int rdlen,
60347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	const void * rdata
60447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt);
60547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
60647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltstatic void *
60747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltadd_address_to_buffer (result_map_t * result, const void * data, int len);
60847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltstatic char *
60947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltadd_alias_to_buffer (result_map_t * result, const char * data, int len);
61047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltstatic char *
61147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltadd_hostname_len (result_map_t * result, const char * fullname, int len);
61247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltstatic char *
61347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltadd_hostname_or_alias (result_map_t * result, const char * data, int len);
61447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
61547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltstatic void *
61647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltcontains_address (result_map_t * result, const void * data, int len);
61747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltstatic char *
61847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltcontains_alias (result_map_t * result, const char * data);
61947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
62047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
62147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltstatic const char *
62247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltis_applicable_name (
62347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	result_map_t * result,
62447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	const char * name,
62547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	char * lookup_name
62647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt);
62747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
62847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltstatic const char *
62947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltis_applicable_addr (
63047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	result_map_t * result,
63147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	const void * addr,
63247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	int af,
63347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	char * addr_str
63447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt);
63547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
63647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
63747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt// Error code functions
63847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
63947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltstatic nss_status
64047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltset_err (result_map_t * result, nss_status status, int err, int herr);
64147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
64247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltstatic nss_status set_err_notfound (result_map_t * result);
64347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltstatic nss_status set_err_bad_hostname (result_map_t * result);
64447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltstatic nss_status set_err_buf_too_small (result_map_t * result);
64547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltstatic nss_status set_err_internal_resource_full (result_map_t * result);
64647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltstatic nss_status set_err_system (result_map_t * result);
64747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltstatic nss_status set_err_mdns_failed (result_map_t * result);
64847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltstatic nss_status set_err_success (result_map_t * result);
64947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
65047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
65147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt//----------
65247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt// Global variables
65347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
65447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
65547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt//----------
65647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt// NSS functions
65747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
65847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltnss_status
65947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt_nss_mdns_gethostbyname_r (
66047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	const char *name,
66147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	hostent * result_buf,
66247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	char *buf,
66347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	size_t buflen,
66447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	int *errnop,
66547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	int *h_errnop
66647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt)
66747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt{
66847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	if (MDNS_VERBOSE)
66947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		syslog (LOG_DEBUG,
67047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			"mdns: Called nss_mdns_gethostbyname with %s",
67147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			name
67247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		);
67347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
67447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	return
67547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		mdns_gethostbyname2 (
67647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			name, AF_INET, result_buf, buf, buflen, errnop, h_errnop
67747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		);
67847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt}
67947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
68047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
68147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltnss_status
68247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt_nss_mdns_gethostbyname2_r (
68347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	const char *name,
68447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	int af,
68547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	hostent * result_buf,
68647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	char *buf,
68747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	size_t buflen,
68847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	int *errnop,
68947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	int *h_errnop
69047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt)
69147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt{
69247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	if (MDNS_VERBOSE)
69347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		syslog (LOG_DEBUG,
69447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			"mdns: Called nss_mdns_gethostbyname2 with %s",
69547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			name
69647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		);
69747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
69847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	return
69947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		mdns_gethostbyname2 (
70047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			name, af, result_buf, buf, buflen, errnop, h_errnop
70147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		);
70247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt}
70347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
70447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
70547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltnss_status
70647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt_nss_mdns_gethostbyaddr_r (
70747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	const void *addr,
70847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	socklen_t len,
70947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	int af,
71047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	hostent * result_buf,
71147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	char *buf,
71247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	size_t buflen,
71347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	int *errnop,
71447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	int *h_errnop
71547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt)
71647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt{
71747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	char addr_str [NI_MAXHOST + 1];
71847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	result_map_t result;
71947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	int err_status;
72047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
72147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	if (inet_ntop (af, addr, addr_str, NI_MAXHOST) == NULL)
72247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	{
72347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		const char * family = af_to_str (af);
72447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		if (family == NULL)
72547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		{
72647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			family = "Unknown";
72747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		}
72847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
72947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		syslog (LOG_WARNING,
73047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			"mdns: Couldn't covert address, family %d (%s) in nss_mdns_gethostbyaddr: %s",
73147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			af,
73247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			family,
73347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			strerror (errno)
73447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		);
73547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
73647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		// This address family never applicable to us, so return NOT_FOUND
73747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
73847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		*errnop = ENOENT;
73947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		*h_errnop = HOST_NOT_FOUND;
74047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		return NSS_STATUS_NOTFOUND;
74147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	}
74247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	if (MDNS_VERBOSE)
74347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	{
74447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		syslog (LOG_DEBUG,
74547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			"mdns: Called nss_mdns_gethostbyaddr with %s",
74647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			addr_str
74747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		);
74847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	}
74947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
75047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	// Initialise result
75147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	err_status = init_result (&result, result_buf, buf, buflen);
75247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	if (err_status)
75347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	{
75447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		*errnop = err_status;
75547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		*h_errnop = NETDB_INTERNAL;
75647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		return NSS_STATUS_TRYAGAIN;
75747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	}
75847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
75947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	if (is_applicable_addr (&result, addr, af, addr_str))
76047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	{
76147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		nss_status rv;
76247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
76347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		rv = mdns_lookup_addr (addr, len, af, addr_str, &result);
76447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		if (rv == NSS_STATUS_SUCCESS)
76547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		{
76647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			return rv;
76747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		}
76847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	}
76947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
77047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	// Return current error status (defaults to NOT_FOUND)
77147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
77247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	*errnop = result.r_errno;
77347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	*h_errnop = result.r_h_errno;
77447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	return result.status;
77547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt}
77647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
77747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
77847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt//----------
77947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt// Local functions
78047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
78147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltnss_status
78247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltmdns_gethostbyname2 (
78347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	const char *name,
78447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	int af,
78547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	hostent * result_buf,
78647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	char *buf,
78747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	size_t buflen,
78847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	int *errnop,
78947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	int *h_errnop
79047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt)
79147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt{
79247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	char lookup_name [k_hostname_maxlen + 1];
79347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	result_map_t result;
79447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	int err_status;
79547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
79647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	// Initialise result
79747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	err_status = init_result (&result, result_buf, buf, buflen);
79847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	if (err_status)
79947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	{
80047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		*errnop = err_status;
80147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		*h_errnop = NETDB_INTERNAL;
80247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		return NSS_STATUS_TRYAGAIN;
80347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	}
80447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
80547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	if (is_applicable_name (&result, name, lookup_name))
80647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	{
80747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		// Try using mdns
80847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		nss_status rv;
80947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
81047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		if (MDNS_VERBOSE)
81147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			syslog (LOG_DEBUG,
81247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt				"mdns: Local name: %s",
81347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt				name
81447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			);
81547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
81647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		rv = mdns_lookup_name (name, af, &result);
81747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		if (rv == NSS_STATUS_SUCCESS)
81847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		{
81947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			return rv;
82047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		}
82147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	}
82247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
82347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	// Return current error status (defaults to NOT_FOUND)
82447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
82547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	*errnop = result.r_errno;
82647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	*h_errnop = result.r_h_errno;
82747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	return result.status;
82847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt}
82947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
83047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
83147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt/*
83247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	Lookup a fully qualified hostname using the default record type
83347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	for the specified address family.
83447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
83547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	Parameters
83647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		fullname
83747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			Fully qualified hostname.  If not fully qualified the code will
83847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			still 'work', but the lookup is unlikely to succeed.
83947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		af
84047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			Either AF_INET or AF_INET6.  Other families are not supported.
84147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		result
84247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			Initialised 'result' data structure.
84347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt */
84447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltstatic nss_status
84547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltmdns_lookup_name (
84647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	const char * fullname,
84747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	int af,
84847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	result_map_t * result
84947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt)
85047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt{
85147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	// Lookup using mDNS.
85247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	DNSServiceErrorType errcode;
85347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	DNSServiceRef sdref;
85447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	ns_type_t rrtype;
85547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	nss_status status;
85647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
85747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	if (MDNS_VERBOSE)
85847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		syslog (LOG_DEBUG,
85947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			"mdns: Attempting lookup of %s",
86047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			fullname
86147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		);
86247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
86347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	switch (af)
86447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	{
86547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	  case AF_INET:
86647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		rrtype = kDNSServiceType_A;
86747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		result->hostent->h_length = 4;
86847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			// Length of an A record
86947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		break;
87047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
87147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	  case AF_INET6:
87247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		rrtype = kDNSServiceType_AAAA;
87347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		result->hostent->h_length = 16;
87447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			// Length of an AAAA record
87547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		break;
87647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
87747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	  default:
87847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		syslog (LOG_WARNING,
87947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			"mdns: Unsupported address family %d",
88047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			af
88147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		);
88247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		return set_err_bad_hostname (result);
88347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	}
88447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	result->hostent->h_addrtype = af;
88547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
88647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	errcode =
88747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		DNSServiceQueryRecord (
88847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			&sdref,
88947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			kDNSServiceFlagsForceMulticast,		// force multicast query
89047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			kDNSServiceInterfaceIndexAny,	// all interfaces
89147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			fullname,	// full name to query for
89247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			rrtype,		// resource record type
89347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			kDNSServiceClass_IN,	// internet class records
89447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			mdns_lookup_callback,	// callback
89547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			result		// Context - result buffer
89647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		);
89747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
89847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	if (errcode)
89947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	{
90047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		syslog (LOG_WARNING,
90147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			"mdns: Failed to initialise lookup, error %d",
90247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			errcode
90347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		);
90447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		return set_err_mdns_failed (result);
90547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	}
90647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
90747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	status = handle_events (sdref, result, fullname);
90847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	DNSServiceRefDeallocate (sdref);
90947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	return status;
91047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt}
91147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
91247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
91347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt/*
91447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	Reverse (PTR) lookup for the specified address.
91547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
91647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	Parameters
91747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		addr
91847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			Either a struct in_addr or a struct in6_addr
91947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		addr_len
92047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			size of the address
92147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		af
92247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			Either AF_INET or AF_INET6.  Other families are not supported.
92347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			Must match addr
92447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		addr_str
92547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			Address in format suitable for PTR lookup.
92647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			AF_INET: a.b.c.d -> d.c.b.a.in-addr.arpa
92747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			AF_INET6: reverse nibble format, x.x.x...x.ip6.arpa
92847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		result
92947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			Initialised 'result' data structure.
93047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt */
93147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltstatic nss_status
93247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltmdns_lookup_addr (
93347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	const void * addr,
93447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	socklen_t addr_len,
93547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	int af,
93647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	const char * addr_str,
93747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	result_map_t * result
93847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt)
93947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt{
94047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	DNSServiceErrorType errcode;
94147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	DNSServiceRef sdref;
94247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	nss_status status;
94347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
94447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	if (MDNS_VERBOSE)
94547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		syslog (LOG_DEBUG,
94647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			"mdns: Attempting lookup of %s",
94747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			addr_str
94847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		);
94947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
95047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	result->hostent->h_addrtype = af;
95147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	result->hostent->h_length = addr_len;
95247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
95347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	// Query address becomes "address" in result.
95447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	if (! add_address_to_buffer (result, addr, addr_len))
95547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	{
95647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		return result->status;
95747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	}
95847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
95947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	result->hostent->h_name [0] = 0;
96047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
96147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	errcode =
96247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		DNSServiceQueryRecord (
96347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			&sdref,
96447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			kDNSServiceFlagsForceMulticast,		// force multicast query
96547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			kDNSServiceInterfaceIndexAny,	// all interfaces
96647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			addr_str,	// address string to query for
96747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			kDNSServiceType_PTR,	// pointer RRs
96847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			kDNSServiceClass_IN,	// internet class records
96947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			mdns_lookup_callback,	// callback
97047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			result		// Context - result buffer
97147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		);
97247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
97347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	if (errcode)
97447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	{
97547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		syslog (LOG_WARNING,
97647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			"mdns: Failed to initialise mdns lookup, error %d",
97747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			errcode
97847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		);
97947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		return set_err_mdns_failed (result);
98047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	}
98147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
98247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	status = handle_events (sdref, result, addr_str);
98347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	DNSServiceRefDeallocate (sdref);
98447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	return status;
98547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt}
98647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
98747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
98847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt/*
98947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	Wait on result of callback, and process it when it arrives.
99047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
99147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	Parameters
99247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		sdref
99347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			dns-sd reference
99447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		result
99547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			Initialised 'result' data structure.
99647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		str
99747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			lookup string, used for status/error reporting.
99847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt */
99947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltstatic nss_status
100047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalthandle_events (DNSServiceRef sdref, result_map_t * result, const char * str)
100147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt{
100247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	int dns_sd_fd = DNSServiceRefSockFD(sdref);
100347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	int nfds = dns_sd_fd + 1;
100447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	fd_set readfds;
100547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	struct timeval tv;
100647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	int select_result;
100747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
100847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	while (! result->done)
100947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	{
101047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		FD_ZERO(&readfds);
101147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		FD_SET(dns_sd_fd, &readfds);
101247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
101347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		tv = k_select_time;
101447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
101547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		select_result =
101647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			select (nfds, &readfds, (fd_set*)NULL, (fd_set*)NULL, &tv);
101747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		if (select_result > 0)
101847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		{
101947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			if (FD_ISSET(dns_sd_fd, &readfds))
102047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			{
102147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt				if (MDNS_VERBOSE)
102247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt					syslog (LOG_DEBUG,
102347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt						"mdns: Reply received for %s",
102447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt						str
102547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt					);
102647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt				DNSServiceProcessResult(sdref);
102747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			}
102847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			else
102947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			{
103047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt				syslog (LOG_WARNING,
103147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt					"mdns: Unexpected return from select on lookup of %s",
103247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt					str
103347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt				);
103447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			}
103547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		}
103647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		else
103747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		{
103847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			// Terminate loop due to timer expiry
103947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			if (MDNS_VERBOSE)
104047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt				syslog (LOG_DEBUG,
104147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt					"mdns: %s not found - timer expired",
104247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt					str
104347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt				);
104447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			set_err_notfound (result);
104547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			break;
104647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		}
104747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	}
104847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
104947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	return result->status;
105047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt}
105147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
105247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
105347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt/*
105447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	Examine incoming data and add to relevant fields in result structure.
105547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	This routine is called from DNSServiceProcessResult where appropriate.
105647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt */
105747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltvoid
105847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltmdns_lookup_callback
105947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt(
106047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	DNSServiceRef		sdref,
106147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	DNSServiceFlags		flags,
106247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	uint32_t			interface_index,
106347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	DNSServiceErrorType	error_code,
106447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	const char			*fullname,
106547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	uint16_t			rrtype,
106647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	uint16_t			rrclass,
106747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	uint16_t			rdlen,
106847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	const void			*rdata,
106947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	uint32_t			ttl,
107047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	void				*context
107147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt)
107247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt{
107347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	// A single record is received
107447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
107547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	result_map_t * result = (result_map_t *) context;
107647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
107747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	(void)sdref; // Unused
107847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	(void)interface_index; // Unused
107947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	(void)ttl; // Unused
108047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
108147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	if (! (flags & kDNSServiceFlagsMoreComing) )
108247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	{
108347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		result->done = 1;
108447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	}
108547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
108647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	if (error_code == kDNSServiceErr_NoError)
108747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	{
108847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		ns_type_t expected_rr_type =
108947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			af_to_rr (result->hostent->h_addrtype);
109047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
109147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		// Idiot check class
109247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		if (rrclass != C_IN)
109347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		{
109447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			syslog (LOG_WARNING,
109547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt				"mdns: Received bad RR class: expected %d (%s),"
109647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt				" got %d (%s), RR type %d (%s)",
109747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt				C_IN,
109847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt				ns_class_to_str (C_IN),
109947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt				rrclass,
110047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt				ns_class_to_str (rrclass),
110147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt				rrtype,
110247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt				ns_type_to_str (rrtype)
110347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			);
110447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			return;
110547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		}
110647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
110747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		// If a PTR
110847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		if (rrtype == kDNSServiceType_PTR)
110947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		{
111047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			if (callback_body_ptr (fullname, result, rdlen, rdata) < 0)
111147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt				return;
111247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		}
111347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		else if (rrtype == expected_rr_type)
111447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		{
111547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			if (!
111647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt				add_hostname_or_alias (
111747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt					result,
111847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt					fullname,
111947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt					strlen (fullname)
112047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt				)
112147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			)
112247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			{
112347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt				result->done = 1;
112447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt				return;
112547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt					// Abort on error
112647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			}
112747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
112847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			if (! add_address_to_buffer (result, rdata, rdlen) )
112947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			{
113047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt				result->done = 1;
113147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt				return;
113247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt					// Abort on error
113347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			}
113447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		}
113547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		else
113647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		{
113747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			syslog (LOG_WARNING,
113847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt				"mdns: Received bad RR type: expected %d (%s),"
113947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt				" got %d (%s)",
114047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt				expected_rr_type,
114147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt				ns_type_to_str (expected_rr_type),
114247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt				rrtype,
114347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt				ns_type_to_str (rrtype)
114447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			);
114547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			return;
114647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		}
114747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
114847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		if (result->status != NSS_STATUS_SUCCESS)
114947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			set_err_success (result);
115047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	}
115147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	else
115247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	{
115347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		// For now, dump message to syslog and continue
115447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		syslog (LOG_WARNING,
115547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			"mdns: callback returned error %d",
115647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			error_code
115747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		);
115847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	}
115947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt}
116047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
116147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltstatic int
116247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltcallback_body_ptr (
116347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	const char * fullname,
116447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	result_map_t * result,
116547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	int rdlen,
116647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	const void * rdata
116747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt)
116847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt{
116947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	char result_name [k_hostname_maxlen + 1];
117047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	int rv;
117147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
117247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	// Fullname should be .in-addr.arpa or equivalent, which we're
117347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	// not interested in.  Ignore it.
117447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
117547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	rv = dns_rdata_to_name (rdata, rdlen, result_name, k_hostname_maxlen);
117647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	if (rv < 0)
117747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	{
117847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		const char * errmsg;
117947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
118047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		switch (rv)
118147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		{
118247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		  case DNS_RDATA_TO_NAME_BAD_FORMAT:
118347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			errmsg = "mdns: PTR '%s' result badly formatted ('%s...')";
118447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			break;
118547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
118647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		  case DNS_RDATA_TO_NAME_TOO_LONG:
118747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			errmsg = "mdns: PTR '%s' result too long ('%s...')";
118847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			break;
118947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
119047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		  case DNS_RDATA_TO_NAME_PTR:
119147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			errmsg = "mdns: PTR '%s' result contained pointer ('%s...')";
119247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			break;
119347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
119447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		  default:
119547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			errmsg = "mdns: PTR '%s' result conversion failed ('%s...')";
119647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		}
119747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
119847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		syslog (LOG_WARNING,
119947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			errmsg,
120047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			fullname,
120147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			result_name
120247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		);
120347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
120447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		return -1;
120547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	}
120647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
120747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	if (MDNS_VERBOSE)
120847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	{
120947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		syslog (LOG_DEBUG,
121047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			"mdns: PTR '%s' resolved to '%s'",
121147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			fullname,
121247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			result_name
121347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		);
121447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	}
121547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
121647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	// Data should be a hostname
121747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	if (!
121847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		add_hostname_or_alias (
121947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			result,
122047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			result_name,
122147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			rv
122247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		)
122347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	)
122447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	{
122547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		result->done = 1;
122647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		return -1;
122747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	}
122847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
122947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	return 0;
123047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt}
123147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
123247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
123347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt/*
123447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	Add an address to the buffer.
123547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
123647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	Parameter
123747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		result
123847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			Result structure to write to
123947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		data
124047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			Incoming address data buffer
124147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			Must be 'int' aligned
124247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		len
124347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			Length of data buffer (in bytes)
124447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			Must match data alignment
124547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
124647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	Result
124747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		Pointer to start of newly written data,
124847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		or NULL on error.
124947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		If address already exists in buffer, returns pointer to that instead.
125047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt */
125147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltstatic void *
125247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltadd_address_to_buffer (result_map_t * result, const void * data, int len)
125347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt{
125447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	int new_addr;
125547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	void * start;
125647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	void * temp;
125747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
125847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	if ((temp = contains_address (result, data, len)))
125947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	{
126047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		return temp;
126147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	}
126247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
126347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	if (result->addrs_count >= k_addrs_max)
126447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	{
126547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		// Not enough addr slots
126647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		set_err_internal_resource_full (result);
126747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		syslog (LOG_ERR,
126847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			"mdns: Internal address buffer full; increase size"
126947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		);
127047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		return NULL;
127147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	}
127247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
127347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	// Idiot check
127447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	if (len != result->hostent->h_length)
127547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	{
127647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		syslog (LOG_WARNING,
127747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			"mdns: Unexpected rdata length for address.  Expected %d, got %d",
127847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			result->hostent->h_length,
127947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			len
128047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		);
128147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		// XXX And continue for now.
128247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	}
128347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
128447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	new_addr = result->addr_idx + len;
128547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
128647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	if (new_addr > result->alias_idx)
128747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	{
128847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		// Not enough room
128947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		set_err_buf_too_small (result);
129047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		if (MDNS_VERBOSE)
129147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			syslog (LOG_DEBUG,
129247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt				"mdns: Ran out of buffer when adding address %d",
129347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt				result->addrs_count + 1
129447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			);
129547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		return NULL;
129647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	}
129747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
129847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	start = result->buffer + result->addr_idx;
129947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	memcpy (start, data, len);
130047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	result->addr_idx = new_addr;
130147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	result->header->addrs [result->addrs_count] = start;
130247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	result->addrs_count ++;
130347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	result->header->addrs [result->addrs_count] = NULL;
130447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
130547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	return start;
130647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt}
130747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
130847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
130947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltstatic void *
131047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltcontains_address (result_map_t * result, const void * data, int len)
131147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt{
131247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	int i;
131347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
131447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	// Idiot check
131547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	if (len != result->hostent->h_length)
131647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	{
131747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		syslog (LOG_WARNING,
131847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			"mdns: Unexpected rdata length for address.  Expected %d, got %d",
131947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			result->hostent->h_length,
132047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			len
132147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		);
132247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		// XXX And continue for now.
132347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	}
132447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
132547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	for (i = 0; result->header->addrs [i]; i++)
132647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	{
132747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		if (memcmp (result->header->addrs [i], data, len) == 0)
132847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		{
132947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			return result->header->addrs [i];
133047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		}
133147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	}
133247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
133347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	return NULL;
133447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt}
133547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
133647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
133747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt/*
133847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	Add an alias to the buffer.
133947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
134047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	Parameter
134147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		result
134247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			Result structure to write to
134347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		data
134447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			Incoming alias (null terminated)
134547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		len
134647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			Length of data buffer (in bytes), including trailing null
134747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
134847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	Result
134947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		Pointer to start of newly written data,
135047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		or NULL on error
135147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		If alias already exists in buffer, returns pointer to that instead.
135247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt */
135347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltstatic char *
135447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltadd_alias_to_buffer (result_map_t * result, const char * data, int len)
135547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt{
135647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	int new_alias;
135747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	char * start;
135847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	char * temp;
135947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
136047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	if ((temp = contains_alias (result, data)))
136147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	{
136247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		return temp;
136347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	}
136447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
136547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	if (result->aliases_count >= k_aliases_max)
136647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	{
136747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		// Not enough alias slots
136847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		set_err_internal_resource_full (result);
136947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		syslog (LOG_ERR,
137047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			"mdns: Internal alias buffer full; increase size"
137147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		);
137247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		return NULL;
137347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	}
137447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
137547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	new_alias = result->alias_idx - len;
137647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
137747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	if (new_alias < result->addr_idx)
137847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	{
137947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		// Not enough room
138047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		set_err_buf_too_small (result);
138147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		if (MDNS_VERBOSE)
138247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			syslog (LOG_DEBUG,
138347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt				"mdns: Ran out of buffer when adding alias %d",
138447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt				result->aliases_count + 1
138547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			);
138647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		return NULL;
138747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	}
138847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
138947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	start = result->buffer + new_alias;
139047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	memcpy (start, data, len);
139147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	result->alias_idx = new_alias;
139247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	result->header->aliases [result->aliases_count] = start;
139347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	result->aliases_count ++;
139447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	result->header->aliases [result->aliases_count] = NULL;
139547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
139647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	return start;
139747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt}
139847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
139947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
140047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltstatic char *
140147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltcontains_alias (result_map_t * result, const char * alias)
140247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt{
140347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	int i;
140447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
140547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	for (i = 0; result->header->aliases [i]; i++)
140647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	{
140747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		if (strcmp (result->header->aliases [i], alias) == 0)
140847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		{
140947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			return result->header->aliases [i];
141047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		}
141147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	}
141247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
141347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	return NULL;
141447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt}
141547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
141647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
141747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt/*
141847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	Add fully qualified hostname to result.
141947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
142047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	Parameter
142147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		result
142247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			Result structure to write to
142347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		fullname
142447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			Fully qualified hostname
142547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
142647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	Result
142747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		Pointer to start of hostname buffer,
142847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		or NULL on error (usually hostname too long)
142947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt */
143047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
143147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltstatic char *
143247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltadd_hostname_len (result_map_t * result, const char * fullname, int len)
143347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt{
143447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	if (len >= k_hostname_maxlen)
143547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	{
143647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		set_err_bad_hostname (result);
143747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		syslog (LOG_WARNING,
143847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			"mdns: Hostname too long '%.*s': len %d, max %d",
143947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			len,
144047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			fullname,
144147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			len,
144247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			k_hostname_maxlen
144347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		);
144447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		return NULL;
144547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	}
144647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
144747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	result->hostent->h_name =
144847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		strcpy (result->header->hostname, fullname);
144947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
145047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	return result->header->hostname;
145147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt}
145247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
145347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
145447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt/*
145547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	Add fully qualified name as hostname or alias.
145647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
145747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	If hostname is not fully qualified this is not an error, but the data
145847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	returned may be not what the application wanted.
145947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
146047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	Parameter
146147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		result
146247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			Result structure to write to
146347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		data
146447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			Incoming alias (null terminated)
146547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		len
146647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			Length of data buffer (in bytes), including trailing null
146747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
146847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	Result
146947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		Pointer to start of newly written data,
147047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		or NULL on error
147147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		If alias or hostname already exists, returns pointer to that instead.
147247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt */
147347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltstatic char *
147447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltadd_hostname_or_alias (result_map_t * result, const char * data, int len)
147547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt{
147647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	char * hostname = result->hostent->h_name;
147747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
147847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	if (*hostname)
147947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	{
148047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		if (strcmp (hostname, data) == 0)
148147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		{
148247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			return hostname;
148347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		}
148447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		else
148547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		{
148647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			return add_alias_to_buffer (result, data, len);
148747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		}
148847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	}
148947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	else
149047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	{
149147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		return add_hostname_len (result, data, len);
149247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	}
149347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt}
149447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
149547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
149647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltstatic int
149747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltinit_result (
149847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	result_map_t * result,
149947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	hostent * result_buf,
150047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	char * buf,
150147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	size_t buflen
150247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt)
150347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt{
150447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	if (buflen < sizeof (buf_header_t))
150547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	{
150647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		return ERANGE;
150747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	}
150847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
150947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	result->hostent = result_buf;
151047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	result->header = (buf_header_t *) buf;
151147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	result->header->hostname[0] = 0;
151247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	result->aliases_count = 0;
151347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	result->header->aliases[0] = NULL;
151447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	result->addrs_count = 0;
151547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	result->header->addrs[0] = NULL;
151647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	result->buffer = buf + sizeof (buf_header_t);
151747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	result->addr_idx = 0;
151847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	result->alias_idx = buflen - sizeof (buf_header_t);
151947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	result->done = 0;
152047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	set_err_notfound (result);
152147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
152247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	// Point hostent to the right buffers
152347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	result->hostent->h_name = result->header->hostname;
152447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	result->hostent->h_aliases = result->header->aliases;
152547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	result->hostent->h_addr_list = result->header->addrs;
152647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
152747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	return 0;
152847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt}
152947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
153047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt/*
153147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	Set the status in the result.
153247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
153347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	Parameters
153447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		result
153547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			Result structure to update
153647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		status
153747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			New nss_status value
153847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		err
153947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			New errno value
154047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		herr
154147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			New h_errno value
154247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
154347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	Returns
154447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		New status value
154547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt */
154647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltstatic nss_status
154747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltset_err (result_map_t * result, nss_status status, int err, int herr)
154847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt{
154947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	result->status = status;
155047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	result->r_errno = err;
155147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	result->r_h_errno = herr;
155247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
155347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	return status;
155447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt}
155547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
155647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltstatic nss_status
155747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltset_err_notfound (result_map_t * result)
155847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt{
155947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	return set_err (result, NSS_STATUS_NOTFOUND, ENOENT, HOST_NOT_FOUND);
156047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt}
156147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
156247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltstatic nss_status
156347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltset_err_bad_hostname (result_map_t * result)
156447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt{
156547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	return set_err (result, NSS_STATUS_TRYAGAIN, ENOENT, NO_RECOVERY);
156647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt}
156747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
156847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltstatic nss_status
156947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltset_err_buf_too_small (result_map_t * result)
157047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt{
157147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	return set_err (result, NSS_STATUS_TRYAGAIN, ERANGE, NETDB_INTERNAL);
157247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt}
157347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
157447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltstatic nss_status
157547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltset_err_internal_resource_full (result_map_t * result)
157647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt{
157747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	return set_err (result, NSS_STATUS_RETURN, ERANGE, NO_RECOVERY);
157847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt}
157947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
158047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltstatic nss_status
158147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltset_err_system (result_map_t * result)
158247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt{
158347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	return set_err (result, NSS_STATUS_UNAVAIL, errno, NETDB_INTERNAL);
158447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt}
158547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
158647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltstatic nss_status
158747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltset_err_mdns_failed (result_map_t * result)
158847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt{
158947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	return set_err (result, NSS_STATUS_TRYAGAIN, EAGAIN, TRY_AGAIN);
159047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt}
159147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
159247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltstatic nss_status
159347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltset_err_success (result_map_t * result)
159447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt{
159547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	result->status = NSS_STATUS_SUCCESS;
159647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	return result->status;
159747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt}
159847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
159947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
160047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt/*
160147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	Test whether name is applicable for mdns to process, and if so copy into
160247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	lookup_name buffer (if non-NULL).
160347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
160447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	Returns
160547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		Pointer to name to lookup up, if applicable, or NULL otherwise.
160647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt */
160747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltstatic const char *
160847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltis_applicable_name (
160947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	result_map_t * result,
161047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	const char * name,
161147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	char * lookup_name
161247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt)
161347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt{
161447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	int match = config_is_mdns_suffix (name);
161547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	if (match > 0)
161647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	{
161747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		if (lookup_name)
161847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		{
161947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			strncpy (lookup_name, name, k_hostname_maxlen + 1);
162047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			return lookup_name;
162147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		}
162247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		else
162347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		{
162447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			return name;
162547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		}
162647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	}
162747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	else
162847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	{
162947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		if (match < 0)
163047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		{
163147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			set_err_system (result);
163247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		}
163347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		return NULL;
163447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	}
163547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt}
163647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
163747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt/*
163847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	Test whether address is applicable for mdns to process, and if so copy into
163947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	addr_str buffer as an address suitable for ptr lookup.
164047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
164147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	Returns
164247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		Pointer to name to lookup up, if applicable, or NULL otherwise.
164347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt */
164447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltstatic const char *
164547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltis_applicable_addr (
164647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	result_map_t * result,
164747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	const void * addr,
164847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	int af,
164947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	char * addr_str
165047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt)
165147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt{
165247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	int match;
165347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
165447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	if (! format_reverse_addr (af, addr, -1, addr_str))
165547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	{
165647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		if (MDNS_VERBOSE)
165747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			syslog (LOG_DEBUG,
165847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt				"mdns: Failed to create reverse address"
165947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			);
166047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		return NULL;
166147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	}
166247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
166347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	if (MDNS_VERBOSE)
166447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		syslog (LOG_DEBUG,
166547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			"mdns: Reverse address: %s",
166647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			addr_str
166747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		);
166847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
166947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	match = config_is_mdns_suffix (addr_str);
167047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	if (match > 0)
167147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	{
167247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		return addr_str;
167347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	}
167447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	else
167547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	{
167647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		if (match < 0)
167747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		{
167847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			set_err_system (result);
167947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		}
168047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		return NULL;
168147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	}
168247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt}
168347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
168447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt//----------
168547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt// Types and Constants
168647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
168747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltconst char * k_conf_file = "/etc/nss_mdns.conf";
168847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#define CONF_LINE_SIZE 1024
168947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
169047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltconst char k_comment_char = '#';
169147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
169247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltconst char * k_keyword_domain = "domain";
169347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
169447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltconst char * k_default_domains [] =
169547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	{
169647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		"local",
169747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		"254.169.in-addr.arpa",
169847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		"8.e.f.ip6.int",
169947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		"8.e.f.ip6.arpa",
170047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		"9.e.f.ip6.int",
170147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		"9.e.f.ip6.arpa",
170247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		"a.e.f.ip6.int",
170347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		"a.e.f.ip6.arpa",
170447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		"b.e.f.ip6.int",
170547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		"b.e.f.ip6.arpa",
170647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		NULL
170747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			// Always null terminated
170847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	};
170947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
171047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt// Linked list of domains
171147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalttypedef struct domain_entry
171247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt{
171347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	char * domain;
171447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	struct domain_entry * next;
171547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt} domain_entry_t;
171647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
171747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
171847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt// Config
171947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalttypedef struct
172047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt{
172147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	domain_entry_t * domains;
172247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt} config_t;
172347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
172447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltconst config_t k_empty_config =
172547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	{
172647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		NULL
172747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	};
172847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
172947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
173047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt// Context - tracks position in config file, used for error reporting
173147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalttypedef struct
173247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt{
173347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	const char * filename;
173447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	int linenum;
173547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt} config_file_context_t;
173647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
173747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
173847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt//----------
173947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt// Local prototypes
174047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
174147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltstatic errcode_t
174247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltload_config (config_t * conf);
174347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
174447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltstatic errcode_t
174547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltprocess_config_line (
174647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	config_t * conf,
174747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	char * line,
174847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	config_file_context_t * context
174947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt);
175047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
175147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltstatic char *
175247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltget_next_word (char * input, char **next);
175347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
175447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltstatic errcode_t
175547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltdefault_config (config_t * conf);
175647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
175747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltstatic errcode_t
175847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltadd_domain (config_t * conf, const char * domain);
175947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
176047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltstatic int
176147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltcontains_domain (const config_t * conf, const char * domain);
176247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
176347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltstatic int
176447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltcontains_domain_suffix (const config_t * conf, const char * addr);
176547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
176647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
176747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt//----------
176847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt// Global variables
176947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
177047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltstatic config_t * g_config = NULL;
177147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	// Configuration info
177247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
177347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltpthread_mutex_t g_config_mutex =
177447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#ifdef PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP
177547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP;
177647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#else
177747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	PTHREAD_MUTEX_INITIALIZER;
177847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#endif
177947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
178047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
178147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt//----------
178247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt// Configuration functions
178347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
178447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
178547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt/*
178647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	Initialise the configuration from the config file.
178747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
178847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	Returns
178947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		0 success
179047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		non-zero error code on failure
179147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt */
179247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalterrcode_t
179347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltinit_config ()
179447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt{
179547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	if (g_config)
179647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	{
179747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		/*
179847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			Safe to test outside mutex.
179947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			If non-zero, initialisation is complete and g_config can be
180047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			safely used read-only.  If zero, then we do proper mutex
180147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			testing before initialisation.
180247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		 */
180347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		return 0;
180447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	}
180547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	else
180647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	{
180747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		int errcode = -1;
180847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		int presult;
180947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		config_t * temp_config;
181047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
181147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		// Acquire mutex
181247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		presult = pthread_mutex_lock (&g_config_mutex);
181347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		if (presult)
181447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		{
181547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			syslog (LOG_ERR,
181647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt				"mdns: Fatal mutex lock error in nss_mdns:init_config, %s:%d: %d: %s",
181747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt				__FILE__, __LINE__, presult, strerror (presult)
181847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			);
181947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			return presult;
182047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		}
182147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
182247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		// Test again now we have mutex, in case initialisation occurred while
182347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		// we were waiting
182447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		if (! g_config)
182547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		{
182647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			temp_config = (config_t *) malloc (sizeof (config_t));
182747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			if (temp_config)
182847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			{
182947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt				// Note: This code will leak memory if initialisation fails
183047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt				// repeatedly.  This should only happen in the case of a memory
183147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt				// error, so I'm not sure if it's a meaningful problem. - AW
183247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt				*temp_config = k_empty_config;
183347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt				errcode = load_config (temp_config);
183447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
183547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt				if (! errcode)
183647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt				{
183747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt					g_config = temp_config;
183847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt				}
183947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			}
184047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			else
184147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			{
184247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt				syslog (LOG_ERR,
184347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt					"mdns: Can't allocate memory in nss_mdns:init_config, %s:%d",
184447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt					__FILE__, __LINE__
184547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt				);
184647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt				errcode = errno;
184747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			}
184847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		}
184947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
185047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		presult = pthread_mutex_unlock (&g_config_mutex);
185147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		if (presult)
185247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		{
185347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			syslog (LOG_ERR,
185447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt				"mdns: Fatal mutex unlock error in nss_mdns:init_config, %s:%d: %d: %s",
185547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt				__FILE__, __LINE__, presult, strerror (presult)
185647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			);
185747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			errcode = presult;
185847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		}
185947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
186047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		return errcode;
186147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	}
186247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt}
186347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
186447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
186547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltint
186647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltconfig_is_mdns_suffix (const char * name)
186747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt{
186847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	int errcode = init_config ();
186947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	if (! errcode)
187047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	{
187147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		return contains_domain_suffix (g_config, name);
187247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	}
187347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	else
187447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	{
187547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		errno = errcode;
187647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		return -1;
187747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	}
187847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt}
187947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
188047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
188147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt//----------
188247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt// Local functions
188347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
188447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltstatic errcode_t
188547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltload_config (config_t * conf)
188647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt{
188747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	FILE * cf;
188847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	char line [CONF_LINE_SIZE];
188947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	config_file_context_t context;
189047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
189147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	context.filename = k_conf_file;
189247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	context.linenum = 0;
189347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
189447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
189547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	cf = fopen (context.filename, "r");
189647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	if (! cf)
189747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	{
189847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		syslog (LOG_INFO,
189947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			"mdns: Couldn't open nss_mdns configuration file %s, using default.",
190047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			context.filename
190147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		);
190247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		return default_config (conf);
190347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	}
190447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
190547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	while (fgets (line, CONF_LINE_SIZE, cf))
190647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	{
190747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		int errcode;
190847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		context.linenum++;
190947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		errcode = process_config_line (conf, line, &context);
191047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		if (errcode)
191147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		{
191247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			// Critical error, give up
191347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			fclose(cf);
191447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			return errcode;
191547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		}
191647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	}
191747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
191847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	fclose (cf);
191947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
192047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	return 0;
192147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt}
192247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
192347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
192447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt/*
192547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	Parse a line of the configuration file.
192647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	For each keyword recognised, perform appropriate handling.
192747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	If the keyword is not recognised, print a message to syslog
192847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	and continue.
192947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
193047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	Returns
193147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		0 success, or recoverable config file error
193247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		non-zero serious system error, processing aborted
193347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt */
193447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltstatic errcode_t
193547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltprocess_config_line (
193647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	config_t * conf,
193747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	char * line,
193847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	config_file_context_t * context
193947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt)
194047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt{
194147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	char * curr = line;
194247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	char * word;
194347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
194447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	word = get_next_word (curr, &curr);
194547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	if (! word || word [0] == k_comment_char)
194647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	{
194747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		// Nothing interesting on this line
194847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		return 0;
194947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	}
195047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
195147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	if (strcmp (word, k_keyword_domain) == 0)
195247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	{
195347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		word = get_next_word (curr, &curr);
195447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		if (word)
195547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		{
195647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			int errcode = add_domain (conf, word);
195747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			if (errcode)
195847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			{
195947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt				// something badly wrong, bail
196047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt				return errcode;
196147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			}
196247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
196347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			if (get_next_word (curr, NULL))
196447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			{
196547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt				syslog (LOG_WARNING,
196647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt					"%s, line %d: ignored extra text found after domain",
196747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt					context->filename,
196847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt					context->linenum
196947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt				);
197047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			}
197147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		}
197247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		else
197347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		{
197447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			syslog (LOG_WARNING,
197547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt				"%s, line %d: no domain specified",
197647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt				context->filename,
197747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt				context->linenum
197847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			);
197947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		}
198047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	}
198147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	else
198247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	{
198347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		syslog (LOG_WARNING,
198447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			"%s, line %d: unknown keyword %s - skipping",
198547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			context->filename,
198647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			context->linenum,
198747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			word
198847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		);
198947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	}
199047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
199147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	return 0;
199247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt}
199347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
199447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
199547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt/*
199647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	Get next word (whitespace separated) from input string.
199747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	A null character is written into the first whitespace character following
199847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	the word.
199947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
200047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	Parameters
200147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		input
200247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			Input string.  This string is modified by get_next_word.
200347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		next
200447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			If non-NULL and the result is non-NULL, a pointer to the
200547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			character following the end of the word (after the null)
200647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			is written to 'next'.
200747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			If no word is found, the original value is unchanged.
200847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			If the word extended to the end of the string, 'next' points
200947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			to the trailling NULL.
201047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			It is safe to pass 'str' as 'input' and '&str' as 'next'.
201147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	Returns
201247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		Pointer to the first non-whitespace character (and thus word) found.
201347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		if no word is found, returns NULL.
201447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt */
201547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltstatic char *
201647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltget_next_word (char * input, char **next)
201747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt{
201847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	char * curr = input;
201947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	char * result;
202047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
202147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	while (isspace (*curr))
202247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	{
202347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		curr ++;
202447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	}
202547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
202647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	if (*curr == 0)
202747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	{
202847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		return NULL;
202947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	}
203047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
203147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	result = curr;
203247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	while (*curr && ! isspace (*curr))
203347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	{
203447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		curr++;
203547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	}
203647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	if (*curr)
203747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	{
203847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		*curr = 0;
203947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		if (next)
204047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		{
204147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			*next = curr+1;
204247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		}
204347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	}
204447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	else
204547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	{
204647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		if (next)
204747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		{
204847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			*next = curr;
204947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		}
205047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	}
205147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
205247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	return result;
205347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt}
205447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
205547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
205647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltstatic errcode_t
205747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltdefault_config (config_t * conf)
205847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt{
205947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	int i;
206047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	for (i = 0; k_default_domains [i]; i++)
206147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	{
206247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		int errcode =
206347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			add_domain (conf, k_default_domains [i]);
206447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		if (errcode)
206547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		{
206647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			// Something has gone (badly) wrong - let's bail
206747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			return errcode;
206847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		}
206947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	}
207047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
207147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	return 0;
207247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt}
207347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
207447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
207547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltstatic errcode_t
207647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltadd_domain (config_t * conf, const char * domain)
207747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt{
207847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	if (! contains_domain (conf, domain))
207947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	{
208047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		domain_entry_t * d =
208147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			(domain_entry_t *) malloc (sizeof (domain_entry_t));
208247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		if (! d)
208347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		{
208447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			syslog (LOG_ERR,
208547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt				"mdns: Can't allocate memory in nss_mdns:init_config, %s:%d",
208647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt				__FILE__, __LINE__
208747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			);
208847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			return ENOMEM;
208947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		}
209047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
209147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		d->domain = strdup (domain);
209247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		if (! d->domain)
209347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		{
209447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			syslog (LOG_ERR,
209547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt				"mdns: Can't allocate memory in nss_mdns:init_config, %s:%d",
209647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt				__FILE__, __LINE__
209747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			);
209847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			free (d);
209947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			return ENOMEM;
210047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		}
210147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		d->next = conf->domains;
210247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		conf->domains = d;
210347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	}
210447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
210547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	return 0;
210647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt}
210747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
210847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
210947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltstatic int
211047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltcontains_domain (const config_t * conf, const char * domain)
211147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt{
211247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	const domain_entry_t * curr = conf->domains;
211347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
211447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	while (curr != NULL)
211547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	{
211647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		if (strcasecmp (curr->domain, domain) == 0)
211747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		{
211847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			return 1;
211947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		}
212047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
212147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		curr = curr->next;
212247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	}
212347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
212447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	return 0;
212547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt}
212647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
212747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
212847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltstatic int
212947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltcontains_domain_suffix (const config_t * conf, const char * addr)
213047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt{
213147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	const domain_entry_t * curr = conf->domains;
213247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
213347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	while (curr != NULL)
213447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	{
213547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		if (cmp_dns_suffix (addr, curr->domain) > 0)
213647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		{
213747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			return 1;
213847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		}
213947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
214047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		curr = curr->next;
214147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	}
214247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
214347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	return 0;
214447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt}
214547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
214647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt//----------
214747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt// Types and Constants
214847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
214947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltstatic const char * k_local_suffix = "local";
215047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltstatic const char k_dns_separator = '.';
215147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
215247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltstatic const int k_label_maxlen = DNS_LABEL_MAXLEN;
215347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	// Label entries longer than this are actually pointers.
215447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
215547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalttypedef struct
215647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt{
215747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	int value;
215847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	const char * name;
215947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	const char * comment;
216047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt} table_entry_t;
216147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
216247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltstatic const table_entry_t k_table_af [] =
216347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	{
216447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		{ AF_UNSPEC, NULL, NULL },
216547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		{ AF_LOCAL, "LOCAL", NULL },
216647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		{ AF_UNIX, "UNIX", NULL },
216747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		{ AF_INET, "INET", NULL },
216847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		{ AF_INET6, "INET6", NULL }
216947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	};
217047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltstatic const int k_table_af_size =
217147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	sizeof (k_table_af) / sizeof (* k_table_af);
217247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
217347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltstatic const char * k_table_ns_class [] =
217447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	{
217547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		NULL,
217647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		"IN"
217747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	};
217847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltstatic const int k_table_ns_class_size =
217947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	sizeof (k_table_ns_class) / sizeof (* k_table_ns_class);
218047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
218147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltstatic const char * k_table_ns_type [] =
218247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	{
218347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		NULL,
218447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		"A",
218547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		"NS",
218647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		"MD",
218747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		"MF",
218847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		"CNAME",
218947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		"SOA",
219047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		"MB",
219147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		"MG",
219247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		"MR",
219347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		"NULL",
219447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		"WKS",
219547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		"PTR",
219647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		"HINFO",
219747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		"MINFO",
219847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		"MX",
219947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		"TXT",
220047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		"RP",
220147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		"AFSDB",
220247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		"X25",
220347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		"ISDN",
220447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		"RT",
220547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		"NSAP",
220647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		NULL,
220747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		"SIG",
220847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		"KEY",
220947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		"PX",
221047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		"GPOS",
221147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		"AAAA",
221247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		"LOC",
221347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		"NXT",
221447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		"EID",
221547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		"NIMLOC",
221647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		"SRV",
221747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		"ATMA",
221847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		"NAPTR",
221947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		"KX",
222047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		"CERT",
222147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		"A6",
222247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		"DNAME",
222347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		"SINK",
222447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		"OPT"
222547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	};
222647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltstatic const int k_table_ns_type_size =
222747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	sizeof (k_table_ns_type) / sizeof (* k_table_ns_type);
222847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
222947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
223047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt//----------
223147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt// Local prototypes
223247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
223347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltstatic int
223447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltsimple_table_index (const char * table [], int size, const char * str);
223547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
223647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltstatic int
223747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalttable_index_name (const table_entry_t table [], int size, const char * str);
223847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
223947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltstatic int
224047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalttable_index_value (const table_entry_t table [], int size, int n);
224147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
224247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
224347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt//----------
224447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt// Global variables
224547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
224647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
224747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt//----------
224847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt// Util functions
224947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
225047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltint
225147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltcount_dots (const char * name)
225247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt{
225347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	int count = 0;
225447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	int i;
225547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	for (i = 0; name[i]; i++)
225647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	{
225747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		if (name [i] == k_dns_separator)
225847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			count++;
225947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	}
226047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
226147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	return count;
226247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt}
226347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
226447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
226547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltint
226647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltislocal (const char * name)
226747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt{
226847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	return cmp_dns_suffix (name, k_local_suffix) > 0;
226947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt}
227047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
227147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
227247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltint
227347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltrr_to_af (ns_type_t rrtype)
227447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt{
227547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	switch (rrtype)
227647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	{
227747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	  case kDNSServiceType_A:
227847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		return AF_INET;
227947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
228047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	  case kDNSServiceType_AAAA:
228147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		return AF_INET6;
228247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
228347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	  default:
228447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		return AF_UNSPEC;
228547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	}
228647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt}
228747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
228847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
228947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltns_type_t
229047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltaf_to_rr (int af)
229147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt{
229247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	switch (af)
229347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	{
229447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	  case AF_INET:
229547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		return kDNSServiceType_A;
229647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
229747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	  case AF_INET6:
229847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		return kDNSServiceType_AAAA;
229947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
230047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	  default:
230147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		//return ns_t_invalid;
230247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		return 0;
230347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	}
230447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt}
230547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
230647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
230747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltint
230847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltstr_to_af (const char * str)
230947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt{
231047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	int result =
231147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		table_index_name (k_table_af, k_table_af_size, str);
231247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	if (result < 0)
231347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		result = 0;
231447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
231547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	return k_table_af [result].value;
231647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt}
231747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
231847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
231947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltns_class_t
232047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltstr_to_ns_class (const char * str)
232147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt{
232247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	return (ns_class_t)
232347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		simple_table_index (k_table_ns_class, k_table_ns_class_size, str);
232447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt}
232547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
232647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
232747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltns_type_t
232847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltstr_to_ns_type (const char * str)
232947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt{
233047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	return (ns_type_t)
233147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		simple_table_index (k_table_ns_type, k_table_ns_type_size, str);
233247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt}
233347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
233447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
233547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltconst char *
233647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltaf_to_str (int in)
233747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt{
233847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	int result =
233947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		table_index_value (k_table_af, k_table_af_size, in);
234047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	if (result < 0)
234147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		result = 0;
234247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
234347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	return k_table_af [result].name;
234447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt}
234547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
234647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
234747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltconst char *
234847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltns_class_to_str (ns_class_t in)
234947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt{
235047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	if (in < k_table_ns_class_size)
235147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		return k_table_ns_class [in];
235247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	else
235347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		return NULL;
235447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt}
235547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
235647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
235747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltconst char *
235847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltns_type_to_str (ns_type_t in)
235947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt{
236047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	if (in < k_table_ns_type_size)
236147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		return k_table_ns_type [in];
236247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	else
236347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		return NULL;
236447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt}
236547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
236647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
236747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltchar *
236847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltformat_reverse_addr_in (
236947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	const struct in_addr * addr,
237047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	int prefixlen,
237147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	char * buf
237247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt)
237347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt{
237447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	char * curr = buf;
237547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	int i;
237647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
237747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	const uint8_t * in_addr_a = (uint8_t *) addr;
237847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
237947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	if (prefixlen > 32)
238047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		return NULL;
238147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	if (prefixlen < 0)
238247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		prefixlen = 32;
238347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
238447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	i = (prefixlen + 7) / 8;
238547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		// divide prefixlen into bytes, rounding up
238647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
238747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	while (i > 0)
238847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	{
238947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		i--;
239047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		curr += sprintf (curr, "%d.", in_addr_a [i]);
239147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	}
239247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	sprintf (curr, "in-addr.arpa");
239347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
239447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	return buf;
239547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt}
239647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
239747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
239847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltchar *
239947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltformat_reverse_addr_in6 (
240047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	const struct in6_addr * addr,
240147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	int prefixlen,
240247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	char * buf
240347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt)
240447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt{
240547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	char * curr = buf;
240647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	int i;
240747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
240847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	const uint8_t * in_addr_a = (uint8_t *) addr;
240947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
241047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	if (prefixlen > 128)
241147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		return NULL;
241247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	if (prefixlen < 0)
241347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		prefixlen = 128;
241447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
241547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	i = (prefixlen + 3) / 4;
241647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		// divide prefixlen into nibbles, rounding up
241747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
241847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	// Special handling for first
241947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	if (i % 2)
242047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	{
242147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		curr += sprintf (curr, "%d.", (in_addr_a [i/2] >> 4) & 0x0F);
242247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	}
242347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	i >>= 1;
242447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		// Convert i to bytes (divide by 2)
242547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
242647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	while (i > 0)
242747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	{
242847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		uint8_t val;
242947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
243047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		i--;
243147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		val = in_addr_a [i];
243247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		curr += sprintf (curr, "%x.%x.", val & 0x0F, (val >> 4) & 0x0F);
243347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	}
243447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	sprintf (curr, "ip6.arpa");
243547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
243647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	return buf;
243747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt}
243847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
243947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
244047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltchar *
244147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltformat_reverse_addr (
244247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	int af,
244347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	const void * addr,
244447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	int prefixlen,
244547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	char * buf
244647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt)
244747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt{
244847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	switch (af)
244947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	{
245047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	  case AF_INET:
245147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		return
245247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			format_reverse_addr_in (
245347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt				(struct in_addr *) addr, prefixlen, buf
245447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			);
245547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		break;
245647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
245747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	  case AF_INET6:
245847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		return
245947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			format_reverse_addr_in6 (
246047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt				(struct in6_addr *) addr, prefixlen, buf
246147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			);
246247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		break;
246347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
246447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	  default:
246547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		return NULL;
246647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	}
246747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt}
246847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
246947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
247047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltint
247147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltcmp_dns_suffix (const char * name, const char * domain)
247247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt{
247347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	const char * nametail;
247447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	const char * domaintail;
247547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
247647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	// Idiot checks
247747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	if (*name == 0 || *name == k_dns_separator)
247847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	{
247947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		// Name can't be empty or start with separator
248047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		return CMP_DNS_SUFFIX_BAD_NAME;
248147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	}
248247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
248347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	if (*domain == 0)
248447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	{
248547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		return CMP_DNS_SUFFIX_SUCCESS;
248647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			// trivially true
248747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	}
248847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
248947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	if (*domain == k_dns_separator)
249047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	{
249147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		// drop leading separator from domain
249247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		domain++;
249347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		if (*domain == k_dns_separator)
249447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		{
249547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			return CMP_DNS_SUFFIX_BAD_DOMAIN;
249647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		}
249747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	}
249847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
249947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	// Find ends of strings
250047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	for (nametail = name; *nametail; nametail++)
250147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		;
250247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	for (domaintail = domain; *domaintail; domaintail++)
250347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		;
250447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
250547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	// Shuffle back to last real character, and drop any trailing '.'
250647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	// while we're at it.
250747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	nametail --;
250847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	if (*nametail == k_dns_separator)
250947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	{
251047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		nametail --;
251147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		if (*nametail == k_dns_separator)
251247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		{
251347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			return CMP_DNS_SUFFIX_BAD_NAME;
251447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		}
251547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	}
251647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	domaintail --;
251747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	if (*domaintail == k_dns_separator)
251847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	{
251947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		domaintail --;
252047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		if (*domaintail == k_dns_separator)
252147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		{
252247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			return CMP_DNS_SUFFIX_BAD_DOMAIN;
252347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		}
252447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	}
252547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
252647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	// Compare.
252747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	while (
252847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		nametail >= name
252947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		&& domaintail >= domain
253047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		&& tolower(*nametail) == tolower(*domaintail))
253147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	{
253247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		nametail--;
253347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		domaintail--;
253447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	}
253547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
253647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	/* A successful finish will be one of the following:
253747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		(leading and trailing . ignored)
253847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
253947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		name  :  domain2.domain1
254047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		domain:  domain2.domain1
254147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		        ^
254247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
254347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		name  : domain3.domain2.domain1
254447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		domain:         domain2.domain1
254547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		               ^
254647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	 */
254747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	if (
254847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		domaintail < domain
254947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		&& (nametail < name || *nametail == k_dns_separator)
255047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	)
255147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	{
255247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		return CMP_DNS_SUFFIX_SUCCESS;
255347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	}
255447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	else
255547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	{
255647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		return CMP_DNS_SUFFIX_FAILURE;
255747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	}
255847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt}
255947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
256047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
256147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltint
256247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltdns_rdata_to_name (const char * rdata, int rdlen, char * name, int name_len)
256347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt{
256447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	int i = 0;
256547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		// Index into 'name'
256647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	const char * rdata_curr = rdata;
256747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
256847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	if (rdlen == 0) return DNS_RDATA_TO_NAME_BAD_FORMAT;
256947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
257047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	/*
257147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		In RDATA, a DNS name is stored as a series of labels.
257247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		Each label consists of a length octet (max value 63)
257347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		followed by the data for that label.
257447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		The series is terminated with a length 0 octet.
257547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		A length octet beginning with bits 11 is a pointer to
257647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		somewhere else in the payload, but we don't support these
257747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		since we don't have access to the entire payload.
257847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
257947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		See RFC1034 section 3.1 and RFC1035 section 3.1.
258047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	 */
258147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	while (1)
258247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	{
258347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		int term_len = *rdata_curr;
258447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		rdata_curr++;
258547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
258647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		if (term_len == 0)
258747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		{
258847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			break;
258947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt				// 0 length record terminates label
259047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		}
259147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		else if (term_len > k_label_maxlen)
259247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		{
259347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			name [i] = 0;
259447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			return DNS_RDATA_TO_NAME_PTR;
259547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		}
259647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		else if (rdata_curr + term_len > rdata + rdlen)
259747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		{
259847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			name [i] = 0;
259947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			return DNS_RDATA_TO_NAME_BAD_FORMAT;
260047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		}
260147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
260247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		if (name_len < i + term_len + 1)
260347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			// +1 is separator
260447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		{
260547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			name [i] = 0;
260647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			return DNS_RDATA_TO_NAME_TOO_LONG;
260747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		}
260847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
260947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		memcpy (name + i, rdata_curr, term_len);
261047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
261147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		i += term_len;
261247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		rdata_curr += term_len;
261347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
261447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		name [i] = k_dns_separator;
261547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		i++;
261647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	}
261747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
261847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	name [i] = 0;
261947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	return i;
262047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt}
262147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
262247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
262347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt//----------
262447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt// Local functions
262547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
262647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt/*
262747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	Find the index of an string entry in a table.  A case insenitive match
262847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	is performed.  If no entry is found, 0 is returned.
262947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
263047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	Parameters
263147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		table
263247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			Lookup table
263347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			Table entries may be NULL.  NULL entries will never match.
263447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		size
263547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			number of entries in table
263647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		str
263747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			lookup string
263847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
263947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	Result
264047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		index of first matching entry, or 0 if no matches
264147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt */
264247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltstatic int
264347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltsimple_table_index (const char * table [], int size, const char * str)
264447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt{
264547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	int i;
264647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	for (i = 0; i < size; i++)
264747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	{
264847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		if (
264947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			table [i]
265047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			&& (strcasecmp (table [i], str) == 0)
265147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		)
265247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		{
265347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			return i;
265447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		}
265547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	}
265647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
265747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	return 0;
265847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt}
265947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
266047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
266147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt/*
266247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	Find the index of a name in a table.
266347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
266447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	Parameters
266547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		table
266647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			array of table_entry_t records.  The name field is compared
266747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			(ignoring case) to the input string.
266847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		size
266947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			number of entries in table
267047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		str
267147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			lookup string
267247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
267347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	Result
267447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		index of first matching entry, or -1 if no matches
267547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt */
267647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltstatic int
267747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalttable_index_name (const table_entry_t table [], int size, const char * str)
267847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt{
267947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	int i;
268047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	for (i = 0; i < size; i++)
268147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	{
268247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		if (
268347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			table [i].name
268447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			&& (strcasecmp (table [i].name, str) == 0)
268547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		)
268647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		{
268747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			return i;
268847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		}
268947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	}
269047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
269147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	return -1;
269247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt}
269347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
269447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
269547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt/*
269647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	Find the index of a value a table.
269747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
269847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	Parameters
269947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		table
270047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			array of table_entry_t records.  The value field is compared to
270147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			the input value
270247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		size
270347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			number of entries in table
270447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		n
270547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			lookup value
270647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
270747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	Result
270847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		index of first matching entry, or -1 if no matches
270947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt */
271047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltstatic int
271147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalttable_index_value (const table_entry_t table [], int size, int n)
271247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt{
271347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	int i;
271447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	for (i = 0; i < size; i++)
271547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	{
271647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		if (table [i].value == n)
271747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		{
271847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt			return i;
271947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt		}
272047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	}
272147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt
272247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt	return -1;
272347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt}
2724