1/*-
2 * Copyright (c) 1994, Garrett Wollman
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 *    notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 *    notice, this list of conditions and the following disclaimer in the
11 *    documentation and/or other materials provided with the distribution.
12 *
13 * THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS ``AS IS'' AND
14 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
16 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
17 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
18 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
19 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
20 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
21 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
22 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
23 * SUCH DAMAGE.
24 */
25
26#include <sys/cdefs.h>
27__FBSDID("$FreeBSD$");
28
29#include <sys/param.h>
30#include <sys/socket.h>
31#include <netinet/in.h>
32#include <arpa/inet.h>
33#include <netdb.h>
34#include <resolv.h>
35#include <stdio.h>
36#include <stdlib.h>
37#include <ctype.h>
38#include <errno.h>
39#include <string.h>
40#include <stdarg.h>
41#include <nsswitch.h>
42#include <arpa/nameser.h>
43#ifdef YP
44#include <rpc/rpc.h>
45#include <rpcsvc/yp_prot.h>
46#include <rpcsvc/ypclnt.h>
47#endif
48#include "netdb_private.h"
49
50#ifdef YP
51static int
52_getnetbynis(const char *name, char *map, int af, struct netent *ne,
53    struct netent_data *ned)
54{
55	char *p, *bp, *ep;
56	char *cp, **q;
57	char *result;
58	int resultlen, len;
59	char ypbuf[YPMAXRECORD + 2];
60
61	switch(af) {
62	case AF_INET:
63		break;
64	default:
65	case AF_INET6:
66		errno = EAFNOSUPPORT;
67		return (-1);
68	}
69
70	if (ned->yp_domain == (char *)NULL)
71		if (yp_get_default_domain (&ned->yp_domain))
72			return (-1);
73
74	if (yp_match(ned->yp_domain, map, name, strlen(name), &result,
75	    &resultlen))
76		return (-1);
77
78	bcopy((char *)result, (char *)&ypbuf, resultlen);
79	ypbuf[resultlen] = '\0';
80	free(result);
81	result = (char *)&ypbuf;
82
83	if ((cp = strchr(result, '\n')))
84		*cp = '\0';
85
86	cp = strpbrk(result, " \t");
87	*cp++ = '\0';
88	bp = ned->netbuf;
89	ep = ned->netbuf + sizeof ned->netbuf;
90	len = strlen(result) + 1;
91	if (ep - bp < len) {
92		RES_SET_H_ERRNO(__res_state(), NO_RECOVERY);
93		return (-1);
94	}
95	strlcpy(bp, result, ep - bp);
96	ne->n_name = bp;
97	bp += len;
98
99	while (*cp == ' ' || *cp == '\t')
100		cp++;
101
102	ne->n_net = inet_network(cp);
103	ne->n_addrtype = AF_INET;
104
105	q = ne->n_aliases = ned->net_aliases;
106	cp = strpbrk(cp, " \t");
107	if (cp != NULL)
108		*cp++ = '\0';
109	while (cp && *cp) {
110		if (*cp == ' ' || *cp == '\t') {
111			cp++;
112			continue;
113		}
114		if (q > &ned->net_aliases[_MAXALIASES - 1])
115			break;
116		p = strpbrk(cp, " \t");
117		if (p != NULL)
118			*p++ = '\0';
119		len = strlen(cp) + 1;
120		if (ep - bp < len)
121			break;
122		strlcpy(bp, cp, ep - bp);
123		*q++ = bp;
124		bp += len;
125		cp = p;
126	}
127	*q = NULL;
128	return (0);
129}
130#endif /* YP */
131
132int
133_nis_getnetbyname(void *rval, void *cb_data, va_list ap)
134{
135#ifdef YP
136	const char *name;
137	char *buffer;
138	size_t buflen;
139	int *errnop, *h_errnop;
140	struct netent *nptr, ne;
141	struct netent_data *ned;
142	res_state statp;
143
144	name = va_arg(ap, const char *);
145	nptr = va_arg(ap, struct netent *);
146	buffer = va_arg(ap, char *);
147	buflen = va_arg(ap, size_t);
148	errnop = va_arg(ap, int *);
149	h_errnop = va_arg(ap, int *);
150
151	statp = __res_state();
152	if ((ned = __netent_data_init()) == NULL) {
153		RES_SET_H_ERRNO(statp, NETDB_INTERNAL);
154		*h_errnop = statp->res_h_errno;
155		return (NS_UNAVAIL);
156	}
157
158	if (_getnetbynis(name, "networks.byname", AF_INET, &ne, ned) != 0) {
159		*h_errnop = statp->res_h_errno;
160		return (NS_NOTFOUND);
161	}
162	if (__copy_netent(&ne, nptr, buffer, buflen) != 0) {
163		*errnop = errno;
164		RES_SET_H_ERRNO(statp, NETDB_INTERNAL);
165		*h_errnop = statp->res_h_errno;
166		return (NS_RETURN);
167	}
168	*((struct netent **)rval) = nptr;
169	return (NS_SUCCESS);
170#else
171	return (NS_UNAVAIL);
172#endif
173
174}
175
176int
177_nis_getnetbyaddr(void *rval, void *cb_data, va_list ap)
178{
179#ifdef YP
180	uint32_t addr;
181	int af;
182	char *buffer;
183	size_t buflen;
184	int *errnop, *h_errnop;
185	struct netent *nptr, ne;
186	struct netent_data *ned;
187	char *str, *cp;
188	uint32_t net2;
189	int nn;
190	unsigned int netbr[4];
191	char buf[MAXDNAME];
192	res_state statp;
193
194	addr = va_arg(ap, uint32_t);
195	af = va_arg(ap, int);
196	nptr = va_arg(ap, struct netent *);
197	buffer = va_arg(ap, char *);
198	buflen = va_arg(ap, size_t);
199	errnop = va_arg(ap, int *);
200	h_errnop = va_arg(ap, int *);
201
202	statp = __res_state();
203	if ((ned = __netent_data_init()) == NULL) {
204		RES_SET_H_ERRNO(statp, NETDB_INTERNAL);
205		*h_errnop = statp->res_h_errno;
206		return (NS_UNAVAIL);
207	}
208
209	if (af != AF_INET) {
210		RES_SET_H_ERRNO(statp, NETDB_INTERNAL);
211		*h_errnop = statp->res_h_errno;
212		errno = EAFNOSUPPORT;
213		return (NS_UNAVAIL);
214	}
215
216        for (nn = 4, net2 = addr; net2; net2 >>= 8) {
217                netbr[--nn] = net2 & 0xff;
218	}
219
220	switch (nn) {
221	case 3:		/* Class A */
222		sprintf(buf, "%u", netbr[3]);
223		break;
224        case 2:		/* Class B */
225		sprintf(buf, "%u.%u", netbr[2], netbr[3]);
226		break;
227        case 1:		/* Class C */
228		sprintf(buf, "%u.%u.%u", netbr[1], netbr[2], netbr[3]);
229                break;
230        case 0:		/* Class D - E */
231		sprintf(buf, "%u.%u.%u.%u", netbr[0], netbr[1],
232			netbr[2], netbr[3]);
233		break;
234	}
235
236	str = (char *)&buf;
237	cp = str + (strlen(str) - 2);
238
239	while(!strcmp(cp, ".0")) {
240		*cp = '\0';
241		cp = str + (strlen(str) - 2);
242	}
243
244	if (_getnetbynis(str, "networks.byaddr", af, &ne, ned) != 0) {
245		*h_errnop = statp->res_h_errno;
246		return (NS_NOTFOUND);
247	}
248	if (__copy_netent(&ne, nptr, buffer, buflen) != 0) {
249		*errnop = errno;
250		RES_SET_H_ERRNO(statp, NETDB_INTERNAL);
251		*h_errnop = statp->res_h_errno;
252		return (NS_RETURN);
253	}
254	*((struct netent **)rval) = nptr;
255	return (NS_SUCCESS);
256#else
257	return (NS_UNAVAIL);
258#endif /* YP */
259}
260