1 /*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21
22 /*
23 * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
25 */
26
27 /*
28 * gethostbyname_r() is defined in this file. It is implemented on top of
29 * _get_hostserv_inetnetdir_byname() which is also used to implement
30 * netdir_getbyname() for inet family transports. In turn the common code
31 * uses the name service switch policy for "hosts" and "services" unless
32 * the administrator chooses to bypass the name service switch by
33 * specifying third-party supplied nametoaddr libs for inet transports
34 * in /etc/netconfig.
35 *
36 * gethostbyaddr_r() is similarly related to _get_hostserv_inetnetdir_byaddr()
37 * and netdir_getbyaddr();
38 *
39 * The common code lives in netdir_inet.c.
40 *
41 * gethostent_r(), sethostent() and endhostent() are *not* implemented on top
42 * of the common interface; they go straight to the switch and are
43 * defined in gethostent_r.c.
44 *
45 * There is absolutely no data sharing, not even the stayopen flag or
46 * enumeration state, between gethostbyYY_r() and gethostent_r();
47 */
48
49 #include "mt.h"
50 #include <netdb.h>
51 #include <netdir.h>
52 #include <sys/types.h>
53 #include <nss_netdir.h>
54 #include <string.h>
55
56 extern struct netconfig *__rpc_getconfip();
57
58 /*
59 * h_errno POLICY: The frontends expect the name service
60 * backends to modify the h_errno in "arg"; _switch_gethostbyYY_r()
61 * will copy that over onto user's h_errnop pointer. This h_errno is
62 * never used for "switching" -- status from nss_search serves
63 * the purpose. There is no explicit zeroing in the case of success.
64 */
65
66 extern struct hostent *
67 _switch_gethostbyname_r(const char *nam, struct hostent *result, char *buffer,
68 int buflen, int *h_errnop);
69
70 extern struct hostent *
71 _switch_gethostbyaddr_r(const char *addr, int length, int type,
72 struct hostent *result, char *buffer, int buflen, int *h_errnop);
73
74 #ifdef PIC
75 struct hostent *
_uncached_gethostbyname_r(const char * nam,struct hostent * result,char * buffer,int buflen,int * h_errnop)76 _uncached_gethostbyname_r(const char *nam, struct hostent *result,
77 char *buffer, int buflen, int *h_errnop)
78 {
79 return (_switch_gethostbyname_r(nam, result,
80 buffer, buflen, h_errnop));
81 }
82
83 struct hostent *
_uncached_gethostbyaddr_r(const char * addr,int length,int type,struct hostent * result,char * buffer,int buflen,int * h_errnop)84 _uncached_gethostbyaddr_r(const char *addr, int length, int type,
85 struct hostent *result, char *buffer, int buflen, int *h_errnop)
86 {
87 return (_switch_gethostbyaddr_r(addr, length, type,
88 result, buffer, buflen, h_errnop));
89 }
90
91 #endif
92
93 extern struct hostent *
94 gethostbyname_r(const char *nam, struct hostent *result, char *buffer,
95 int buflen, int *h_errnop);
96
97 extern struct hostent *
98 gethostbyaddr_r(const char *addr, int length, int type,
99 struct hostent *result, char *buffer, int buflen, int *h_errnop);
100
101 struct hostent *
gethostbyname_r(const char * nam,struct hostent * result,char * buffer,int buflen,int * h_errnop)102 gethostbyname_r(const char *nam, struct hostent *result, char *buffer,
103 int buflen, int *h_errnop)
104 {
105 struct netconfig *nconf;
106 struct nss_netdirbyname_in nssin;
107 union nss_netdirbyname_out nssout;
108 int neterr, dummy;
109
110 if (h_errnop == NULL)
111 h_errnop = &dummy;
112
113 if (strlen(nam) == 0) {
114 *h_errnop = HOST_NOT_FOUND;
115 return (NULL);
116 }
117
118 if ((nconf = __rpc_getconfip("udp")) == NULL &&
119 (nconf = __rpc_getconfip("tcp")) == NULL) {
120 *h_errnop = NO_RECOVERY;
121 return (NULL);
122 }
123
124 nssin.op_t = NSS_HOST;
125 nssin.arg.nss.host.name = nam;
126 nssin.arg.nss.host.buf = buffer;
127 nssin.arg.nss.host.buflen = buflen;
128
129 nssout.nss.host.hent = result;
130 nssout.nss.host.herrno_p = h_errnop;
131
132 /*
133 * We pass in nconf and let the implementation of the long-named func
134 * decide whether to use the switch based on nc_nlookups.
135 */
136 neterr = _get_hostserv_inetnetdir_byname(nconf, &nssin, &nssout);
137
138 (void) freenetconfigent(nconf);
139 if (neterr != ND_OK)
140 return (NULL);
141 return (nssout.nss.host.hent);
142 }
143
144 struct hostent *
gethostbyaddr_r(const char * addr,int length,int type,struct hostent * result,char * buffer,int buflen,int * h_errnop)145 gethostbyaddr_r(const char *addr, int length, int type,
146 struct hostent *result, char *buffer, int buflen, int *h_errnop)
147 {
148 struct netconfig *nconf;
149 struct nss_netdirbyaddr_in nssin;
150 union nss_netdirbyaddr_out nssout;
151 int neterr, dummy;
152
153 if (h_errnop == NULL)
154 h_errnop = &dummy;
155
156 if (type != AF_INET) {
157 *h_errnop = HOST_NOT_FOUND;
158 return (NULL);
159 }
160
161 if ((nconf = __rpc_getconfip("udp")) == NULL &&
162 (nconf = __rpc_getconfip("tcp")) == NULL) {
163 *h_errnop = NO_RECOVERY;
164 return (NULL);
165 }
166
167 nssin.op_t = NSS_HOST;
168 nssin.arg.nss.host.addr = addr;
169 nssin.arg.nss.host.len = length;
170 nssin.arg.nss.host.type = type;
171 nssin.arg.nss.host.buf = buffer;
172 nssin.arg.nss.host.buflen = buflen;
173
174 nssout.nss.host.hent = result;
175 nssout.nss.host.herrno_p = h_errnop;
176
177 /*
178 * We pass in nconf and let the implementation of this long-named func
179 * decide whether to use the switch based on nc_nlookups.
180 */
181 neterr = _get_hostserv_inetnetdir_byaddr(nconf, &nssin, &nssout);
182
183 (void) freenetconfigent(nconf);
184 if (neterr != ND_OK)
185 return (NULL);
186 return (nssout.nss.host.hent);
187 }
188