/*
-NICTA Public Software Licence
-Version 1.0
-
-Copyright © 2004 National ICT Australia Ltd
-
-All rights reserved.
-
-By this licence, National ICT Australia Ltd (NICTA) grants permission,
-free of charge, to any person who obtains a copy of this software
-and any associated documentation files ("the Software") to use and
-deal with the Software in source code and binary forms without
-restriction, with or without modification, and to permit persons
-to whom the Software is furnished to do so, provided that the
-following conditions are met:
-
-- Redistributions of source code must retain the above copyright
- notice, this list of conditions and the following disclaimers.
-- Redistributions in binary form must reproduce the above copyright
- notice, this list of conditions and the following disclaimers in
- the documentation and/or other materials provided with the
- distribution.
-- The name of NICTA may not be used to endorse or promote products
- derived from this Software without specific prior written permission.
-
-EXCEPT AS EXPRESSLY STATED IN THIS LICENCE AND TO THE FULL EXTENT
-PERMITTED BY APPLICABLE LAW, THE SOFTWARE IS PROVIDED "AS-IS" AND
-NICTA MAKES NO REPRESENTATIONS, WARRANTIES OR CONDITIONS OF ANY
-KIND, EXPRESS OR IMPLIED, INCLUDING, WITHOUT LIMITATION, ANY
-REPRESENTATIONS, WARRANTIES OR CONDITIONS REGARDING THE CONTENTS
-OR ACCURACY OF THE SOFTWARE, OR OF TITLE, MERCHANTABILITY, FITNESS
-FOR A PARTICULAR PURPOSE, NONINFRINGEMENT, THE ABSENCE OF LATENT
-OR OTHER DEFECTS, OR THE PRESENCE OR ABSENCE OF ERRORS, WHETHER OR
-NOT DISCOVERABLE.
-
-TO THE FULL EXTENT PERMITTED BY APPLICABLE LAW, IN NO EVENT WILL
-NICTA BE LIABLE ON ANY LEGAL THEORY (INCLUDING, WITHOUT LIMITATION,
-NEGLIGENCE) FOR ANY LOSS OR DAMAGE WHATSOEVER, INCLUDING (WITHOUT
-LIMITATION) LOSS OF PRODUCTION OR OPERATION TIME, LOSS, DAMAGE OR
-CORRUPTION OF DATA OR RECORDS; OR LOSS OF ANTICIPATED SAVINGS,
-OPPORTUNITY, REVENUE, PROFIT OR GOODWILL, OR OTHER ECONOMIC LOSS;
-OR ANY SPECIAL, INCIDENTAL, INDIRECT, CONSEQUENTIAL, PUNITIVE OR
-EXEMPLARY DAMAGES ARISING OUT OF OR IN CONNECTION WITH THIS LICENCE,
-THE SOFTWARE OR THE USE OF THE SOFTWARE, EVEN IF NICTA HAS BEEN
-ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
-
-If applicable legislation implies warranties or conditions, or
-imposes obligations or liability on NICTA in respect of the Software
-that cannot be wholly or partly excluded, restricted or modified,
-NICTA's liability is limited, to the full extent permitted by the
-applicable legislation, at its option, to:
-
-a. in the case of goods, any one or more of the following:
- i. the replacement of the goods or the supply of equivalent goods;
- ii. the repair of the goods;
- iii. the payment of the cost of replacing the goods or of acquiring
+ NICTA Public Software Licence
+ Version 1.0
+
+ Copyright © 2004 National ICT Australia Ltd
+
+ All rights reserved.
+
+ By this licence, National ICT Australia Ltd (NICTA) grants permission,
+ free of charge, to any person who obtains a copy of this software
+ and any associated documentation files ("the Software") to use and
+ deal with the Software in source code and binary forms without
+ restriction, with or without modification, and to permit persons
+ to whom the Software is furnished to do so, provided that the
+ following conditions are met:
+
+ - Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimers.
+ - Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimers in
+ the documentation and/or other materials provided with the
+ distribution.
+ - The name of NICTA may not be used to endorse or promote products
+ derived from this Software without specific prior written permission.
+
+ EXCEPT AS EXPRESSLY STATED IN THIS LICENCE AND TO THE FULL EXTENT
+ PERMITTED BY APPLICABLE LAW, THE SOFTWARE IS PROVIDED "AS-IS" AND
+ NICTA MAKES NO REPRESENTATIONS, WARRANTIES OR CONDITIONS OF ANY
+ KIND, EXPRESS OR IMPLIED, INCLUDING, WITHOUT LIMITATION, ANY
+ REPRESENTATIONS, WARRANTIES OR CONDITIONS REGARDING THE CONTENTS
+ OR ACCURACY OF THE SOFTWARE, OR OF TITLE, MERCHANTABILITY, FITNESS
+ FOR A PARTICULAR PURPOSE, NONINFRINGEMENT, THE ABSENCE OF LATENT
+ OR OTHER DEFECTS, OR THE PRESENCE OR ABSENCE OF ERRORS, WHETHER OR
+ NOT DISCOVERABLE.
+
+ TO THE FULL EXTENT PERMITTED BY APPLICABLE LAW, IN NO EVENT WILL
+ NICTA BE LIABLE ON ANY LEGAL THEORY (INCLUDING, WITHOUT LIMITATION,
+ NEGLIGENCE) FOR ANY LOSS OR DAMAGE WHATSOEVER, INCLUDING (WITHOUT
+ LIMITATION) LOSS OF PRODUCTION OR OPERATION TIME, LOSS, DAMAGE OR
+ CORRUPTION OF DATA OR RECORDS; OR LOSS OF ANTICIPATED SAVINGS,
+ OPPORTUNITY, REVENUE, PROFIT OR GOODWILL, OR OTHER ECONOMIC LOSS;
+ OR ANY SPECIAL, INCIDENTAL, INDIRECT, CONSEQUENTIAL, PUNITIVE OR
+ EXEMPLARY DAMAGES ARISING OUT OF OR IN CONNECTION WITH THIS LICENCE,
+ THE SOFTWARE OR THE USE OF THE SOFTWARE, EVEN IF NICTA HAS BEEN
+ ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+
+ If applicable legislation implies warranties or conditions, or
+ imposes obligations or liability on NICTA in respect of the Software
+ that cannot be wholly or partly excluded, restricted or modified,
+ NICTA's liability is limited, to the full extent permitted by the
+ applicable legislation, at its option, to:
+
+ a. in the case of goods, any one or more of the following:
+ i. the replacement of the goods or the supply of equivalent goods;
+ ii. the repair of the goods;
+ iii. the payment of the cost of replacing the goods or of acquiring
equivalent goods;
- iv. the payment of the cost of having the goods repaired; or
-b. in the case of services:
- i. the supplying of the services again; or
- ii. the payment of the cost of having the services supplied
+ iv. the payment of the cost of having the goods repaired; or
+ b. in the case of services:
+ i. the supplying of the services again; or
+ ii. the payment of the cost of having the services supplied
again.
*/
/*
- NSSwitch Implementation of mDNS interface.
-
- Andrew White (Andrew.White@nicta.com.au)
- May 2004
+ NSSwitch Implementation of mDNS interface.
+
+ Andrew White (Andrew.White@nicta.com.au)
+ May 2004
*/
#include <stdlib.h>
// Public functions
/*
- Count the number of dots in a name string.
+ Count the number of dots in a name string.
*/
int
count_dots (const char * name);
/*
- Test whether a domain name is local.
+ Test whether a domain name is local.
- Returns
- 1 if name ends with ".local" or ".local."
- 0 otherwise
+ Returns
+ 1 if name ends with ".local" or ".local."
+ 0 otherwise
*/
int
islocal (const char * name);
/*
- Format an address structure as a string appropriate for DNS reverse (PTR)
- lookup, based on address type.
-
- Parameters
- prefixlen
- Prefix length, in bits. When formatting, this will be rounded up
- to the nearest appropriate size. If -1, assume maximum.
- buf
- Output buffer. Must be long enough to hold largest possible
- output.
- Returns
- Pointer to (first character of) output buffer,
- or NULL on error.
+ Format an address structure as a string appropriate for DNS reverse (PTR)
+ lookup, based on address type.
+
+ Parameters
+ prefixlen
+ Prefix length, in bits. When formatting, this will be rounded up
+ to the nearest appropriate size. If -1, assume maximum.
+ buf
+ Output buffer. Must be long enough to hold largest possible
+ output.
+ Returns
+ Pointer to (first character of) output buffer,
+ or NULL on error.
*/
char *
format_reverse_addr (int af, const void * addr, int prefixlen, char * buf);
/*
- Format an address structure as a string appropriate for DNS reverse (PTR)
- lookup for AF_INET. Output is in .in-addr.arpa domain.
-
- Parameters
- prefixlen
- Prefix length, in bits. When formatting, this will be rounded up
- to the nearest byte (8). If -1, assume 32.
- buf
- Output buffer. Must be long enough to hold largest possible
- output. For AF_INET, this is 29 characters (including null).
- Returns
- Pointer to (first character of) output buffer,
- or NULL on error.
+ Format an address structure as a string appropriate for DNS reverse (PTR)
+ lookup for AF_INET. Output is in .in-addr.arpa domain.
+
+ Parameters
+ prefixlen
+ Prefix length, in bits. When formatting, this will be rounded up
+ to the nearest byte (8). If -1, assume 32.
+ buf
+ Output buffer. Must be long enough to hold largest possible
+ output. For AF_INET, this is 29 characters (including null).
+ Returns
+ Pointer to (first character of) output buffer,
+ or NULL on error.
*/
char *
format_reverse_addr_in (
- const struct in_addr * addr,
- int prefixlen,
- char * buf
-);
+ const struct in_addr * addr,
+ int prefixlen,
+ char * buf
+ );
#define DNS_PTR_AF_INET_SIZE 29
/*
- Format an address structure as a string appropriate for DNS reverse (PTR)
- lookup for AF_INET6. Output is in .ip6.int domain.
-
- Parameters
- prefixlen
- Prefix length, in bits. When formatting, this will be rounded up
- to the nearest nibble (4). If -1, assume 128.
- buf
- Output buffer. Must be long enough to hold largest possible
- output. For AF_INET6, this is 72 characters (including null).
- Returns
- Pointer to (first character of) output buffer,
- or NULL on error.
+ Format an address structure as a string appropriate for DNS reverse (PTR)
+ lookup for AF_INET6. Output is in .ip6.arpa domain.
+
+ Parameters
+ prefixlen
+ Prefix length, in bits. When formatting, this will be rounded up
+ to the nearest nibble (4). If -1, assume 128.
+ buf
+ Output buffer. Must be long enough to hold largest possible
+ output. For AF_INET6, this is 72 characters (including null).
+ Returns
+ Pointer to (first character of) output buffer,
+ or NULL on error.
*/
char *
format_reverse_addr_in6 (
- const struct in6_addr * addr,
- int prefixlen,
- char * buf
-);
+ const struct in6_addr * addr,
+ int prefixlen,
+ char * buf
+ );
#define DNS_PTR_AF_INET6_SIZE 72
/*
- Compare whether the given dns name has the given domain suffix.
- A single leading '.' on the name or leading or trailing '.' on the
- domain is ignored for the purposes of the comparison.
- Multiple leading or trailing '.'s are an error. Other DNS syntax
- errors are not checked for. The comparison is case insensitive.
-
- Returns
- 1 on success (match)
- 0 on failure (no match)
- < 0 on error
+ Compare whether the given dns name has the given domain suffix.
+ A single leading '.' on the name or leading or trailing '.' on the
+ domain is ignored for the purposes of the comparison.
+ Multiple leading or trailing '.'s are an error. Other DNS syntax
+ errors are not checked for. The comparison is case insensitive.
+
+ Returns
+ 1 on success (match)
+ 0 on failure (no match)
+ < 0 on error
*/
int
cmp_dns_suffix (const char * name, const char * domain);
enum
{
- CMP_DNS_SUFFIX_SUCCESS = 1,
- CMP_DNS_SUFFIX_FAILURE = 0,
- CMP_DNS_SUFFIX_BAD_NAME = 1,
- CMP_DNS_SUFFIX_BAD_DOMAIN = -2
+ CMP_DNS_SUFFIX_SUCCESS = 1,
+ CMP_DNS_SUFFIX_FAILURE = 0,
+ CMP_DNS_SUFFIX_BAD_NAME = 1,
+ CMP_DNS_SUFFIX_BAD_DOMAIN = -2
};
typedef int ns_type_t;
typedef int ns_class_t;
/*
- Convert a DNS resource record (RR) code to an address family (AF) code.
-
- Parameters
- rrtype
- resource record type (from nameser.h)
-
- Returns
- Appropriate AF code (from socket.h), or AF_UNSPEC if an appropriate
- mapping couldn't be determined
+ Convert a DNS resource record (RR) code to an address family (AF) code.
+
+ Parameters
+ rrtype
+ resource record type (from nameser.h)
+
+ Returns
+ Appropriate AF code (from socket.h), or AF_UNSPEC if an appropriate
+ mapping couldn't be determined
*/
int
rr_to_af (ns_type_t rrtype);
/*
- Convert an address family (AF) code to a DNS resource record (RR) code.
-
- Parameters
- int
- address family code (from socket.h)
- Returns
- Appropriate RR code (from nameser.h), or ns_t_invalid if an appropriate
- mapping couldn't be determined
+ Convert an address family (AF) code to a DNS resource record (RR) code.
+
+ Parameters
+ int
+ address family code (from socket.h)
+ Returns
+ Appropriate RR code (from nameser.h), or ns_t_invalid if an appropriate
+ mapping couldn't be determined
*/
ns_type_t
af_to_rr (int af);
/*
- Convert a string to an address family (case insensitive).
+ Convert a string to an address family (case insensitive).
- Returns
- Matching AF code, or AF_UNSPEC if no match found.
+ Returns
+ Matching AF code, or AF_UNSPEC if no match found.
*/
int
str_to_af (const char * str);
/*
- Convert a string to an ns_class_t (case insensitive).
+ Convert a string to an ns_class_t (case insensitive).
- Returns
- Matching ns_class_t, or ns_c_invalid if no match found.
+ Returns
+ Matching ns_class_t, or ns_c_invalid if no match found.
*/
ns_class_t
str_to_ns_class (const char * str);
/*
- Convert a string to an ns_type_t (case insensitive).
+ Convert a string to an ns_type_t (case insensitive).
- Returns
- Matching ns_type_t, or ns_t_invalid if no match found.
+ Returns
+ Matching ns_type_t, or ns_t_invalid if no match found.
*/
ns_type_t
str_to_ns_type (const char * str);
/*
- Convert an address family code to a string.
+ Convert an address family code to a string.
- Returns
- String representation of AF,
- or NULL if address family unrecognised or invalid.
+ Returns
+ String representation of AF,
+ or NULL if address family unrecognised or invalid.
*/
const char *
af_to_str (int in);
/*
- Convert an ns_class_t code to a string.
+ Convert an ns_class_t code to a string.
- Returns
- String representation of ns_class_t,
- or NULL if ns_class_t unrecognised or invalid.
+ Returns
+ String representation of ns_class_t,
+ or NULL if ns_class_t unrecognised or invalid.
*/
const char *
ns_class_to_str (ns_class_t in);
/*
- Convert an ns_type_t code to a string.
+ Convert an ns_type_t code to a string.
- Returns
- String representation of ns_type_t,
- or NULL if ns_type_t unrecognised or invalid.
+ Returns
+ String representation of ns_type_t,
+ or NULL if ns_type_t unrecognised or invalid.
*/
const char *
ns_type_to_str (ns_type_t in);
/*
- Convert DNS rdata in label format (RFC1034, RFC1035) to a name.
-
- On error, partial data is written to name (as much as was successfully
- processed) and an error code is returned. Errors include a name too
- long for the buffer and a pointer in the label (which cannot be
- resolved).
-
- Parameters
- rdata
- Rdata formatted as series of labels.
- rdlen
- Length of rdata buffer.
- name
- Buffer to store fully qualified result in.
- By RFC1034 section 3.1, a 255 character buffer (256 characters
- including null) is long enough for any legal name.
- name_len
- Number of characters available in name buffer, not including
- trailing null.
-
- Returns
- Length of name buffer (not including trailing null).
- < 0 on error.
- A return of 0 implies the empty domain.
+ Convert DNS rdata in label format (RFC1034, RFC1035) to a name.
+
+ On error, partial data is written to name (as much as was successfully
+ processed) and an error code is returned. Errors include a name too
+ long for the buffer and a pointer in the label (which cannot be
+ resolved).
+
+ Parameters
+ rdata
+ Rdata formatted as series of labels.
+ rdlen
+ Length of rdata buffer.
+ name
+ Buffer to store fully qualified result in.
+ By RFC1034 section 3.1, a 255 character buffer (256 characters
+ including null) is long enough for any legal name.
+ name_len
+ Number of characters available in name buffer, not including
+ trailing null.
+
+ Returns
+ Length of name buffer (not including trailing null).
+ < 0 on error.
+ A return of 0 implies the empty domain.
*/
-int
-dns_rdata_to_name (const char * rdata, int rdlen, char * name, int name_len);
+static int
+dns_rdata_to_name (const unsigned char * rdata, int rdlen, char * name, unsigned int name_len);
enum
{
- DNS_RDATA_TO_NAME_BAD_FORMAT = -1,
- // Format is broken. Usually because we ran out of data
- // (according to rdata) before the labels said we should.
- DNS_RDATA_TO_NAME_TOO_LONG = -2,
- // The converted rdata is longer than the name buffer.
- DNS_RDATA_TO_NAME_PTR = -3,
- // The rdata contains a pointer.
+ DNS_RDATA_TO_NAME_BAD_FORMAT = -1,
+ // Format is broken. Usually because we ran out of data
+ // (according to rdata) before the labels said we should.
+ DNS_RDATA_TO_NAME_TOO_LONG = -2,
+ // The converted rdata is longer than the name buffer.
+ DNS_RDATA_TO_NAME_PTR = -3,
+ // The rdata contains a pointer.
};
#define DNS_LABEL_MAXLEN 63
- // Maximum length of a single DNS label
-#define DNS_NAME_MAXLEN 255
- // Maximum length of a DNS name
+// Maximum length of a single DNS label
+#define DNS_NAME_MAXLEN 256
+// Maximum length of a DNS name
//----------
// Public types
typedef int errcode_t;
- // Used for 0 = success, non-zero = error code functions
+// Used for 0 = success, non-zero = error code functions
//----------
// Public functions
/*
- Test whether a domain name is in a domain covered by nss_mdns.
- The name is assumed to be fully qualified (trailing dot optional);
- unqualified names will be processed but may return unusual results
- if the unqualified prefix happens to match a domain suffix.
-
- Returns
- 1 success
- 0 failure
- -1 error, check errno
+ Test whether a domain name is in a domain covered by nss_mdns.
+ The name is assumed to be fully qualified (trailing dot optional);
+ unqualified names will be processed but may return unusual results
+ if the unqualified prefix happens to match a domain suffix.
+
+ Returns
+ 1 success
+ 0 failure
+ -1 error, check errno
*/
int
config_is_mdns_suffix (const char * name);
/*
- Loads all relevant data from configuration file. Other code should
- rarely need to call this function, since all other public configuration
- functions do so implicitly. Once loaded, configuration info doesn't
- change.
-
- Returns
- 0 configuration ready
- non-zero configuration error code
+ Loads all relevant data from configuration file. Other code should
+ rarely need to call this function, since all other public configuration
+ functions do so implicitly. Once loaded, configuration info doesn't
+ change.
+
+ Returns
+ 0 configuration ready
+ non-zero configuration error code
*/
errcode_t
init_config ();
#define DATABASE "hosts"
#include <nss.h>
- // For nss_status
+// For nss_status
#include <netdb.h>
- // For hostent
+// For hostent
#include <sys/types.h>
- // For size_t
+// For size_t
typedef enum nss_status nss_status;
typedef struct hostent hostent;
/*
-gethostbyname implementation
-
- name:
- name to look up
- result_buf:
- resulting entry
- buf:
- auxillary buffer
- buflen:
- length of auxillary buffer
- errnop:
- pointer to errno
- h_errnop:
- pointer to h_errno
+ gethostbyname implementation
+
+ name:
+ name to look up
+ result_buf:
+ resulting entry
+ buf:
+ auxillary buffer
+ buflen:
+ length of auxillary buffer
+ errnop:
+ pointer to errno
+ h_errnop:
+ pointer to h_errno
*/
nss_status
_nss_mdns_gethostbyname_r (
- const char *name,
- hostent * result_buf,
- char *buf,
- size_t buflen,
- int *errnop,
- int *h_errnop
-);
+ const char *name,
+ hostent * result_buf,
+ char *buf,
+ size_t buflen,
+ int *errnop,
+ int *h_errnop
+ );
/*
-gethostbyname2 implementation
-
- name:
- name to look up
- af:
- address family
- result_buf:
- resulting entry
- buf:
- auxillary buffer
- buflen:
- length of auxillary buffer
- errnop:
- pointer to errno
- h_errnop:
- pointer to h_errno
+ gethostbyname2 implementation
+
+ name:
+ name to look up
+ af:
+ address family
+ result_buf:
+ resulting entry
+ buf:
+ auxillary buffer
+ buflen:
+ length of auxillary buffer
+ errnop:
+ pointer to errno
+ h_errnop:
+ pointer to h_errno
*/
nss_status
_nss_mdns_gethostbyname2_r (
- const char *name,
- int af,
- hostent * result_buf,
- char *buf,
- size_t buflen,
- int *errnop,
- int *h_errnop
-);
+ const char *name,
+ int af,
+ hostent * result_buf,
+ char *buf,
+ size_t buflen,
+ int *errnop,
+ int *h_errnop
+ );
/*
-gethostbyaddr implementation
-
- addr:
- address structure to look up
- len:
- length of address structure
- af:
- address family
- result_buf:
- resulting entry
- buf:
- auxillary buffer
- buflen:
- length of auxillary buffer
- errnop:
- pointer to errno
- h_errnop:
- pointer to h_errno
+ gethostbyaddr implementation
+
+ addr:
+ address structure to look up
+ len:
+ length of address structure
+ af:
+ address family
+ result_buf:
+ resulting entry
+ buf:
+ auxillary buffer
+ buflen:
+ length of auxillary buffer
+ errnop:
+ pointer to errno
+ h_errnop:
+ pointer to h_errno
*/
nss_status
_nss_mdns_gethostbyaddr_r (
- const void *addr,
- socklen_t len,
- int af,
- hostent * result_buf,
- char *buf,
- size_t buflen,
- int *errnop,
- int *h_errnop
-);
+ const void *addr,
+ socklen_t len,
+ int af,
+ hostent * result_buf,
+ char *buf,
+ size_t buflen,
+ int *errnop,
+ int *h_errnop
+ );
//----------
// Types and Constants
const int MDNS_VERBOSE = 0;
- // This enables verbose syslog messages
- // If zero, only "imporant" messages will appear in syslog
+// This enables verbose syslog messages
+// If zero, only "imporant" messages will appear in syslog
-#define k_hostname_maxlen 255
- // As per RFC1034 and RFC1035
+#define k_hostname_maxlen 256
+// As per RFC1034 and RFC1035
#define k_aliases_max 15
#define k_addrs_max 15
-const int k_mdnsd_intfs_local = 0;
- // Tell mdnsd to perform lookups only using link-local interfaces.
- /*
- Currently, this feature is buggy. 0 will actually cause mdnsd to
- do what it thinks is best. Unfortunately, this is to lookup 'local'
- addresses locally and remote addresses via the DNS. Thus, lookups
- for non-"local" addresses via mdns will not work correctly.
-
- Apple is currently modifying mdnsd to allow a special interface id
- (expected value -2) to mean "always lookup locally". This constant
- should be changed once the change is made.
-
- AW - 16 June 2004
- */
-
-
typedef struct buf_header
{
- char hostname [k_hostname_maxlen + 1];
- char * aliases [k_aliases_max + 1];
- char * addrs [k_addrs_max + 1];
+ char hostname [k_hostname_maxlen + 1];
+ char * aliases [k_aliases_max + 1];
+ char * addrs [k_addrs_max + 1];
} buf_header_t;
typedef struct result_map
{
- int done;
- nss_status status;
- hostent * hostent;
- buf_header_t * header;
- int aliases_count;
- int addrs_count;
- char * buffer;
- int addr_idx;
- // Index for addresses - grow from low end
- // Index points to first empty space
- int alias_idx;
- // Index for aliases - grow from high end
- // Index points to lowest entry
- int r_errno;
- int r_h_errno;
+ int done;
+ nss_status status;
+ hostent * hostent;
+ buf_header_t * header;
+ int aliases_count;
+ int addrs_count;
+ char * buffer;
+ int addr_idx;
+ // Index for addresses - grow from low end
+ // Index points to first empty space
+ int alias_idx;
+ // Index for aliases - grow from high end
+ // Index points to lowest entry
+ int r_errno;
+ int r_h_errno;
} result_map_t;
static const struct timeval
- k_select_time = { 0, 500000 };
- // 0 seconds, 500 milliseconds
+k_select_time = { 0, 500000 };
+// 0 seconds, 500 milliseconds
//----------
// Local prototypes
static nss_status
mdns_gethostbyname2 (
- const char *name,
- int af,
- hostent * result_buf,
- char *buf,
- size_t buflen,
- int *errnop,
- int *h_errnop
-);
+ const char *name,
+ int af,
+ hostent * result_buf,
+ char *buf,
+ size_t buflen,
+ int *errnop,
+ int *h_errnop
+ );
/*
- Lookup name using mDNS server
+ Lookup name using mDNS server
*/
static nss_status
mdns_lookup_name (
- const char * fullname,
- int af,
- result_map_t * result
-);
+ const char * fullname,
+ int af,
+ result_map_t * result
+ );
/*
- Lookup address using mDNS server
+ Lookup address using mDNS server
*/
static nss_status
mdns_lookup_addr (
- const void * addr,
- socklen_t len,
- int af,
- const char * addr_str,
- result_map_t * result
-);
+ const void * addr,
+ socklen_t len,
+ int af,
+ const char * addr_str,
+ result_map_t * result
+ );
/*
- Handle incoming MDNS events
+ Handle incoming MDNS events
*/
static nss_status
handle_events (DNSServiceRef sdref, result_map_t * result, const char * str);
typedef void
mdns_lookup_callback_t
(
- DNSServiceRef sdref,
- DNSServiceFlags flags,
- uint32_t interface_index,
- DNSServiceErrorType error_code,
- const char *fullname,
- uint16_t rrtype,
- uint16_t rrclass,
- uint16_t rdlen,
- const void *rdata,
- uint32_t ttl,
- void *context
+ DNSServiceRef sdref,
+ DNSServiceFlags flags,
+ uint32_t interface_index,
+ DNSServiceErrorType error_code,
+ const char *fullname,
+ uint16_t rrtype,
+ uint16_t rrclass,
+ uint16_t rdlen,
+ const void *rdata,
+ uint32_t ttl,
+ void *context
);
mdns_lookup_callback_t mdns_lookup_callback;
static int
init_result (
- result_map_t * result,
- hostent * result_buf,
- char * buf,
- size_t buflen
-);
+ result_map_t * result,
+ hostent * result_buf,
+ char * buf,
+ size_t buflen
+ );
static int
callback_body_ptr (
- const char * fullname,
- result_map_t * result,
- int rdlen,
- const void * rdata
-);
+ const char * fullname,
+ result_map_t * result,
+ int rdlen,
+ const void * rdata
+ );
static void *
add_address_to_buffer (result_map_t * result, const void * data, int len);
static const char *
is_applicable_name (
- result_map_t * result,
- const char * name,
- char * lookup_name
-);
+ result_map_t * result,
+ const char * name,
+ char * lookup_name
+ );
static const char *
is_applicable_addr (
- result_map_t * result,
- const void * addr,
- int af,
- char * addr_str
-);
+ result_map_t * result,
+ const void * addr,
+ int af,
+ char * addr_str
+ );
// Error code functions
nss_status
_nss_mdns_gethostbyname_r (
- const char *name,
- hostent * result_buf,
- char *buf,
- size_t buflen,
- int *errnop,
- int *h_errnop
-)
+ const char *name,
+ hostent * result_buf,
+ char *buf,
+ size_t buflen,
+ int *errnop,
+ int *h_errnop
+ )
{
- if (MDNS_VERBOSE)
- syslog (LOG_DEBUG,
- "mdns: Called nss_mdns_gethostbyname with %s",
- name
- );
-
- return
- mdns_gethostbyname2 (
- name, AF_INET, result_buf, buf, buflen, errnop, h_errnop
- );
+ if (MDNS_VERBOSE)
+ syslog (LOG_DEBUG,
+ "mdns: Called nss_mdns_gethostbyname with %s",
+ name
+ );
+
+ return
+ mdns_gethostbyname2 (
+ name, AF_INET, result_buf, buf, buflen, errnop, h_errnop
+ );
}
nss_status
_nss_mdns_gethostbyname2_r (
- const char *name,
- int af,
- hostent * result_buf,
- char *buf,
- size_t buflen,
- int *errnop,
- int *h_errnop
-)
+ const char *name,
+ int af,
+ hostent * result_buf,
+ char *buf,
+ size_t buflen,
+ int *errnop,
+ int *h_errnop
+ )
{
- if (MDNS_VERBOSE)
- syslog (LOG_DEBUG,
- "mdns: Called nss_mdns_gethostbyname2 with %s",
- name
- );
-
- return
- mdns_gethostbyname2 (
- name, af, result_buf, buf, buflen, errnop, h_errnop
- );
+ if (MDNS_VERBOSE)
+ syslog (LOG_DEBUG,
+ "mdns: Called nss_mdns_gethostbyname2 with %s",
+ name
+ );
+
+ return
+ mdns_gethostbyname2 (
+ name, af, result_buf, buf, buflen, errnop, h_errnop
+ );
}
nss_status
_nss_mdns_gethostbyaddr_r (
- const void *addr,
- socklen_t len,
- int af,
- hostent * result_buf,
- char *buf,
- size_t buflen,
- int *errnop,
- int *h_errnop
-)
+ const void *addr,
+ socklen_t len,
+ int af,
+ hostent * result_buf,
+ char *buf,
+ size_t buflen,
+ int *errnop,
+ int *h_errnop
+ )
{
- char addr_str [NI_MAXHOST + 1];
- result_map_t result;
- int err_status;
-
- if (inet_ntop (af, addr, addr_str, NI_MAXHOST) == NULL)
- {
- const char * family = af_to_str (af);
- if (family == NULL)
- {
- family = "Unknown";
- }
-
- syslog (LOG_WARNING,
- "mdns: Couldn't covert address, family %d (%s) in nss_mdns_gethostbyaddr: %s",
- af,
- family,
- strerror (errno)
- );
-
- // This address family never applicable to us, so return NOT_FOUND
-
- *errnop = ENOENT;
- *h_errnop = HOST_NOT_FOUND;
- return NSS_STATUS_NOTFOUND;
- }
- if (MDNS_VERBOSE)
- {
- syslog (LOG_DEBUG,
- "mdns: Called nss_mdns_gethostbyaddr with %s",
- addr_str
- );
- }
-
- // Initialise result
- err_status = init_result (&result, result_buf, buf, buflen);
- if (err_status)
- {
- *errnop = err_status;
- *h_errnop = NETDB_INTERNAL;
- return NSS_STATUS_TRYAGAIN;
- }
-
- if (is_applicable_addr (&result, addr, af, addr_str))
- {
- nss_status rv;
-
- rv = mdns_lookup_addr (addr, len, af, addr_str, &result);
- if (rv == NSS_STATUS_SUCCESS)
- {
- return rv;
- }
- }
-
- // Return current error status (defaults to NOT_FOUND)
-
- *errnop = result.r_errno;
- *h_errnop = result.r_h_errno;
- return result.status;
+ char addr_str [NI_MAXHOST + 1];
+ result_map_t result;
+ int err_status;
+
+ if (inet_ntop (af, addr, addr_str, NI_MAXHOST) == NULL)
+ {
+ const char * family = af_to_str (af);
+ if (family == NULL)
+ {
+ family = "Unknown";
+ }
+
+ syslog (LOG_WARNING,
+ "mdns: Couldn't covert address, family %d (%s) in nss_mdns_gethostbyaddr: %s",
+ af,
+ family,
+ strerror (errno)
+ );
+
+ // This address family never applicable to us, so return NOT_FOUND
+
+ *errnop = ENOENT;
+ *h_errnop = HOST_NOT_FOUND;
+ return NSS_STATUS_NOTFOUND;
+ }
+ if (MDNS_VERBOSE)
+ {
+ syslog (LOG_DEBUG,
+ "mdns: Called nss_mdns_gethostbyaddr with %s",
+ addr_str
+ );
+ }
+
+ // Initialise result
+ err_status = init_result (&result, result_buf, buf, buflen);
+ if (err_status)
+ {
+ *errnop = err_status;
+ *h_errnop = NETDB_INTERNAL;
+ return NSS_STATUS_TRYAGAIN;
+ }
+
+ if (is_applicable_addr (&result, addr, af, addr_str))
+ {
+ nss_status rv;
+
+ rv = mdns_lookup_addr (addr, len, af, addr_str, &result);
+ if (rv == NSS_STATUS_SUCCESS)
+ {
+ return rv;
+ }
+ }
+
+ // Return current error status (defaults to NOT_FOUND)
+
+ *errnop = result.r_errno;
+ *h_errnop = result.r_h_errno;
+ return result.status;
}
nss_status
mdns_gethostbyname2 (
- const char *name,
- int af,
- hostent * result_buf,
- char *buf,
- size_t buflen,
- int *errnop,
- int *h_errnop
-)
+ const char *name,
+ int af,
+ hostent * result_buf,
+ char *buf,
+ size_t buflen,
+ int *errnop,
+ int *h_errnop
+ )
{
- char lookup_name [k_hostname_maxlen + 1];
- result_map_t result;
- int err_status;
-
- // Initialise result
- err_status = init_result (&result, result_buf, buf, buflen);
- if (err_status)
- {
- *errnop = err_status;
- *h_errnop = NETDB_INTERNAL;
- return NSS_STATUS_TRYAGAIN;
- }
-
- if (is_applicable_name (&result, name, lookup_name))
- {
- // Try using mdns
- nss_status rv;
-
- if (MDNS_VERBOSE)
- syslog (LOG_DEBUG,
- "mdns: Local name: %s",
- name
- );
-
- rv = mdns_lookup_name (name, af, &result);
- if (rv == NSS_STATUS_SUCCESS)
- {
- return rv;
- }
- }
-
- // Return current error status (defaults to NOT_FOUND)
-
- *errnop = result.r_errno;
- *h_errnop = result.r_h_errno;
- return result.status;
+ char lookup_name [k_hostname_maxlen + 1];
+ result_map_t result;
+ int err_status;
+
+ // Initialise result
+ err_status = init_result (&result, result_buf, buf, buflen);
+ if (err_status)
+ {
+ *errnop = err_status;
+ *h_errnop = NETDB_INTERNAL;
+ return NSS_STATUS_TRYAGAIN;
+ }
+
+ if (is_applicable_name (&result, name, lookup_name))
+ {
+ // Try using mdns
+ nss_status rv;
+
+ if (MDNS_VERBOSE)
+ syslog (LOG_DEBUG,
+ "mdns: Local name: %s",
+ name
+ );
+
+ rv = mdns_lookup_name (name, af, &result);
+ if (rv == NSS_STATUS_SUCCESS)
+ {
+ return rv;
+ }
+ }
+
+ // Return current error status (defaults to NOT_FOUND)
+
+ *errnop = result.r_errno;
+ *h_errnop = result.r_h_errno;
+ return result.status;
}
/*
- Lookup a fully qualified hostname using the default record type
- for the specified address family.
-
- Parameters
- fullname
- Fully qualified hostname. If not fully qualified the code will
- still 'work', but the lookup is unlikely to succeed.
- af
- Either AF_INET or AF_INET6. Other families are not supported.
- result
- Initialised 'result' data structure.
+ Lookup a fully qualified hostname using the default record type
+ for the specified address family.
+
+ Parameters
+ fullname
+ Fully qualified hostname. If not fully qualified the code will
+ still 'work', but the lookup is unlikely to succeed.
+ af
+ Either AF_INET or AF_INET6. Other families are not supported.
+ result
+ Initialised 'result' data structure.
*/
static nss_status
mdns_lookup_name (
- const char * fullname,
- int af,
- result_map_t * result
-)
+ const char * fullname,
+ int af,
+ result_map_t * result
+ )
{
- // Lookup using mDNS.
- DNSServiceErrorType errcode;
- DNSServiceRef sdref;
- ns_type_t rrtype;
- nss_status status;
-
- if (MDNS_VERBOSE)
- syslog (LOG_DEBUG,
- "mdns: Attempting lookup of %s",
- fullname
- );
-
- switch (af)
- {
- case AF_INET:
- rrtype = T_A;
- result->hostent->h_length = 4;
- // Length of an A record
- break;
-
- case AF_INET6:
- rrtype = T_AAAA;
- result->hostent->h_length = 16;
- // Length of an AAAA record
- break;
-
- default:
- syslog (LOG_WARNING,
- "mdns: Unsupported address family %d",
- af
- );
- return set_err_bad_hostname (result);
- }
- result->hostent->h_addrtype = af;
-
- errcode =
- DNSServiceQueryRecord (
- &sdref,
- 0, // reserved flags field
- k_mdnsd_intfs_local, // all local interfaces
- fullname, // full name to query for
- rrtype, // resource record type
- C_IN, // internet class records
- mdns_lookup_callback, // callback
- result // Context - result buffer
- );
-
- if (errcode)
- {
- syslog (LOG_WARNING,
- "mdns: Failed to initialise lookup, error %d",
- errcode
- );
- return set_err_mdns_failed (result);
- }
-
- status = handle_events (sdref, result, fullname);
- DNSServiceRefDeallocate (sdref);
- return status;
+ // Lookup using mDNS.
+ DNSServiceErrorType errcode;
+ DNSServiceRef sdref;
+ ns_type_t rrtype;
+ nss_status status;
+
+ if (MDNS_VERBOSE)
+ syslog (LOG_DEBUG,
+ "mdns: Attempting lookup of %s",
+ fullname
+ );
+
+ switch (af)
+ {
+ case AF_INET:
+ rrtype = kDNSServiceType_A;
+ result->hostent->h_length = 4;
+ // Length of an A record
+ break;
+
+ case AF_INET6:
+ rrtype = kDNSServiceType_AAAA;
+ result->hostent->h_length = 16;
+ // Length of an AAAA record
+ break;
+
+ default:
+ syslog (LOG_WARNING,
+ "mdns: Unsupported address family %d",
+ af
+ );
+ return set_err_bad_hostname (result);
+ }
+ result->hostent->h_addrtype = af;
+
+ errcode =
+ DNSServiceQueryRecord (
+ &sdref,
+ kDNSServiceFlagsForceMulticast, // force multicast query
+ kDNSServiceInterfaceIndexAny, // all interfaces
+ fullname, // full name to query for
+ rrtype, // resource record type
+ kDNSServiceClass_IN, // internet class records
+ mdns_lookup_callback, // callback
+ result // Context - result buffer
+ );
+
+ if (errcode)
+ {
+ syslog (LOG_WARNING,
+ "mdns: Failed to initialise lookup, error %d",
+ errcode
+ );
+ return set_err_mdns_failed (result);
+ }
+
+ status = handle_events (sdref, result, fullname);
+ DNSServiceRefDeallocate (sdref);
+ return status;
}
/*
- Reverse (PTR) lookup for the specified address.
-
- Parameters
- addr
- Either a struct in_addr or a struct in6_addr
- addr_len
- size of the address
- af
- Either AF_INET or AF_INET6. Other families are not supported.
- Must match addr
- addr_str
- Address in format suitable for PTR lookup.
- AF_INET: a.b.c.d -> d.c.b.a.in-addr.arpa
- AF_INET6: reverse nibble format, x.x.x...x.ip6.arpa
- result
- Initialised 'result' data structure.
+ Reverse (PTR) lookup for the specified address.
+
+ Parameters
+ addr
+ Either a struct in_addr or a struct in6_addr
+ addr_len
+ size of the address
+ af
+ Either AF_INET or AF_INET6. Other families are not supported.
+ Must match addr
+ addr_str
+ Address in format suitable for PTR lookup.
+ AF_INET: a.b.c.d -> d.c.b.a.in-addr.arpa
+ AF_INET6: reverse nibble format, x.x.x...x.ip6.arpa
+ result
+ Initialised 'result' data structure.
*/
static nss_status
mdns_lookup_addr (
- const void * addr,
- socklen_t addr_len,
- int af,
- const char * addr_str,
- result_map_t * result
-)
+ const void * addr,
+ socklen_t addr_len,
+ int af,
+ const char * addr_str,
+ result_map_t * result
+ )
{
- DNSServiceErrorType errcode;
- DNSServiceRef sdref;
- nss_status status;
-
- if (MDNS_VERBOSE)
- syslog (LOG_DEBUG,
- "mdns: Attempting lookup of %s",
- addr_str
- );
-
- result->hostent->h_addrtype = af;
- result->hostent->h_length = addr_len;
-
- // Query address becomes "address" in result.
- if (! add_address_to_buffer (result, addr, addr_len))
- {
- return result->status;
- }
-
- result->hostent->h_name [0] = 0;
-
- errcode =
- DNSServiceQueryRecord (
- &sdref,
- 0, // reserved flags field
- k_mdnsd_intfs_local, // all local interfaces
- addr_str, // address string to query for
- T_PTR, // pointer RRs
- C_IN, // internet class records
- mdns_lookup_callback, // callback
- result // Context - result buffer
- );
-
- if (errcode)
- {
- syslog (LOG_WARNING,
- "mdns: Failed to initialise mdns lookup, error %d",
- errcode
- );
- return set_err_mdns_failed (result);
- }
-
- status = handle_events (sdref, result, addr_str);
- DNSServiceRefDeallocate (sdref);
- return status;
+ DNSServiceErrorType errcode;
+ DNSServiceRef sdref;
+ nss_status status;
+
+ if (MDNS_VERBOSE)
+ syslog (LOG_DEBUG,
+ "mdns: Attempting lookup of %s",
+ addr_str
+ );
+
+ result->hostent->h_addrtype = af;
+ result->hostent->h_length = addr_len;
+
+ // Query address becomes "address" in result.
+ if (!add_address_to_buffer (result, addr, addr_len))
+ {
+ return result->status;
+ }
+
+ result->hostent->h_name [0] = 0;
+
+ errcode =
+ DNSServiceQueryRecord (
+ &sdref,
+ kDNSServiceFlagsForceMulticast, // force multicast query
+ kDNSServiceInterfaceIndexAny, // all interfaces
+ addr_str, // address string to query for
+ kDNSServiceType_PTR, // pointer RRs
+ kDNSServiceClass_IN, // internet class records
+ mdns_lookup_callback, // callback
+ result // Context - result buffer
+ );
+
+ if (errcode)
+ {
+ syslog (LOG_WARNING,
+ "mdns: Failed to initialise mdns lookup, error %d",
+ errcode
+ );
+ return set_err_mdns_failed (result);
+ }
+
+ status = handle_events (sdref, result, addr_str);
+ DNSServiceRefDeallocate (sdref);
+ return status;
}
/*
- Wait on result of callback, and process it when it arrives.
-
- Parameters
- sdref
- dns-sd reference
- result
- Initialised 'result' data structure.
- str
- lookup string, used for status/error reporting.
+ Wait on result of callback, and process it when it arrives.
+
+ Parameters
+ sdref
+ dns-sd reference
+ result
+ Initialised 'result' data structure.
+ str
+ lookup string, used for status/error reporting.
*/
static nss_status
handle_events (DNSServiceRef sdref, result_map_t * result, const char * str)
{
- int dns_sd_fd = DNSServiceRefSockFD(sdref);
- int nfds = dns_sd_fd + 1;
- fd_set readfds;
- struct timeval tv;
- int select_result;
-
- while (! result->done)
- {
- FD_ZERO(&readfds);
- FD_SET(dns_sd_fd, &readfds);
-
- tv = k_select_time;
-
- select_result =
- select (nfds, &readfds, (fd_set*)NULL, (fd_set*)NULL, &tv);
- if (select_result > 0)
- {
- if (FD_ISSET(dns_sd_fd, &readfds))
- {
- if (MDNS_VERBOSE)
- syslog (LOG_DEBUG,
- "mdns: Reply received for %s",
- str
- );
- DNSServiceProcessResult(sdref);
- }
- else
- {
- syslog (LOG_WARNING,
- "mdns: Unexpected return from select on lookup of %s",
- str
- );
- }
- }
- else
- {
- // Terminate loop due to timer expiry
- if (MDNS_VERBOSE)
- syslog (LOG_DEBUG,
- "mdns: %s not found - timer expired",
- str
- );
- set_err_notfound (result);
- break;
- }
- }
-
- return result->status;
+ int dns_sd_fd = DNSServiceRefSockFD(sdref);
+ int nfds = dns_sd_fd + 1;
+ fd_set readfds;
+ struct timeval tv;
+ int select_result;
+
+ while (!result->done)
+ {
+ FD_ZERO(&readfds);
+ FD_SET(dns_sd_fd, &readfds);
+
+ tv = k_select_time;
+
+ select_result =
+ select (nfds, &readfds, (fd_set*)NULL, (fd_set*)NULL, &tv);
+ if (select_result > 0)
+ {
+ if (FD_ISSET(dns_sd_fd, &readfds))
+ {
+ if (MDNS_VERBOSE)
+ syslog (LOG_DEBUG,
+ "mdns: Reply received for %s",
+ str
+ );
+ DNSServiceProcessResult(sdref);
+ }
+ else
+ {
+ syslog (LOG_WARNING,
+ "mdns: Unexpected return from select on lookup of %s",
+ str
+ );
+ }
+ }
+ else
+ {
+ // Terminate loop due to timer expiry
+ if (MDNS_VERBOSE)
+ syslog (LOG_DEBUG,
+ "mdns: %s not found - timer expired",
+ str
+ );
+ set_err_notfound (result);
+ break;
+ }
+ }
+
+ return result->status;
}
/*
- Examine incoming data and add to relevant fields in result structure.
- This routine is called from DNSServiceProcessResult where appropriate.
+ Examine incoming data and add to relevant fields in result structure.
+ This routine is called from DNSServiceProcessResult where appropriate.
*/
void
mdns_lookup_callback
(
- DNSServiceRef sdref,
- DNSServiceFlags flags,
- uint32_t interface_index,
- DNSServiceErrorType error_code,
- const char *fullname,
- uint16_t rrtype,
- uint16_t rrclass,
- uint16_t rdlen,
- const void *rdata,
- uint32_t ttl,
- void *context
+ DNSServiceRef sdref,
+ DNSServiceFlags flags,
+ uint32_t interface_index,
+ DNSServiceErrorType error_code,
+ const char *fullname,
+ uint16_t rrtype,
+ uint16_t rrclass,
+ uint16_t rdlen,
+ const void *rdata,
+ uint32_t ttl,
+ void *context
)
{
- // A single record is received
-
- result_map_t * result = (result_map_t *) context;
-
- (void)sdref; // Unused
- (void)interface_index; // Unused
- (void)ttl; // Unused
-
- if (! (flags & kDNSServiceFlagsMoreComing) )
- {
- result->done = 1;
- }
-
- if (error_code == kDNSServiceErr_NoError)
- {
- ns_type_t expected_rr_type =
- af_to_rr (result->hostent->h_addrtype);
-
- // Idiot check class
- if (rrclass != C_IN)
- {
- syslog (LOG_WARNING,
- "mdns: Received bad RR class: expected %d (%s),"
- " got %d (%s), RR type %d (%s)",
- C_IN,
- ns_class_to_str (C_IN),
- rrclass,
- ns_class_to_str (rrclass),
- rrtype,
- ns_type_to_str (rrtype)
- );
- return;
- }
-
- // If a PTR
- if (rrtype == T_PTR)
- {
- if (callback_body_ptr (fullname, result, rdlen, rdata) < 0)
- return;
- }
- else if (rrtype == expected_rr_type)
- {
- if (!
- add_hostname_or_alias (
- result,
- fullname,
- strlen (fullname)
- )
- )
- {
- result->done = 1;
- return;
- // Abort on error
- }
-
- if (! add_address_to_buffer (result, rdata, rdlen) )
- {
- result->done = 1;
- return;
- // Abort on error
- }
- }
- else
- {
- syslog (LOG_WARNING,
- "mdns: Received bad RR type: expected %d (%s),"
- " got %d (%s)",
- expected_rr_type,
- ns_type_to_str (expected_rr_type),
- rrtype,
- ns_type_to_str (rrtype)
- );
- return;
- }
-
- if (result->status != NSS_STATUS_SUCCESS)
- set_err_success (result);
- }
- else
- {
- // For now, dump message to syslog and continue
- syslog (LOG_WARNING,
- "mdns: callback returned error %d",
- error_code
- );
- }
+ // A single record is received
+
+ result_map_t * result = (result_map_t *) context;
+
+ (void)sdref; // Unused
+ (void)interface_index; // Unused
+ (void)ttl; // Unused
+
+ if (!(flags & kDNSServiceFlagsMoreComing) )
+ {
+ result->done = 1;
+ }
+
+ if (error_code == kDNSServiceErr_NoError)
+ {
+ ns_type_t expected_rr_type =
+ af_to_rr (result->hostent->h_addrtype);
+
+ // Idiot check class
+ if (rrclass != C_IN)
+ {
+ syslog (LOG_WARNING,
+ "mdns: Received bad RR class: expected %d (%s),"
+ " got %d (%s), RR type %d (%s)",
+ C_IN,
+ ns_class_to_str (C_IN),
+ rrclass,
+ ns_class_to_str (rrclass),
+ rrtype,
+ ns_type_to_str (rrtype)
+ );
+ return;
+ }
+
+ // If a PTR
+ if (rrtype == kDNSServiceType_PTR)
+ {
+ if (callback_body_ptr (fullname, result, rdlen, rdata) < 0)
+ return;
+ }
+ else if (rrtype == expected_rr_type)
+ {
+ if (!
+ add_hostname_or_alias (
+ result,
+ fullname,
+ strlen (fullname)
+ )
+ )
+ {
+ result->done = 1;
+ return;
+ // Abort on error
+ }
+
+ if (!add_address_to_buffer (result, rdata, rdlen) )
+ {
+ result->done = 1;
+ return;
+ // Abort on error
+ }
+ }
+ else
+ {
+ syslog (LOG_WARNING,
+ "mdns: Received bad RR type: expected %d (%s),"
+ " got %d (%s)",
+ expected_rr_type,
+ ns_type_to_str (expected_rr_type),
+ rrtype,
+ ns_type_to_str (rrtype)
+ );
+ return;
+ }
+
+ if (result->status != NSS_STATUS_SUCCESS)
+ set_err_success (result);
+ }
+ else
+ {
+ // For now, dump message to syslog and continue
+ syslog (LOG_WARNING,
+ "mdns: callback returned error %d",
+ error_code
+ );
+ }
}
static int
callback_body_ptr (
- const char * fullname,
- result_map_t * result,
- int rdlen,
- const void * rdata
-)
+ const char * fullname,
+ result_map_t * result,
+ int rdlen,
+ const void * rdata
+ )
{
- char result_name [k_hostname_maxlen + 1];
- int rv;
-
- // Fullname should be .in-addr.arpa or equivalent, which we're
- // not interested in. Ignore it.
-
- rv = dns_rdata_to_name (rdata, rdlen, result_name, k_hostname_maxlen);
- if (rv < 0)
- {
- const char * errmsg;
-
- switch (rv)
- {
- case DNS_RDATA_TO_NAME_BAD_FORMAT:
- errmsg = "mdns: PTR '%s' result badly formatted ('%s...')";
- break;
-
- case DNS_RDATA_TO_NAME_TOO_LONG:
- errmsg = "mdns: PTR '%s' result too long ('%s...')";
- break;
-
- case DNS_RDATA_TO_NAME_PTR:
- errmsg = "mdns: PTR '%s' result contained pointer ('%s...')";
- break;
-
- default:
- errmsg = "mdns: PTR '%s' result conversion failed ('%s...')";
- }
-
- syslog (LOG_WARNING,
- errmsg,
- fullname,
- result_name
- );
-
- return -1;
- }
-
- if (MDNS_VERBOSE)
- {
- syslog (LOG_DEBUG,
- "mdns: PTR '%s' resolved to '%s'",
- fullname,
- result_name
- );
- }
-
- // Data should be a hostname
- if (!
- add_hostname_or_alias (
- result,
- result_name,
- rv
- )
- )
- {
- result->done = 1;
- return -1;
- }
-
- return 0;
+ char result_name [k_hostname_maxlen + 1];
+ int rv;
+
+ // Fullname should be .in-addr.arpa or equivalent, which we're
+ // not interested in. Ignore it.
+
+ rv = dns_rdata_to_name (rdata, rdlen, result_name, k_hostname_maxlen);
+ if (rv < 0)
+ {
+ const char * errmsg;
+
+ switch (rv)
+ {
+ case DNS_RDATA_TO_NAME_BAD_FORMAT:
+ errmsg = "mdns: PTR '%s' result badly formatted ('%s...')";
+ break;
+
+ case DNS_RDATA_TO_NAME_TOO_LONG:
+ errmsg = "mdns: PTR '%s' result too long ('%s...')";
+ break;
+
+ case DNS_RDATA_TO_NAME_PTR:
+ errmsg = "mdns: PTR '%s' result contained pointer ('%s...')";
+ break;
+
+ default:
+ errmsg = "mdns: PTR '%s' result conversion failed ('%s...')";
+ }
+
+ syslog (LOG_WARNING,
+ errmsg,
+ fullname,
+ result_name
+ );
+
+ return -1;
+ }
+
+ if (MDNS_VERBOSE)
+ {
+ syslog (LOG_DEBUG,
+ "mdns: PTR '%s' resolved to '%s'",
+ fullname,
+ result_name
+ );
+ }
+
+ // Data should be a hostname
+ if (!
+ add_hostname_or_alias (
+ result,
+ result_name,
+ rv
+ )
+ )
+ {
+ result->done = 1;
+ return -1;
+ }
+
+ return 0;
}
/*
- Add an address to the buffer.
-
- Parameter
- result
- Result structure to write to
- data
- Incoming address data buffer
- Must be 'int' aligned
- len
- Length of data buffer (in bytes)
- Must match data alignment
-
- Result
- Pointer to start of newly written data,
- or NULL on error.
- If address already exists in buffer, returns pointer to that instead.
+ Add an address to the buffer.
+
+ Parameter
+ result
+ Result structure to write to
+ data
+ Incoming address data buffer
+ Must be 'int' aligned
+ len
+ Length of data buffer (in bytes)
+ Must match data alignment
+
+ Result
+ Pointer to start of newly written data,
+ or NULL on error.
+ If address already exists in buffer, returns pointer to that instead.
*/
static void *
add_address_to_buffer (result_map_t * result, const void * data, int len)
{
- int new_addr;
- void * start;
- void * temp;
-
- if ((temp = contains_address (result, data, len)))
- {
- return temp;
- }
-
- if (result->addrs_count >= k_addrs_max)
- {
- // Not enough addr slots
- set_err_internal_resource_full (result);
- syslog (LOG_ERR,
- "mdns: Internal address buffer full; increase size"
- );
- return NULL;
- }
-
- // Idiot check
- if (len != result->hostent->h_length)
- {
- syslog (LOG_WARNING,
- "mdns: Unexpected rdata length for address. Expected %d, got %d",
- result->hostent->h_length,
- len
- );
- // XXX And continue for now.
- }
-
- new_addr = result->addr_idx + len;
-
- if (new_addr > result->alias_idx)
- {
- // Not enough room
- set_err_buf_too_small (result);
- if (MDNS_VERBOSE)
- syslog (LOG_DEBUG,
- "mdns: Ran out of buffer when adding address %d",
- result->addrs_count + 1
- );
- return NULL;
- }
-
- start = result->buffer + result->addr_idx;
- memcpy (start, data, len);
- result->addr_idx = new_addr;
- result->header->addrs [result->addrs_count] = start;
- result->addrs_count ++;
- result->header->addrs [result->addrs_count] = NULL;
-
- return start;
+ int new_addr;
+ void * start;
+ void * temp;
+
+ if ((temp = contains_address (result, data, len)))
+ {
+ return temp;
+ }
+
+ if (result->addrs_count >= k_addrs_max)
+ {
+ // Not enough addr slots
+ set_err_internal_resource_full (result);
+ syslog (LOG_ERR,
+ "mdns: Internal address buffer full; increase size"
+ );
+ return NULL;
+ }
+
+ // Idiot check
+ if (len != result->hostent->h_length)
+ {
+ syslog (LOG_WARNING,
+ "mdns: Unexpected rdata length for address. Expected %d, got %d",
+ result->hostent->h_length,
+ len
+ );
+ // XXX And continue for now.
+ }
+
+ new_addr = result->addr_idx + len;
+
+ if (new_addr > result->alias_idx)
+ {
+ // Not enough room
+ set_err_buf_too_small (result);
+ if (MDNS_VERBOSE)
+ syslog (LOG_DEBUG,
+ "mdns: Ran out of buffer when adding address %d",
+ result->addrs_count + 1
+ );
+ return NULL;
+ }
+
+ start = result->buffer + result->addr_idx;
+ memcpy (start, data, len);
+ result->addr_idx = new_addr;
+ result->header->addrs [result->addrs_count] = start;
+ result->addrs_count++;
+ result->header->addrs [result->addrs_count] = NULL;
+
+ return start;
}
static void *
contains_address (result_map_t * result, const void * data, int len)
{
- int i;
-
- // Idiot check
- if (len != result->hostent->h_length)
- {
- syslog (LOG_WARNING,
- "mdns: Unexpected rdata length for address. Expected %d, got %d",
- result->hostent->h_length,
- len
- );
- // XXX And continue for now.
- }
-
- for (i = 0; result->header->addrs [i]; i++)
- {
- if (memcmp (result->header->addrs [i], data, len) == 0)
- {
- return result->header->addrs [i];
- }
- }
-
- return NULL;
+ int i;
+
+ // Idiot check
+ if (len != result->hostent->h_length)
+ {
+ syslog (LOG_WARNING,
+ "mdns: Unexpected rdata length for address. Expected %d, got %d",
+ result->hostent->h_length,
+ len
+ );
+ // XXX And continue for now.
+ }
+
+ for (i = 0; result->header->addrs [i]; i++)
+ {
+ if (memcmp (result->header->addrs [i], data, len) == 0)
+ {
+ return result->header->addrs [i];
+ }
+ }
+
+ return NULL;
}
/*
- Add an alias to the buffer.
-
- Parameter
- result
- Result structure to write to
- data
- Incoming alias (null terminated)
- len
- Length of data buffer (in bytes), including trailing null
-
- Result
- Pointer to start of newly written data,
- or NULL on error
- If alias already exists in buffer, returns pointer to that instead.
+ Add an alias to the buffer.
+
+ Parameter
+ result
+ Result structure to write to
+ data
+ Incoming alias (null terminated)
+ len
+ Length of data buffer (in bytes), including trailing null
+
+ Result
+ Pointer to start of newly written data,
+ or NULL on error
+ If alias already exists in buffer, returns pointer to that instead.
*/
static char *
add_alias_to_buffer (result_map_t * result, const char * data, int len)
{
- int new_alias;
- char * start;
- char * temp;
-
- if ((temp = contains_alias (result, data)))
- {
- return temp;
- }
-
- if (result->aliases_count >= k_aliases_max)
- {
- // Not enough alias slots
- set_err_internal_resource_full (result);
- syslog (LOG_ERR,
- "mdns: Internal alias buffer full; increase size"
- );
- return NULL;
- }
-
- new_alias = result->alias_idx - len;
-
- if (new_alias < result->addr_idx)
- {
- // Not enough room
- set_err_buf_too_small (result);
- if (MDNS_VERBOSE)
- syslog (LOG_DEBUG,
- "mdns: Ran out of buffer when adding alias %d",
- result->aliases_count + 1
- );
- return NULL;
- }
-
- start = result->buffer + new_alias;
- memcpy (start, data, len);
- result->alias_idx = new_alias;
- result->header->aliases [result->aliases_count] = start;
- result->aliases_count ++;
- result->header->aliases [result->aliases_count] = NULL;
-
- return start;
+ int new_alias;
+ char * start;
+ char * temp;
+
+ if ((temp = contains_alias (result, data)))
+ {
+ return temp;
+ }
+
+ if (result->aliases_count >= k_aliases_max)
+ {
+ // Not enough alias slots
+ set_err_internal_resource_full (result);
+ syslog (LOG_ERR,
+ "mdns: Internal alias buffer full; increase size"
+ );
+ return NULL;
+ }
+
+ new_alias = result->alias_idx - len;
+
+ if (new_alias < result->addr_idx)
+ {
+ // Not enough room
+ set_err_buf_too_small (result);
+ if (MDNS_VERBOSE)
+ syslog (LOG_DEBUG,
+ "mdns: Ran out of buffer when adding alias %d",
+ result->aliases_count + 1
+ );
+ return NULL;
+ }
+
+ start = result->buffer + new_alias;
+ memcpy (start, data, len);
+ result->alias_idx = new_alias;
+ result->header->aliases [result->aliases_count] = start;
+ result->aliases_count++;
+ result->header->aliases [result->aliases_count] = NULL;
+
+ return start;
}
static char *
contains_alias (result_map_t * result, const char * alias)
{
- int i;
-
- for (i = 0; result->header->aliases [i]; i++)
- {
- if (strcmp (result->header->aliases [i], alias) == 0)
- {
- return result->header->aliases [i];
- }
- }
-
- return NULL;
+ int i;
+
+ for (i = 0; result->header->aliases [i]; i++)
+ {
+ if (strcmp (result->header->aliases [i], alias) == 0)
+ {
+ return result->header->aliases [i];
+ }
+ }
+
+ return NULL;
}
/*
- Add fully qualified hostname to result.
-
- Parameter
- result
- Result structure to write to
- fullname
- Fully qualified hostname
-
- Result
- Pointer to start of hostname buffer,
- or NULL on error (usually hostname too long)
+ Add fully qualified hostname to result.
+
+ Parameter
+ result
+ Result structure to write to
+ fullname
+ Fully qualified hostname
+
+ Result
+ Pointer to start of hostname buffer,
+ or NULL on error (usually hostname too long)
*/
static char *
add_hostname_len (result_map_t * result, const char * fullname, int len)
{
- if (len >= k_hostname_maxlen)
- {
- set_err_bad_hostname (result);
- syslog (LOG_WARNING,
- "mdns: Hostname too long '%.*s': len %d, max %d",
- len,
- fullname,
- len,
- k_hostname_maxlen
- );
- return NULL;
- }
-
- result->hostent->h_name =
- strcpy (result->header->hostname, fullname);
-
- return result->header->hostname;
+ if (len >= k_hostname_maxlen)
+ {
+ set_err_bad_hostname (result);
+ syslog (LOG_WARNING,
+ "mdns: Hostname too long '%.*s': len %d, max %d",
+ len,
+ fullname,
+ len,
+ k_hostname_maxlen
+ );
+ return NULL;
+ }
+
+ result->hostent->h_name =
+ strcpy (result->header->hostname, fullname);
+
+ return result->header->hostname;
}
/*
- Add fully qualified name as hostname or alias.
-
- If hostname is not fully qualified this is not an error, but the data
- returned may be not what the application wanted.
-
- Parameter
- result
- Result structure to write to
- data
- Incoming alias (null terminated)
- len
- Length of data buffer (in bytes), including trailing null
-
- Result
- Pointer to start of newly written data,
- or NULL on error
- If alias or hostname already exists, returns pointer to that instead.
+ Add fully qualified name as hostname or alias.
+
+ If hostname is not fully qualified this is not an error, but the data
+ returned may be not what the application wanted.
+
+ Parameter
+ result
+ Result structure to write to
+ data
+ Incoming alias (null terminated)
+ len
+ Length of data buffer (in bytes), including trailing null
+
+ Result
+ Pointer to start of newly written data,
+ or NULL on error
+ If alias or hostname already exists, returns pointer to that instead.
*/
static char *
add_hostname_or_alias (result_map_t * result, const char * data, int len)
{
- char * hostname = result->hostent->h_name;
-
- if (*hostname)
- {
- if (strcmp (hostname, data) == 0)
- {
- return hostname;
- }
- else
- {
- return add_alias_to_buffer (result, data, len);
- }
- }
- else
- {
- return add_hostname_len (result, data, len);
- }
+ char * hostname = result->hostent->h_name;
+
+ if (*hostname)
+ {
+ if (strcmp (hostname, data) == 0)
+ {
+ return hostname;
+ }
+ else
+ {
+ return add_alias_to_buffer (result, data, len);
+ }
+ }
+ else
+ {
+ return add_hostname_len (result, data, len);
+ }
}
static int
init_result (
- result_map_t * result,
- hostent * result_buf,
- char * buf,
- size_t buflen
-)
+ result_map_t * result,
+ hostent * result_buf,
+ char * buf,
+ size_t buflen
+ )
{
- if (buflen < sizeof (buf_header_t))
- {
- return ERANGE;
- }
-
- result->hostent = result_buf;
- result->header = (buf_header_t *) buf;
- result->header->hostname[0] = 0;
- result->aliases_count = 0;
- result->header->aliases[0] = NULL;
- result->addrs_count = 0;
- result->header->addrs[0] = NULL;
- result->buffer = buf + sizeof (buf_header_t);
- result->addr_idx = 0;
- result->alias_idx = buflen - sizeof (buf_header_t);
- result->done = 0;
- set_err_notfound (result);
-
- // Point hostent to the right buffers
- result->hostent->h_name = result->header->hostname;
- result->hostent->h_aliases = result->header->aliases;
- result->hostent->h_addr_list = result->header->addrs;
-
- return 0;
+ if (buflen < sizeof (buf_header_t))
+ {
+ return ERANGE;
+ }
+
+ result->hostent = result_buf;
+ result->header = (buf_header_t *) buf;
+ result->header->hostname[0] = 0;
+ result->aliases_count = 0;
+ result->header->aliases[0] = NULL;
+ result->addrs_count = 0;
+ result->header->addrs[0] = NULL;
+ result->buffer = buf + sizeof (buf_header_t);
+ result->addr_idx = 0;
+ result->alias_idx = buflen - sizeof (buf_header_t);
+ result->done = 0;
+ set_err_notfound (result);
+
+ // Point hostent to the right buffers
+ result->hostent->h_name = result->header->hostname;
+ result->hostent->h_aliases = result->header->aliases;
+ result->hostent->h_addr_list = result->header->addrs;
+
+ return 0;
}
/*
- Set the status in the result.
-
- Parameters
- result
- Result structure to update
- status
- New nss_status value
- err
- New errno value
- herr
- New h_errno value
-
- Returns
- New status value
+ Set the status in the result.
+
+ Parameters
+ result
+ Result structure to update
+ status
+ New nss_status value
+ err
+ New errno value
+ herr
+ New h_errno value
+
+ Returns
+ New status value
*/
static nss_status
set_err (result_map_t * result, nss_status status, int err, int herr)
{
- result->status = status;
- result->r_errno = err;
- result->r_h_errno = herr;
-
- return status;
+ result->status = status;
+ result->r_errno = err;
+ result->r_h_errno = herr;
+
+ return status;
}
static nss_status
set_err_notfound (result_map_t * result)
{
- return set_err (result, NSS_STATUS_NOTFOUND, ENOENT, HOST_NOT_FOUND);
+ return set_err (result, NSS_STATUS_NOTFOUND, ENOENT, HOST_NOT_FOUND);
}
static nss_status
set_err_bad_hostname (result_map_t * result)
{
- return set_err (result, NSS_STATUS_TRYAGAIN, ENOENT, NO_RECOVERY);
+ return set_err (result, NSS_STATUS_TRYAGAIN, ENOENT, NO_RECOVERY);
}
static nss_status
set_err_buf_too_small (result_map_t * result)
{
- return set_err (result, NSS_STATUS_TRYAGAIN, ERANGE, NETDB_INTERNAL);
+ return set_err (result, NSS_STATUS_TRYAGAIN, ERANGE, NETDB_INTERNAL);
}
static nss_status
set_err_internal_resource_full (result_map_t * result)
{
- return set_err (result, NSS_STATUS_RETURN, ERANGE, NO_RECOVERY);
+ return set_err (result, NSS_STATUS_RETURN, ERANGE, NO_RECOVERY);
}
static nss_status
set_err_system (result_map_t * result)
{
- return set_err (result, NSS_STATUS_UNAVAIL, errno, NETDB_INTERNAL);
+ return set_err (result, NSS_STATUS_UNAVAIL, errno, NETDB_INTERNAL);
}
static nss_status
set_err_mdns_failed (result_map_t * result)
{
- return set_err (result, NSS_STATUS_TRYAGAIN, EAGAIN, TRY_AGAIN);
+ return set_err (result, NSS_STATUS_TRYAGAIN, EAGAIN, TRY_AGAIN);
}
static nss_status
set_err_success (result_map_t * result)
{
- result->status = NSS_STATUS_SUCCESS;
- return result->status;
+ result->status = NSS_STATUS_SUCCESS;
+ return result->status;
}
/*
- Test whether name is applicable for mdns to process, and if so copy into
- lookup_name buffer (if non-NULL).
-
- Returns
- Pointer to name to lookup up, if applicable, or NULL otherwise.
+ Test whether name is applicable for mdns to process, and if so copy into
+ lookup_name buffer (if non-NULL).
+
+ Returns
+ Pointer to name to lookup up, if applicable, or NULL otherwise.
*/
static const char *
is_applicable_name (
- result_map_t * result,
- const char * name,
- char * lookup_name
-)
+ result_map_t * result,
+ const char * name,
+ char * lookup_name
+ )
{
- int match = config_is_mdns_suffix (name);
- if (match > 0)
- {
- if (lookup_name)
- {
- strncpy (lookup_name, name, k_hostname_maxlen + 1);
- return lookup_name;
- }
- else
- {
- return name;
- }
- }
- else
- {
- if (match < 0)
- {
- set_err_system (result);
- }
- return NULL;
- }
+ int match = config_is_mdns_suffix (name);
+ if (match > 0)
+ {
+ if (lookup_name)
+ {
+ strncpy (lookup_name, name, k_hostname_maxlen + 1);
+ return lookup_name;
+ }
+ else
+ {
+ return name;
+ }
+ }
+ else
+ {
+ if (match < 0)
+ {
+ set_err_system (result);
+ }
+ return NULL;
+ }
}
/*
- Test whether address is applicable for mdns to process, and if so copy into
- addr_str buffer as an address suitable for ptr lookup.
-
- Returns
- Pointer to name to lookup up, if applicable, or NULL otherwise.
+ Test whether address is applicable for mdns to process, and if so copy into
+ addr_str buffer as an address suitable for ptr lookup.
+
+ Returns
+ Pointer to name to lookup up, if applicable, or NULL otherwise.
*/
static const char *
is_applicable_addr (
- result_map_t * result,
- const void * addr,
- int af,
- char * addr_str
-)
+ result_map_t * result,
+ const void * addr,
+ int af,
+ char * addr_str
+ )
{
- int match;
-
- if (! format_reverse_addr (af, addr, -1, addr_str))
- {
- if (MDNS_VERBOSE)
- syslog (LOG_DEBUG,
- "mdns: Failed to create reverse address"
- );
- return NULL;
- }
-
- if (MDNS_VERBOSE)
- syslog (LOG_DEBUG,
- "mdns: Reverse address: %s",
- addr_str
- );
-
- match = config_is_mdns_suffix (addr_str);
- if (match > 0)
- {
- return addr_str;
- }
- else
- {
- if (match < 0)
- {
- set_err_system (result);
- }
- return NULL;
- }
+ int match;
+
+ if (!format_reverse_addr (af, addr, -1, addr_str))
+ {
+ if (MDNS_VERBOSE)
+ syslog (LOG_DEBUG,
+ "mdns: Failed to create reverse address"
+ );
+ return NULL;
+ }
+
+ if (MDNS_VERBOSE)
+ syslog (LOG_DEBUG,
+ "mdns: Reverse address: %s",
+ addr_str
+ );
+
+ match = config_is_mdns_suffix (addr_str);
+ if (match > 0)
+ {
+ return addr_str;
+ }
+ else
+ {
+ if (match < 0)
+ {
+ set_err_system (result);
+ }
+ return NULL;
+ }
}
//----------
const char * k_keyword_domain = "domain";
const char * k_default_domains [] =
- {
- "local",
- "254.169.in-addr.arpa",
- "0.8.e.f.ip6.int",
- "0.8.e.f.ip6.arpa",
- NULL
- // Always null terminated
- };
+{
+ "local",
+ "254.169.in-addr.arpa",
+ "8.e.f.ip6.int",
+ "8.e.f.ip6.arpa",
+ "9.e.f.ip6.int",
+ "9.e.f.ip6.arpa",
+ "a.e.f.ip6.int",
+ "a.e.f.ip6.arpa",
+ "b.e.f.ip6.int",
+ "b.e.f.ip6.arpa",
+ NULL
+ // Always null terminated
+};
// Linked list of domains
typedef struct domain_entry
{
- char * domain;
- struct domain_entry * next;
+ char * domain;
+ struct domain_entry * next;
} domain_entry_t;
// Config
typedef struct
{
- domain_entry_t * domains;
+ domain_entry_t * domains;
} config_t;
const config_t k_empty_config =
- {
- NULL
- };
+{
+ NULL
+};
// Context - tracks position in config file, used for error reporting
typedef struct
{
- const char * filename;
- int linenum;
+ const char * filename;
+ int linenum;
} config_file_context_t;
static errcode_t
process_config_line (
- config_t * conf,
- char * line,
- config_file_context_t * context
-);
+ config_t * conf,
+ char * line,
+ config_file_context_t * context
+ );
static char *
get_next_word (char * input, char **next);
// Global variables
static config_t * g_config = NULL;
- // Configuration info
+// Configuration info
pthread_mutex_t g_config_mutex =
#ifdef PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP
- PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP;
+ PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP;
#else
- PTHREAD_MUTEX_INITIALIZER;
+ PTHREAD_MUTEX_INITIALIZER;
#endif
/*
- Initialise the configuration from the config file.
-
- Returns
- 0 success
- non-zero error code on failure
+ Initialise the configuration from the config file.
+
+ Returns
+ 0 success
+ non-zero error code on failure
*/
errcode_t
init_config ()
{
- if (g_config)
- {
- /*
- Safe to test outside mutex.
- If non-zero, initialisation is complete and g_config can be
- safely used read-only. If zero, then we do proper mutex
- testing before initialisation.
- */
- return 0;
- }
- else
- {
- int errcode = -1;
- int presult;
- config_t * temp_config;
-
- // Acquire mutex
- presult = pthread_mutex_lock (&g_config_mutex);
- if (presult)
- {
- syslog (LOG_ERR,
- "mdns: Fatal mutex lock error in nss_mdns:init_config, %s:%d: %d: %s",
- __FILE__, __LINE__, presult, strerror (presult)
- );
- return presult;
- }
-
- // Test again now we have mutex, in case initialisation occurred while
- // we were waiting
- if (! g_config)
- {
- temp_config = (config_t *) malloc (sizeof (config_t));
- if (temp_config)
- {
- // NOTE: This code will leak memory if initialisation fails
- // repeatedly. This should only happen in the case of a memory
- // error, so I'm not sure if it's a meaningful problem. - AW
- *temp_config = k_empty_config;
- errcode = load_config (temp_config);
-
- if (! errcode)
- {
- g_config = temp_config;
- }
- }
- else
- {
- syslog (LOG_ERR,
- "mdns: Can't allocate memory in nss_mdns:init_config, %s:%d",
- __FILE__, __LINE__
- );
- errcode = errno;
- }
- }
-
- presult = pthread_mutex_unlock (&g_config_mutex);
- if (presult)
- {
- syslog (LOG_ERR,
- "mdns: Fatal mutex unlock error in nss_mdns:init_config, %s:%d: %d: %s",
- __FILE__, __LINE__, presult, strerror (presult)
- );
- errcode = presult;
- }
-
- return errcode;
- }
+ if (g_config)
+ {
+ /*
+ Safe to test outside mutex.
+ If non-zero, initialisation is complete and g_config can be
+ safely used read-only. If zero, then we do proper mutex
+ testing before initialisation.
+ */
+ return 0;
+ }
+ else
+ {
+ int errcode = -1;
+ int presult;
+ config_t * temp_config;
+
+ // Acquire mutex
+ presult = pthread_mutex_lock (&g_config_mutex);
+ if (presult)
+ {
+ syslog (LOG_ERR,
+ "mdns: Fatal mutex lock error in nss_mdns:init_config, %s:%d: %d: %s",
+ __FILE__, __LINE__, presult, strerror (presult)
+ );
+ return presult;
+ }
+
+ // Test again now we have mutex, in case initialisation occurred while
+ // we were waiting
+ if (!g_config)
+ {
+ temp_config = (config_t *) malloc (sizeof (config_t));
+ if (temp_config)
+ {
+ // Note: This code will leak memory if initialisation fails
+ // repeatedly. This should only happen in the case of a memory
+ // error, so I'm not sure if it's a meaningful problem. - AW
+ *temp_config = k_empty_config;
+ errcode = load_config (temp_config);
+
+ if (!errcode)
+ {
+ g_config = temp_config;
+ }
+ }
+ else
+ {
+ syslog (LOG_ERR,
+ "mdns: Can't allocate memory in nss_mdns:init_config, %s:%d",
+ __FILE__, __LINE__
+ );
+ errcode = errno;
+ }
+ }
+
+ presult = pthread_mutex_unlock (&g_config_mutex);
+ if (presult)
+ {
+ syslog (LOG_ERR,
+ "mdns: Fatal mutex unlock error in nss_mdns:init_config, %s:%d: %d: %s",
+ __FILE__, __LINE__, presult, strerror (presult)
+ );
+ errcode = presult;
+ }
+
+ return errcode;
+ }
}
int
config_is_mdns_suffix (const char * name)
{
- int errcode = init_config ();
- if (! errcode)
- {
- return contains_domain_suffix (g_config, name);
- }
- else
- {
- errno = errcode;
- return -1;
- }
+ int errcode = init_config ();
+ if (!errcode)
+ {
+ return contains_domain_suffix (g_config, name);
+ }
+ else
+ {
+ errno = errcode;
+ return -1;
+ }
}
static errcode_t
load_config (config_t * conf)
{
- FILE * cf;
- char line [CONF_LINE_SIZE];
- config_file_context_t context;
-
- context.filename = k_conf_file;
- context.linenum = 0;
-
-
- cf = fopen (context.filename, "r");
- if (! cf)
- {
- syslog (LOG_INFO,
- "mdns: Couldn't open nss_mdns configuration file %s, using default.",
- context.filename
- );
- return default_config (conf);
- }
-
- while (fgets (line, CONF_LINE_SIZE, cf))
- {
- int errcode;
- context.linenum++;
- errcode = process_config_line (conf, line, &context);
- if (errcode)
- {
- // Critical error, give up
- return errcode;
- }
- }
-
- return 0;
+ FILE * cf;
+ char line [CONF_LINE_SIZE];
+ config_file_context_t context;
+
+ context.filename = k_conf_file;
+ context.linenum = 0;
+
+
+ cf = fopen (context.filename, "r");
+ if (!cf)
+ {
+ syslog (LOG_INFO,
+ "mdns: Couldn't open nss_mdns configuration file %s, using default.",
+ context.filename
+ );
+ return default_config (conf);
+ }
+
+ while (fgets (line, CONF_LINE_SIZE, cf))
+ {
+ int errcode;
+ context.linenum++;
+ errcode = process_config_line (conf, line, &context);
+ if (errcode)
+ {
+ // Critical error, give up
+ fclose(cf);
+ return errcode;
+ }
+ }
+
+ fclose (cf);
+
+ return 0;
}
/*
- Parse a line of the configuration file.
- For each keyword recognised, perform appropriate handling.
- If the keyword is not recognised, print a message to syslog
- and continue.
-
- Returns
- 0 success, or recoverable config file error
- non-zero serious system error, processing aborted
+ Parse a line of the configuration file.
+ For each keyword recognised, perform appropriate handling.
+ If the keyword is not recognised, print a message to syslog
+ and continue.
+
+ Returns
+ 0 success, or recoverable config file error
+ non-zero serious system error, processing aborted
*/
static errcode_t
process_config_line (
- config_t * conf,
- char * line,
- config_file_context_t * context
-)
+ config_t * conf,
+ char * line,
+ config_file_context_t * context
+ )
{
- char * curr = line;
- char * word;
-
- word = get_next_word (curr, &curr);
- if (! word || word [0] == k_comment_char)
- {
- // Nothing interesting on this line
- return 0;
- }
-
- if (strcmp (word, k_keyword_domain) == 0)
- {
- word = get_next_word (curr, &curr);
- if (word)
- {
- int errcode = add_domain (conf, word);
- if (errcode)
- {
- // something badly wrong, bail
- return errcode;
- }
-
- if (get_next_word (curr, NULL))
- {
- syslog (LOG_WARNING,
- "%s, line %d: ignored extra text found after domain",
- context->filename,
- context->linenum
- );
- }
- }
- else
- {
- syslog (LOG_WARNING,
- "%s, line %d: no domain specified",
- context->filename,
- context->linenum
- );
- }
- }
- else
- {
- syslog (LOG_WARNING,
- "%s, line %d: unknown keyword %s - skipping",
- context->filename,
- context->linenum,
- word
- );
- }
-
- return 0;
+ char * curr = line;
+ char * word;
+
+ word = get_next_word (curr, &curr);
+ if (!word || word [0] == k_comment_char)
+ {
+ // Nothing interesting on this line
+ return 0;
+ }
+
+ if (strcmp (word, k_keyword_domain) == 0)
+ {
+ word = get_next_word (curr, &curr);
+ if (word)
+ {
+ int errcode = add_domain (conf, word);
+ if (errcode)
+ {
+ // something badly wrong, bail
+ return errcode;
+ }
+
+ if (get_next_word (curr, NULL))
+ {
+ syslog (LOG_WARNING,
+ "%s, line %d: ignored extra text found after domain",
+ context->filename,
+ context->linenum
+ );
+ }
+ }
+ else
+ {
+ syslog (LOG_WARNING,
+ "%s, line %d: no domain specified",
+ context->filename,
+ context->linenum
+ );
+ }
+ }
+ else
+ {
+ syslog (LOG_WARNING,
+ "%s, line %d: unknown keyword %s - skipping",
+ context->filename,
+ context->linenum,
+ word
+ );
+ }
+
+ return 0;
}
/*
- Get next word (whitespace separated) from input string.
- A null character is written into the first whitespace character following
- the word.
-
- Parameters
- input
- Input string. This string is modified by get_next_word.
- next
- If non-NULL and the result is non-NULL, a pointer to the
- character following the end of the word (after the null)
- is written to 'next'.
- If no word is found, the original value is unchanged.
- If the word extended to the end of the string, 'next' points
- to the trailling NULL.
- It is safe to pass 'str' as 'input' and '&str' as 'next'.
- Returns
- Pointer to the first non-whitespace character (and thus word) found.
- if no word is found, returns NULL.
+ Get next word (whitespace separated) from input string.
+ A null character is written into the first whitespace character following
+ the word.
+
+ Parameters
+ input
+ Input string. This string is modified by get_next_word.
+ next
+ If non-NULL and the result is non-NULL, a pointer to the
+ character following the end of the word (after the null)
+ is written to 'next'.
+ If no word is found, the original value is unchanged.
+ If the word extended to the end of the string, 'next' points
+ to the trailling NULL.
+ It is safe to pass 'str' as 'input' and '&str' as 'next'.
+ Returns
+ Pointer to the first non-whitespace character (and thus word) found.
+ if no word is found, returns NULL.
*/
static char *
get_next_word (char * input, char **next)
{
- char * curr = input;
- char * result;
-
- while (isspace (*curr))
- {
- curr ++;
- }
-
- if (*curr == 0)
- {
- return NULL;
- }
-
- result = curr;
- while (*curr && ! isspace (*curr))
- {
- curr++;
- }
- if (*curr)
- {
- *curr = 0;
- if (next)
- {
- *next = curr+1;
- }
- }
- else
- {
- if (next)
- {
- *next = curr;
- }
- }
-
- return result;
+ char * curr = input;
+ char * result;
+
+ while (isspace (*curr))
+ {
+ curr++;
+ }
+
+ if (*curr == 0)
+ {
+ return NULL;
+ }
+
+ result = curr;
+ while (*curr && !isspace (*curr))
+ {
+ curr++;
+ }
+ if (*curr)
+ {
+ *curr = 0;
+ if (next)
+ {
+ *next = curr+1;
+ }
+ }
+ else
+ {
+ if (next)
+ {
+ *next = curr;
+ }
+ }
+
+ return result;
}
static errcode_t
default_config (config_t * conf)
{
- int i;
- for (i = 0; k_default_domains [i]; i++)
- {
- int errcode =
- add_domain (conf, k_default_domains [i]);
- if (errcode)
- {
- // Something has gone (badly) wrong - let's bail
- return errcode;
- }
- }
-
- return 0;
+ int i;
+ for (i = 0; k_default_domains [i]; i++)
+ {
+ int errcode =
+ add_domain (conf, k_default_domains [i]);
+ if (errcode)
+ {
+ // Something has gone (badly) wrong - let's bail
+ return errcode;
+ }
+ }
+
+ return 0;
}
static errcode_t
add_domain (config_t * conf, const char * domain)
{
- if (! contains_domain (conf, domain))
- {
- domain_entry_t * d =
- (domain_entry_t *) malloc (sizeof (domain_entry_t));
- if (! d)
- {
- syslog (LOG_ERR,
- "mdns: Can't allocate memory in nss_mdns:init_config, %s:%d",
- __FILE__, __LINE__
- );
- return ENOMEM;
- }
-
- d->domain = strdup (domain);
- if (! d->domain)
- {
- syslog (LOG_ERR,
- "mdns: Can't allocate memory in nss_mdns:init_config, %s:%d",
- __FILE__, __LINE__
- );
- free (d);
- return ENOMEM;
- }
- d->next = conf->domains;
- conf->domains = d;
- }
-
- return 0;
+ if (!contains_domain (conf, domain))
+ {
+ domain_entry_t * d =
+ (domain_entry_t *) malloc (sizeof (domain_entry_t));
+ if (!d)
+ {
+ syslog (LOG_ERR,
+ "mdns: Can't allocate memory in nss_mdns:init_config, %s:%d",
+ __FILE__, __LINE__
+ );
+ return ENOMEM;
+ }
+
+ d->domain = strdup (domain);
+ if (!d->domain)
+ {
+ syslog (LOG_ERR,
+ "mdns: Can't allocate memory in nss_mdns:init_config, %s:%d",
+ __FILE__, __LINE__
+ );
+ free (d);
+ return ENOMEM;
+ }
+ d->next = conf->domains;
+ conf->domains = d;
+ }
+
+ return 0;
}
static int
contains_domain (const config_t * conf, const char * domain)
{
- const domain_entry_t * curr = conf->domains;
-
- while (curr != NULL)
- {
- if (strcasecmp (curr->domain, domain) == 0)
- {
- return 1;
- }
-
- curr = curr->next;
- }
-
- return 0;
+ const domain_entry_t * curr = conf->domains;
+
+ while (curr != NULL)
+ {
+ if (strcasecmp (curr->domain, domain) == 0)
+ {
+ return 1;
+ }
+
+ curr = curr->next;
+ }
+
+ return 0;
}
static int
contains_domain_suffix (const config_t * conf, const char * addr)
{
- const domain_entry_t * curr = conf->domains;
-
- while (curr != NULL)
- {
- if (cmp_dns_suffix (addr, curr->domain) > 0)
- {
- return 1;
- }
-
- curr = curr->next;
- }
-
- return 0;
+ const domain_entry_t * curr = conf->domains;
+
+ while (curr != NULL)
+ {
+ if (cmp_dns_suffix (addr, curr->domain) > 0)
+ {
+ return 1;
+ }
+
+ curr = curr->next;
+ }
+
+ return 0;
}
//----------
static const char * k_local_suffix = "local";
static const char k_dns_separator = '.';
-static const int k_label_maxlen = DNS_LABEL_MAXLEN;
- // Label entries longer than this are actually pointers.
+static const unsigned int k_label_maxlen = DNS_LABEL_MAXLEN;
+// Label entries longer than this are actually pointers.
typedef struct
{
- int value;
- const char * name;
- const char * comment;
+ int value;
+ const char * name;
+ const char * comment;
} table_entry_t;
static const table_entry_t k_table_af [] =
- {
- { AF_UNSPEC, NULL, NULL },
- { AF_LOCAL, "LOCAL", NULL },
- { AF_UNIX, "UNIX", NULL },
- { AF_INET, "INET", NULL },
- { AF_INET6, "INET6", NULL }
- };
+{
+ { AF_UNSPEC, NULL, NULL },
+ { AF_LOCAL, "LOCAL", NULL },
+ { AF_UNIX, "UNIX", NULL },
+ { AF_INET, "INET", NULL },
+ { AF_INET6, "INET6", NULL }
+};
static const int k_table_af_size =
- sizeof (k_table_af) / sizeof (* k_table_af);
+ sizeof (k_table_af) / sizeof (*k_table_af);
static const char * k_table_ns_class [] =
- {
- NULL,
- "IN"
- };
+{
+ NULL,
+ "IN"
+};
static const int k_table_ns_class_size =
- sizeof (k_table_ns_class) / sizeof (* k_table_ns_class);
+ sizeof (k_table_ns_class) / sizeof (*k_table_ns_class);
static const char * k_table_ns_type [] =
- {
- NULL,
- "A",
- "NS",
- "MD",
- "MF",
- "CNAME",
- "SOA",
- "MB",
- "MG",
- "MR",
- "NULL",
- "WKS",
- "PTR",
- "HINFO",
- "MINFO",
- "MX",
- "TXT",
- "RP",
- "AFSDB",
- "X25",
- "ISDN",
- "RT",
- "NSAP",
- NULL,
- "SIG",
- "KEY",
- "PX",
- "GPOS",
- "AAAA",
- "LOC",
- "NXT",
- "EID",
- "NIMLOC",
- "SRV",
- "ATMA",
- "NAPTR",
- "KX",
- "CERT",
- "A6",
- "DNAME",
- "SINK",
- "OPT"
- };
+{
+ NULL,
+ "A",
+ "NS",
+ "MD",
+ "MF",
+ "CNAME",
+ "SOA",
+ "MB",
+ "MG",
+ "MR",
+ "NULL",
+ "WKS",
+ "PTR",
+ "HINFO",
+ "MINFO",
+ "MX",
+ "TXT",
+ "RP",
+ "AFSDB",
+ "X25",
+ "ISDN",
+ "RT",
+ "NSAP",
+ NULL,
+ "SIG",
+ "KEY",
+ "PX",
+ "GPOS",
+ "AAAA",
+ "LOC",
+ "NXT",
+ "EID",
+ "NIMLOC",
+ "SRV",
+ "ATMA",
+ "NAPTR",
+ "KX",
+ "CERT",
+ "A6",
+ "DNAME",
+ "SINK",
+ "OPT"
+};
static const int k_table_ns_type_size =
- sizeof (k_table_ns_type) / sizeof (* k_table_ns_type);
+ sizeof (k_table_ns_type) / sizeof (*k_table_ns_type);
//----------
int
count_dots (const char * name)
{
- int count = 0;
- int i;
- for (i = 0; name[i]; i++)
- {
- if (name [i] == k_dns_separator)
- count++;
- }
-
- return count;
+ int count = 0;
+ int i;
+ for (i = 0; name[i]; i++)
+ {
+ if (name [i] == k_dns_separator)
+ count++;
+ }
+
+ return count;
}
int
islocal (const char * name)
{
- return cmp_dns_suffix (name, k_local_suffix) > 0;
+ return cmp_dns_suffix (name, k_local_suffix) > 0;
}
int
rr_to_af (ns_type_t rrtype)
{
- switch (rrtype)
- {
- case T_A:
- return AF_INET;
-
- case T_AAAA:
- return AF_INET6;
-
- default:
- return AF_UNSPEC;
- }
+ switch (rrtype)
+ {
+ case kDNSServiceType_A:
+ return AF_INET;
+
+ case kDNSServiceType_AAAA:
+ return AF_INET6;
+
+ default:
+ return AF_UNSPEC;
+ }
}
ns_type_t
af_to_rr (int af)
{
- switch (af)
- {
- case AF_INET:
- return T_A;
-
- case AF_INET6:
- return T_AAAA;
-
- default:
- //return ns_t_invalid;
- return 0;
- }
+ switch (af)
+ {
+ case AF_INET:
+ return kDNSServiceType_A;
+
+ case AF_INET6:
+ return kDNSServiceType_AAAA;
+
+ default:
+ //return ns_t_invalid;
+ return 0;
+ }
}
int
str_to_af (const char * str)
{
- int result =
- table_index_name (k_table_af, k_table_af_size, str);
- if (result < 0)
- result = 0;
+ int result =
+ table_index_name (k_table_af, k_table_af_size, str);
+ if (result < 0)
+ result = 0;
- return k_table_af [result].value;
+ return k_table_af [result].value;
}
ns_class_t
str_to_ns_class (const char * str)
{
- return (ns_class_t)
- simple_table_index (k_table_ns_class, k_table_ns_class_size, str);
+ return (ns_class_t)
+ simple_table_index (k_table_ns_class, k_table_ns_class_size, str);
}
ns_type_t
str_to_ns_type (const char * str)
{
- return (ns_type_t)
- simple_table_index (k_table_ns_type, k_table_ns_type_size, str);
+ return (ns_type_t)
+ simple_table_index (k_table_ns_type, k_table_ns_type_size, str);
}
const char *
af_to_str (int in)
{
- int result =
- table_index_value (k_table_af, k_table_af_size, in);
- if (result < 0)
- result = 0;
+ int result =
+ table_index_value (k_table_af, k_table_af_size, in);
+ if (result < 0)
+ result = 0;
- return k_table_af [result].name;
+ return k_table_af [result].name;
}
const char *
ns_class_to_str (ns_class_t in)
{
- if (in < k_table_ns_class_size)
- return k_table_ns_class [in];
- else
- return NULL;
+ if (in < k_table_ns_class_size)
+ return k_table_ns_class [in];
+ else
+ return NULL;
}
const char *
ns_type_to_str (ns_type_t in)
{
- if (in < k_table_ns_type_size)
- return k_table_ns_type [in];
- else
- return NULL;
+ if (in < k_table_ns_type_size)
+ return k_table_ns_type [in];
+ else
+ return NULL;
}
char *
format_reverse_addr_in (
- const struct in_addr * addr,
- int prefixlen,
- char * buf
-)
+ const struct in_addr * addr,
+ int prefixlen,
+ char * buf
+ )
{
- char * curr = buf;
- int i;
-
- const uint8_t * in_addr_a = (uint8_t *) addr;
-
- if (prefixlen > 32)
- return NULL;
- if (prefixlen < 0)
- prefixlen = 32;
-
- i = (prefixlen + 7) / 8;
- // divide prefixlen into bytes, rounding up
-
- while (i > 0)
- {
- i--;
- curr += sprintf (curr, "%d.", in_addr_a [i]);
- }
- sprintf (curr, "in-addr.arpa");
-
- return buf;
+ char * curr = buf;
+ int i;
+
+ const uint8_t * in_addr_a = (uint8_t *) addr;
+
+ if (prefixlen > 32)
+ return NULL;
+ if (prefixlen < 0)
+ prefixlen = 32;
+
+ i = (prefixlen + 7) / 8;
+ // divide prefixlen into bytes, rounding up
+
+ while (i > 0)
+ {
+ i--;
+ curr += sprintf (curr, "%d.", in_addr_a [i]);
+ }
+ sprintf (curr, "in-addr.arpa");
+
+ return buf;
}
char *
format_reverse_addr_in6 (
- const struct in6_addr * addr,
- int prefixlen,
- char * buf
-)
+ const struct in6_addr * addr,
+ int prefixlen,
+ char * buf
+ )
{
- char * curr = buf;
- int i;
-
- const uint8_t * in_addr_a = (uint8_t *) addr;
-
- if (prefixlen > 128)
- return NULL;
- if (prefixlen < 0)
- prefixlen = 128;
-
- i = (prefixlen + 3) / 4;
- // divide prefixlen into nibbles, rounding up
-
- // Special handling for first
- if (i / 2)
- {
- curr += sprintf (curr, "%d.", (in_addr_a [i] >> 4) & 0x0F);
- }
- i >>= 1;
- // Convert i to bytes (divide by 2)
-
- while (i > 0)
- {
- uint8_t val;
-
- i--;
- val = in_addr_a [i];
- curr += sprintf (curr, "%x.%x.", val & 0x0F, (val >> 4) & 0x0F);
- }
- sprintf (curr, "ip6.arpa");
-
- return buf;
+ char * curr = buf;
+ int i;
+
+ const uint8_t * in_addr_a = (uint8_t *) addr;
+
+ if (prefixlen > 128)
+ return NULL;
+ if (prefixlen < 0)
+ prefixlen = 128;
+
+ i = (prefixlen + 3) / 4;
+ // divide prefixlen into nibbles, rounding up
+
+ // Special handling for first
+ if (i % 2)
+ {
+ curr += sprintf (curr, "%d.", (in_addr_a [i/2] >> 4) & 0x0F);
+ }
+ i >>= 1;
+ // Convert i to bytes (divide by 2)
+
+ while (i > 0)
+ {
+ uint8_t val;
+
+ i--;
+ val = in_addr_a [i];
+ curr += sprintf (curr, "%x.%x.", val & 0x0F, (val >> 4) & 0x0F);
+ }
+ sprintf (curr, "ip6.arpa");
+
+ return buf;
}
char *
format_reverse_addr (
- int af,
- const void * addr,
- int prefixlen,
- char * buf
-)
+ int af,
+ const void * addr,
+ int prefixlen,
+ char * buf
+ )
{
- switch (af)
- {
- case AF_INET:
- return
- format_reverse_addr_in (
- (struct in_addr *) addr, prefixlen, buf
- );
- break;
-
- case AF_INET6:
- return
- format_reverse_addr_in6 (
- (struct in6_addr *) addr, prefixlen, buf
- );
- break;
-
- default:
- return NULL;
- }
+ switch (af)
+ {
+ case AF_INET:
+ return
+ format_reverse_addr_in (
+ (struct in_addr *) addr, prefixlen, buf
+ );
+ break;
+
+ case AF_INET6:
+ return
+ format_reverse_addr_in6 (
+ (struct in6_addr *) addr, prefixlen, buf
+ );
+ break;
+
+ default:
+ return NULL;
+ }
}
int
cmp_dns_suffix (const char * name, const char * domain)
{
- const char * nametail;
- const char * domaintail;
-
- // Idiot checks
- if (*name == 0 || *name == k_dns_separator)
- {
- // Name can't be empty or start with separator
- return CMP_DNS_SUFFIX_BAD_NAME;
- }
-
- if (*domain == 0)
- {
- return CMP_DNS_SUFFIX_SUCCESS;
- // trivially true
- }
-
- if (*domain == k_dns_separator)
- {
- // drop leading separator from domain
- domain++;
- if (*domain == k_dns_separator)
- {
- return CMP_DNS_SUFFIX_BAD_DOMAIN;
- }
- }
-
- // Find ends of strings
- for (nametail = name; *nametail; nametail++)
- ;
- for (domaintail = domain; *domaintail; domaintail++)
- ;
-
- // Shuffle back to last real character, and drop any trailing '.'
- // while we're at it.
- nametail --;
- if (*nametail == k_dns_separator)
- {
- nametail --;
- if (*nametail == k_dns_separator)
- {
- return CMP_DNS_SUFFIX_BAD_NAME;
- }
- }
- domaintail --;
- if (*domaintail == k_dns_separator)
- {
- domaintail --;
- if (*domaintail == k_dns_separator)
- {
- return CMP_DNS_SUFFIX_BAD_DOMAIN;
- }
- }
-
- // Compare.
- while (
- nametail >= name
- && domaintail >= domain
- && tolower(*nametail) == tolower(*domaintail))
- {
- nametail--;
- domaintail--;
- }
-
- /* A successful finish will be one of the following:
- (leading and trailing . ignored)
-
- name : domain2.domain1
- domain: domain2.domain1
- ^
-
- name : domain3.domain2.domain1
- domain: domain2.domain1
- ^
- */
- if (
- domaintail < domain
- && (nametail < name || *nametail == k_dns_separator)
- )
- {
- return CMP_DNS_SUFFIX_SUCCESS;
- }
- else
- {
- return CMP_DNS_SUFFIX_FAILURE;
- }
+ const char * nametail;
+ const char * domaintail;
+
+ // Idiot checks
+ if (*name == 0 || *name == k_dns_separator)
+ {
+ // Name can't be empty or start with separator
+ return CMP_DNS_SUFFIX_BAD_NAME;
+ }
+
+ if (*domain == 0)
+ {
+ return CMP_DNS_SUFFIX_SUCCESS;
+ // trivially true
+ }
+
+ if (*domain == k_dns_separator)
+ {
+ // drop leading separator from domain
+ domain++;
+ if (*domain == k_dns_separator)
+ {
+ return CMP_DNS_SUFFIX_BAD_DOMAIN;
+ }
+ }
+
+ // Find ends of strings
+ for (nametail = name; *nametail; nametail++)
+ ;
+ for (domaintail = domain; *domaintail; domaintail++)
+ ;
+
+ // Shuffle back to last real character, and drop any trailing '.'
+ // while we're at it.
+ nametail--;
+ if (*nametail == k_dns_separator)
+ {
+ nametail--;
+ if (*nametail == k_dns_separator)
+ {
+ return CMP_DNS_SUFFIX_BAD_NAME;
+ }
+ }
+ domaintail--;
+ if (*domaintail == k_dns_separator)
+ {
+ domaintail--;
+ if (*domaintail == k_dns_separator)
+ {
+ return CMP_DNS_SUFFIX_BAD_DOMAIN;
+ }
+ }
+
+ // Compare.
+ while (
+ nametail >= name
+ && domaintail >= domain
+ && tolower(*nametail) == tolower(*domaintail))
+ {
+ nametail--;
+ domaintail--;
+ }
+
+ /* A successful finish will be one of the following:
+ (leading and trailing . ignored)
+
+ name : domain2.domain1
+ domain: domain2.domain1
+ ^
+
+ name : domain3.domain2.domain1
+ domain: domain2.domain1
+ ^
+ */
+ if (
+ domaintail < domain
+ && (nametail < name || *nametail == k_dns_separator)
+ )
+ {
+ return CMP_DNS_SUFFIX_SUCCESS;
+ }
+ else
+ {
+ return CMP_DNS_SUFFIX_FAILURE;
+ }
}
-int
-dns_rdata_to_name (const char * rdata, int rdlen, char * name, int name_len)
-{
- int i = 0;
- // Index into 'name'
- const char * rdata_curr = rdata;
-
- // drop any leading whitespace rubbish
- while (isspace (*rdata_curr))
- {
- rdata_curr ++;
- if (rdata_curr > rdata + rdlen)
- {
- return DNS_RDATA_TO_NAME_BAD_FORMAT;
- }
- }
-
- /*
- In RDATA, a DNS name is stored as a series of labels.
- Each label consists of a length octet (max value 63)
- followed by the data for that label.
- The series is terminated with a length 0 octet.
- A length octet beginning with bits 11 is a pointer to
- somewhere else in the payload, but we don't support these
- since we don't have access to the entire payload.
-
- See RFC1034 section 3.1 and RFC1035 section 3.1.
- */
- while (1)
- {
- int term_len = *rdata_curr;
- rdata_curr++;
-
- if (term_len == 0)
- {
- break;
- // 0 length record terminates label
- }
- else if (term_len > k_label_maxlen)
- {
- name [i] = 0;
- return DNS_RDATA_TO_NAME_PTR;
- }
- else if (rdata_curr + term_len > rdata + rdlen)
- {
- name [i] = 0;
- return DNS_RDATA_TO_NAME_BAD_FORMAT;
- }
-
- if (name_len < i + term_len + 1)
- // +1 is separator
- {
- name [i] = 0;
- return DNS_RDATA_TO_NAME_TOO_LONG;
- }
-
- memcpy (name + i, rdata_curr, term_len);
-
- i += term_len;
- rdata_curr += term_len;
-
- name [i] = k_dns_separator;
- i++;
- }
-
- name [i] = 0;
- return i;
+static int
+dns_rdata_to_name (const unsigned char * rdata, int rdlen, char * name, unsigned int name_len)
+{
+ int i = 0;
+ // Index into 'name'
+ const unsigned char * rdata_curr = rdata;
+
+ if (rdlen == 0) return DNS_RDATA_TO_NAME_BAD_FORMAT;
+
+ /*
+ In RDATA, a DNS name is stored as a series of labels.
+ Each label consists of a length octet (max value 63)
+ followed by the data for that label.
+ The series is terminated with a length 0 octet.
+ A length octet beginning with bits 11 is a pointer to
+ somewhere else in the payload, but we don't support these
+ since we don't have access to the entire payload.
+
+ See RFC1034 section 3.1 and RFC1035 section 3.1.
+ */
+ while (1)
+ {
+ unsigned int term_len = *rdata_curr;
+ rdata_curr++;
+
+ if (term_len == 0)
+ {
+ break;
+ // 0 length record terminates label
+ }
+ else if (term_len > k_label_maxlen)
+ {
+ name [i] = 0;
+ return DNS_RDATA_TO_NAME_PTR;
+ }
+ else if (rdata_curr + term_len > rdata + rdlen)
+ {
+ name [i] = 0;
+ return DNS_RDATA_TO_NAME_BAD_FORMAT;
+ }
+
+ if (name_len < i + term_len + 1)
+ // +1 is separator
+ {
+ name [i] = 0;
+ return DNS_RDATA_TO_NAME_TOO_LONG;
+ }
+
+ memcpy (name + i, rdata_curr, term_len);
+
+ i += term_len;
+ rdata_curr += term_len;
+
+ name [i] = k_dns_separator;
+ i++;
+ }
+
+ name [i] = 0;
+ return i;
}
// Local functions
/*
- Find the index of an string entry in a table. A case insenitive match
- is performed. If no entry is found, 0 is returned.
-
- Parameters
- table
- Lookup table
- Table entries may be NULL. NULL entries will never match.
- size
- number of entries in table
- str
- lookup string
-
- Result
- index of first matching entry, or 0 if no matches
+ Find the index of an string entry in a table. A case insenitive match
+ is performed. If no entry is found, 0 is returned.
+
+ Parameters
+ table
+ Lookup table
+ Table entries may be NULL. NULL entries will never match.
+ size
+ number of entries in table
+ str
+ lookup string
+
+ Result
+ index of first matching entry, or 0 if no matches
*/
static int
simple_table_index (const char * table [], int size, const char * str)
{
- int i;
- for (i = 0; i < size; i++)
- {
- if (
- table [i]
- && (strcasecmp (table [i], str) == 0)
- )
- {
- return i;
- }
- }
-
- return 0;
+ int i;
+ for (i = 0; i < size; i++)
+ {
+ if (
+ table [i]
+ && (strcasecmp (table [i], str) == 0)
+ )
+ {
+ return i;
+ }
+ }
+
+ return 0;
}
/*
- Find the index of a name in a table.
-
- Parameters
- table
- array of table_entry_t records. The name field is compared
- (ignoring case) to the input string.
- size
- number of entries in table
- str
- lookup string
-
- Result
- index of first matching entry, or -1 if no matches
+ Find the index of a name in a table.
+
+ Parameters
+ table
+ array of table_entry_t records. The name field is compared
+ (ignoring case) to the input string.
+ size
+ number of entries in table
+ str
+ lookup string
+
+ Result
+ index of first matching entry, or -1 if no matches
*/
static int
table_index_name (const table_entry_t table [], int size, const char * str)
{
- int i;
- for (i = 0; i < size; i++)
- {
- if (
- table [i].name
- && (strcasecmp (table [i].name, str) == 0)
- )
- {
- return i;
- }
- }
-
- return -1;
+ int i;
+ for (i = 0; i < size; i++)
+ {
+ if (
+ table [i].name
+ && (strcasecmp (table [i].name, str) == 0)
+ )
+ {
+ return i;
+ }
+ }
+
+ return -1;
}
/*
- Find the index of a value a table.
-
- Parameters
- table
- array of table_entry_t records. The value field is compared to
- the input value
- size
- number of entries in table
- n
- lookup value
-
- Result
- index of first matching entry, or -1 if no matches
+ Find the index of a value a table.
+
+ Parameters
+ table
+ array of table_entry_t records. The value field is compared to
+ the input value
+ size
+ number of entries in table
+ n
+ lookup value
+
+ Result
+ index of first matching entry, or -1 if no matches
*/
static int
table_index_value (const table_entry_t table [], int size, int n)
{
- int i;
- for (i = 0; i < size; i++)
- {
- if (table [i].value == n)
- {
- return i;
- }
- }
-
- return -1;
+ int i;
+ for (i = 0; i < size; i++)
+ {
+ if (table [i].value == n)
+ {
+ return i;
+ }
+ }
+
+ return -1;
}