dns_common.c revision 0e50326a4ce28578aae604a6b6d95bc7c4ce6540
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
/*
*/
#include "dns_common.h"
#pragma weak res_ndestroy
#pragma weak res_nsearch
#pragma weak res_nclose
#pragma weak __ns_get16
#pragma weak __ns_get32
#define DNS_ALIASES 0
#define DNS_ADDRLIST 1
#define DNS_MAPDLIST 2
#ifndef tolower
#endif
static int
{
char *fstr;
int cnt = 0;
*count = 0;
return (NSS_STR_PARSE_ERANGE);
if (type == DNS_ALIASES)
else
: sizeof (struct in6_addr);
return (NSS_STR_PARSE_ERANGE);
if (type == DNS_MAPDLIST) {
/* LINTED: E_BAD_PTR_CAST_ALIGN */
sizeof (struct in_addr));
++cnt;
} else {
++cnt;
}
}
if (cnt == 0)
return (NSS_STR_PARSE_PARSE);
return (NSS_STR_PARSE_SUCCESS);
}
int
int af_type;
{
/* h_addrtype and h_length */
: sizeof (struct in6_addr);
/* h_name */
return (NSS_STR_PARSE_ERANGE);
/* h_addr_list */
host->h_addr_list = (char **)
if (ret != NSS_STR_PARSE_SUCCESS)
return (ret);
/* h_aliases */
} else {
host->h_addr_list = (char **)
} else {
}
if (ret != NSS_STR_PARSE_SUCCESS)
return (ret);
/* h_aliases */
}
if (ret == NSS_STR_PARSE_PARSE)
return (ret);
}
/*
* Convert the hostent structure into string in the following
* format:
*
* IP-address official-host-name nicknames ...
*
* If more than one IP-addresses matches the official-host-name,
* the above line will be followed by:
* IP-address-1 official-host-name
* IP-address-2 official-host-name
* ...
*
* This is so that the str2hostent function in libnsl
* can convert the string back to the original hostent
* data.
*/
int
int af_type)
{
char **p;
char obuf[INET6_ADDRSTRLEN];
void *addr;
int af;
int n;
const char *res;
char **q;
/*
* for "hosts" lookup, we only want address type of
* AF_INET. For "ipnodes", we can have both AF_INET
* and AF_INET6.
*/
return (NSS_STR_PARSE_PARSE);
for (p = hp->h_addr_list; *p != 0; p++) {
if (p != hp->h_addr_list) {
*s = '\n';
s++;
l--;
}
/* LINTED: E_BAD_PTR_CAST_ALIGN */
if (IN6_IS_ADDR_V4MAPPED((struct in6_addr *)*p)) {
/* LINTED: E_BAD_PTR_CAST_ALIGN */
IN6_V4MAPPED_TO_INADDR((struct in6_addr *)*p,
&in4);
} else {
addr = *p;
}
} else {
addr = *p;
}
return (NSS_STR_PARSE_PARSE);
return (NSS_STR_PARSE_ERANGE);
l -= n;
s += n;
return (NSS_STR_PARSE_ERANGE);
l -= n;
s += n;
}
if (p == hp->h_addr_list) {
if ((n = snprintf(s, l, " %s", *q)) >= l)
return (NSS_STR_PARSE_ERANGE);
l -= n;
s += n;
}
}
}
return (NSS_STR_PARSE_SUCCESS);
}
{
return (0);
return ((nss_backend_t *)be);
}
/*
* name_is_alias(aliases_ptr, name_ptr)
* Verify name matches an alias in the provided aliases list.
*
* Within DNS there should be only one canonical name, aliases should
* all refer to the one canonical. However alias chains do occur and
* pre BIND 9 servers may also respond with multiple CNAMEs. This
* routine checks if a given name has been provided as a CNAME in the
* response. This assumes that the chains have been sent in-order.
*
* INPUT:
* aliases_ptr: space separated list of alias names.
* name_ptr: name to look for in aliases_ptr list.
* RETURNS: NSS_SUCCESS or NSS_NOTFOUND
* NSS_SUCCESS indicates that the name is listed in the collected aliases.
*/
static nss_status_t
char *host_ptr;
/* Loop through alias string and compare it against host string. */
while (*aliases_ptr != '\0') {
/* Compare name with alias. */
*host_ptr != '\0') {
host_ptr++;
aliases_ptr++;
}
/*
* If name was exhausted and the next character in the
* alias is either the end-of-string or space
* character then we have a match.
*/
if (*host_ptr == '\0' &&
return (NSS_SUCCESS);
}
/* Alias did not match, step over remainder of alias. */
aliases_ptr++;
/* Step over separator character. */
}
return (NSS_NOTFOUND);
}
/*
* nss_dns_gethost_withttl(void *buffer, size_t bufsize, int ipnode)
*
* This API is given a pointer to a packed buffer, and the buffer size
* It's job is to perform the appropriate res_nsearch, extract the
* Additionally in the extended results a nssuint_t ttl is placed.
* This ttl is the lessor of the ttl's extracted from the result.
*
* ***Currently the first version of this API only performs simple
* single res_nsearch lookups for with T_A or T_AAAA results.
* Other searches are deferred to the generic API w/t ttls.
*
* This function is not a generic res_* operation. It only performs
* a single T_A or T_AAAA lookups***
*
* RETURNS: NSS_SUCCESS or NSS_ERROR
* If an NSS_ERROR result is returned, nscd is expected
* to resubmit the gethosts request using the old style
* nsswitch lookup format.
*/
{
/* nss buffer variables */
char *dbname;
int dbop;
char *bptr;
/* resolver query variables */
union msg {
HEADER h;
} resbuf;
const char *name;
int qtype;
/* answer parsing variables */
int n, ret;
const char *np;
/* temporary buffers */
/* misc variables */
int af;
return (NSS_ERROR);
alen = 0;
/* save space for ttl otherwise, why bother... */
blen = 0;
if (sret != NSS_SUCCESS) {
return (NSS_ERROR);
}
if (ipnode) {
/* initially only handle the simple cases */
return (NSS_ERROR);
}
else
} else {
}
if (ret == -1) {
return (NSS_NOTFOUND);
}
/* else lookup error - handle in general code */
return (NSS_ERROR);
}
if (qdcount != 1) {
return (NSS_ERROR);
}
if (n < 0) {
return (NSS_ERROR);
} else
/* no host name is an error, return */
if (hlen <= 0) {
return (NSS_ERROR);
}
return (NSS_ERROR);
}
if (n > 0) {
/*
* Check that the expanded name is either the
* name we asked for or a learned alias.
*/
== NSS_NOTFOUND)) {
return (NSS_ERROR); /* spoof? */
}
}
cp += n;
/* bounds check */
cp += n;
continue;
}
/*
* The name looked up is really an alias and the
* canonical name should be in the RDATA.
* A canonical name may have several aliases but an
* alias should only have one canonical name.
* However multiple CNAMEs and CNAME chains do exist!
*
* Just error out on attempted buffer overflow exploit,
* generic code will syslog.
*
*/
if (isans == 0) { /* host matched ans. */
/*
* Append host to alias list.
*/
return (NSS_ERROR);
}
*apc++ = ' ';
alen++;
}
/*
* Overwrite host with canonical name.
*/
return (NSS_ERROR);
}
}
cp += n;
continue;
}
cp += n;
continue;
}
/* check data size */
cp += n;
continue;
}
return (NSS_ERROR);
}
cp += n;
/* append IP host aliases to results */
/* ip <SP> hostname [<SP>][aliases] */
if (alen > 0)
len++;
return (NSS_ERROR);
}
*bptr++ = ' ';
blen++;
if (alen > 0) {
*bptr++ = ' ';
blen++;
}
*bptr++ = '\n';
blen++;
}
/* Presumably the buffer is now filled. */
/* still room? */
/* sigh, no, what happened? */
return (NSS_ERROR);
}
return (NSS_SUCCESS);
}