1/*
2 * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
3 * Copyright (c) 1998-1999 by Internet Software Consortium.
4 *
5 * Permission to use, copy, modify, and distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above
7 * copyright notice and this permission notice appear in all copies.
8 *
9 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 * MERCHANTABILITY AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR
12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
15 * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16 */
17
18#include <port_before.h>
19#if !defined(_REENTRANT) || !defined(DO_PTHREADS)
20	static int getnetent_r_not_required = 0;
21#else
22#include <errno.h>
23#include <string.h>
24#include <stdio.h>
25#include <sys/types.h>
26#include <netinet/in.h>
27#include <netdb.h>
28#include <sys/param.h>
29#include <port_after.h>
30
31#ifdef NET_R_RETURN
32
33static NET_R_RETURN
34copy_netent(struct netent *, struct netent *, NET_R_COPY_ARGS);
35
36NET_R_RETURN
37getnetbyname_r(const char *name,  struct netent *nptr, NET_R_ARGS) {
38	struct netent *ne = getnetbyname(name);
39#ifdef NET_R_SETANSWER
40	int n = 0;
41
42	if (ne == NULL || (n = copy_netent(ne, nptr, NET_R_COPY)) != 0)
43		*answerp = NULL;
44	else
45		*answerp = ne;
46	if (ne == NULL)
47		*h_errnop = h_errno;
48	return (n);
49#else
50	if (ne == NULL)
51		return (NET_R_BAD);
52
53	return (copy_netent(ne, nptr, NET_R_COPY));
54#endif
55}
56
57#ifndef GETNETBYADDR_ADDR_T
58#define GETNETBYADDR_ADDR_T long
59#endif
60NET_R_RETURN
61getnetbyaddr_r(GETNETBYADDR_ADDR_T addr, int type, struct netent *nptr, NET_R_ARGS) {
62	struct netent *ne = getnetbyaddr(addr, type);
63#ifdef NET_R_SETANSWER
64	int n = 0;
65
66	if (ne == NULL || (n = copy_netent(ne, nptr, NET_R_COPY)) != 0)
67		*answerp = NULL;
68	else
69		*answerp = ne;
70	if (ne == NULL)
71		*h_errnop = h_errno;
72	return (n);
73#else
74
75	if (ne == NULL)
76		return (NET_R_BAD);
77
78	return (copy_netent(ne, nptr, NET_R_COPY));
79#endif
80}
81
82/*%
83 *	These assume a single context is in operation per thread.
84 *	If this is not the case we will need to call irs directly
85 *	rather than through the base functions.
86 */
87
88NET_R_RETURN
89getnetent_r(struct netent *nptr, NET_R_ARGS) {
90	struct netent *ne = getnetent();
91#ifdef NET_R_SETANSWER
92	int n = 0;
93
94	if (ne == NULL || (n = copy_netent(ne, nptr, NET_R_COPY)) != 0)
95		*answerp = NULL;
96	else
97		*answerp = ne;
98	if (ne == NULL)
99		*h_errnop = h_errno;
100	return (n);
101#else
102
103	if (ne == NULL)
104		return (NET_R_BAD);
105
106	return (copy_netent(ne, nptr, NET_R_COPY));
107#endif
108}
109
110NET_R_SET_RETURN
111#ifdef NET_R_ENT_ARGS
112setnetent_r(int stay_open, NET_R_ENT_ARGS)
113#else
114setnetent_r(int stay_open)
115#endif
116{
117#ifdef NET_R_ENT_ARGS
118	UNUSED(ndptr);
119#endif
120	setnetent(stay_open);
121#ifdef NET_R_SET_RESULT
122	return (NET_R_SET_RESULT);
123#endif
124}
125
126NET_R_END_RETURN
127#ifdef NET_R_ENT_ARGS
128endnetent_r(NET_R_ENT_ARGS)
129#else
130endnetent_r()
131#endif
132{
133#ifdef NET_R_ENT_ARGS
134	UNUSED(ndptr);
135#endif
136	endnetent();
137	NET_R_END_RESULT(NET_R_OK);
138}
139
140/* Private */
141
142#ifndef NETENT_DATA
143static NET_R_RETURN
144copy_netent(struct netent *ne, struct netent *nptr, NET_R_COPY_ARGS) {
145	char *cp;
146	int i, n;
147	int numptr, len;
148
149	/* Find out the amount of space required to store the answer. */
150	numptr = 1; /*%< NULL ptr */
151	len = (char *)ALIGN(buf) - buf;
152	for (i = 0; ne->n_aliases[i]; i++, numptr++) {
153		len += strlen(ne->n_aliases[i]) + 1;
154	}
155	len += strlen(ne->n_name) + 1;
156	len += numptr * sizeof(char*);
157
158	if (len > (int)buflen) {
159		errno = ERANGE;
160		return (NET_R_BAD);
161	}
162
163	/* copy net value and type */
164	nptr->n_addrtype = ne->n_addrtype;
165	nptr->n_net = ne->n_net;
166
167	cp = (char *)ALIGN(buf) + numptr * sizeof(char *);
168
169	/* copy official name */
170	n = strlen(ne->n_name) + 1;
171	strcpy(cp, ne->n_name);
172	nptr->n_name = cp;
173	cp += n;
174
175	/* copy aliases */
176	nptr->n_aliases = (char **)ALIGN(buf);
177	for (i = 0 ; ne->n_aliases[i]; i++) {
178		n = strlen(ne->n_aliases[i]) + 1;
179		strcpy(cp, ne->n_aliases[i]);
180		nptr->n_aliases[i] = cp;
181		cp += n;
182	}
183	nptr->n_aliases[i] = NULL;
184
185	return (NET_R_OK);
186}
187#else /* !NETENT_DATA */
188static int
189copy_netent(struct netent *ne, struct netent *nptr, NET_R_COPY_ARGS) {
190	char *cp, *eob;
191	int i, n;
192
193	/* copy net value and type */
194	nptr->n_addrtype = ne->n_addrtype;
195	nptr->n_net = ne->n_net;
196
197	/* copy official name */
198	cp = ndptr->line;
199	eob = ndptr->line + sizeof(ndptr->line);
200	if ((n = strlen(ne->n_name) + 1) < (eob - cp)) {
201		strcpy(cp, ne->n_name);
202		nptr->n_name = cp;
203		cp += n;
204	} else {
205		return (-1);
206	}
207
208	/* copy aliases */
209	i = 0;
210	nptr->n_aliases = ndptr->net_aliases;
211	while (ne->n_aliases[i] && i < (_MAXALIASES-1)) {
212		if ((n = strlen(ne->n_aliases[i]) + 1) < (eob - cp)) {
213			strcpy(cp, ne->n_aliases[i]);
214			nptr->n_aliases[i] = cp;
215			cp += n;
216		} else {
217			break;
218		}
219		i++;
220	}
221	nptr->n_aliases[i] = NULL;
222
223	return (NET_R_OK);
224}
225#endif /* !NETENT_DATA */
226#else /* NET_R_RETURN */
227	static int getnetent_r_unknown_system = 0;
228#endif /* NET_R_RETURN */
229#endif /* !defined(_REENTRANT) || !defined(DO_PTHREADS) */
230/*! \file */
231