dns_common.c revision 7c478bd95313f5f23a4c958a745db2134aa03244
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License, Version 1.0 only
* (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
* or http://www.opensolaris.org/os/licensing.
* 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
*/
/*
* dns_common.c
*
* Copyright (c) 1993,1998 by Sun Microsystems, Inc.
* All rights reserved.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
#include "dns_common.h"
#define DNS_ALIASES 0
#define DNS_ADDRLIST 1
#define DNS_MAPDLIST 2
static int
dns_netdb_aliases(from_list, to_list, aliaspp, type, count, af_type)
char **from_list, **to_list, **aliaspp;
int type, *count, af_type;
{
char *fstr;
int cnt = 0;
size_t len;
*count = 0;
if ((char *)to_list >= *aliaspp)
return (NSS_STR_PARSE_ERANGE);
for (fstr = from_list[cnt]; fstr != NULL; fstr = from_list[cnt]) {
if (type == DNS_ALIASES)
len = strlen(fstr) + 1;
else
len = (af_type == AF_INET) ? sizeof (struct in_addr)
: sizeof (struct in6_addr);
*aliaspp -= len;
to_list[cnt] = *aliaspp;
if (*aliaspp <= (char *)&to_list[cnt+1])
return (NSS_STR_PARSE_ERANGE);
if (type == DNS_MAPDLIST) {
struct in6_addr *addr6p = (struct in6_addr *) *aliaspp;
(void) memset(addr6p, '\0', sizeof (struct in6_addr));
(void) memcpy(&addr6p->s6_addr[12], fstr,
sizeof (struct in_addr));
addr6p->s6_addr[10] = 0xffU;
addr6p->s6_addr[11] = 0xffU;
++cnt;
} else {
(void) memcpy (*aliaspp, fstr, len);
++cnt;
}
}
to_list[cnt] = NULL;
*count = cnt;
if (cnt == 0)
return (NSS_STR_PARSE_PARSE);
return (NSS_STR_PARSE_SUCCESS);
}
int
ent2result(he, argp, af_type)
struct hostent *he;
nss_XbyY_args_t *argp;
int af_type;
{
char *buffer, *limit;
int buflen = argp->buf.buflen;
int ret, count;
size_t len;
struct hostent *host;
struct in_addr *addrp;
struct in6_addr *addrp6;
limit = argp->buf.buffer + buflen;
host = (struct hostent *) argp->buf.result;
buffer = argp->buf.buffer;
/* h_addrtype and h_length */
host->h_addrtype = af_type;
host->h_length = (af_type == AF_INET) ? sizeof (struct in_addr)
: sizeof (struct in6_addr);
/* h_name */
len = strlen(he->h_name) + 1;
host->h_name = buffer;
if (host->h_name + len >= limit)
return (NSS_STR_PARSE_ERANGE);
(void) memcpy(host->h_name, he->h_name, len);
buffer += len;
/* h_addr_list */
if (af_type == AF_INET) {
addrp = (struct in_addr *) ROUND_DOWN(limit, sizeof (*addrp));
host->h_addr_list = (char **)
ROUND_UP(buffer, sizeof (char **));
ret = dns_netdb_aliases(he->h_addr_list, host->h_addr_list,
(char **)&addrp, DNS_ADDRLIST, &count, af_type);
if (ret != NSS_STR_PARSE_SUCCESS)
return (ret);
/* h_aliases */
host->h_aliases = host->h_addr_list + count + 1;
ret = dns_netdb_aliases(he->h_aliases, host->h_aliases,
(char **)&addrp, DNS_ALIASES, &count, af_type);
} else {
addrp6 = (struct in6_addr *)
ROUND_DOWN(limit, sizeof (*addrp6));
host->h_addr_list = (char **)
ROUND_UP(buffer, sizeof (char **));
if (he->h_addrtype == AF_INET && af_type == AF_INET6) {
ret = dns_netdb_aliases(he->h_addr_list,
host->h_addr_list, (char **)&addrp6,
DNS_MAPDLIST, &count, af_type);
} else {
ret = dns_netdb_aliases(he->h_addr_list,
host->h_addr_list, (char **)&addrp6,
DNS_ADDRLIST, &count, af_type);
}
if (ret != NSS_STR_PARSE_SUCCESS)
return (ret);
/* h_aliases */
host->h_aliases = host->h_addr_list + count + 1;
ret = dns_netdb_aliases(he->h_aliases, host->h_aliases,
(char **)&addrp6, DNS_ALIASES, &count, af_type);
}
if (ret == NSS_STR_PARSE_PARSE)
ret = NSS_STR_PARSE_SUCCESS;
return (ret);
}
nss_backend_t *
_nss_dns_constr(dns_backend_op_t ops[], int n_ops)
{
dns_backend_ptr_t be;
if ((be = (dns_backend_ptr_t) malloc(sizeof (*be))) == 0)
return (0);
be->ops = ops;
be->n_ops = n_ops;
return ((nss_backend_t *) be);
}