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.
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.
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]
21 * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
22 * Use is subject to license terms.
25 /* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */
26 /* All Rights Reserved */
29 * Portions of this source code were derived from Berkeley
30 * under license from the Regents of the University of
34 #pragma ident "%Z%%M% %I% %E% SMI"
36 #include <sys/types.h>
42 #include <netinet/in.h>
43 #include <arpa/inet.h>
44 #include <sys/socket.h>
48 #include <rpc/pmap_clnt.h>
49 #include <rpcsvc/nis.h>
51 CLIENT
*__clnt_tp_create_bootstrap();
52 int __rpcb_getaddr_bootstrap();
53 struct hostent
*__files_gethostbyname(char *, sa_family_t
);
55 extern int hostNotKnownLocally
;
57 static char *__map_addr();
58 static struct hostent host
;
59 static char hostaddr
[sizeof (struct in6_addr
)];
60 static char *host_aliases
[MAXALIASES
];
61 static char *host_addrs
[] = {
67 * __clnt_tp_create_bootstrap()
69 * This routine is NOT TRANSPORT INDEPENDENT.
71 * It relies on the local /etc/hosts file for hostname to address
72 * translation and does it itself instead of calling netdir_getbyname
73 * thereby avoids recursion. Secondarily, it will use a validated
74 * IP address directly.
77 __clnt_tp_create_bootstrap(hostname
, prog
, vers
, nconf
)
80 struct netconfig
*nconf
;
83 struct netbuf
*svc_taddr
;
84 struct sockaddr_in6
*sa
;
88 rpc_createerr
.cf_stat
= RPC_N2AXLATEFAILURE
;
91 if ((fd
= t_open(nconf
->nc_device
, O_RDWR
, NULL
)) == -1) {
92 rpc_createerr
.cf_stat
= RPC_TLIERROR
;
95 svc_taddr
= (struct netbuf
*)malloc(sizeof (struct netbuf
));
97 rpc_createerr
.cf_stat
= RPC_SYSTEMERROR
;
101 sa
= (struct sockaddr_in6
*)calloc(1, sizeof (*sa
));
103 rpc_createerr
.cf_stat
= RPC_SYSTEMERROR
;
108 svc_taddr
->maxlen
= svc_taddr
->len
= sizeof (*sa
);
109 svc_taddr
->buf
= (char *)sa
;
110 if (__rpcb_getaddr_bootstrap(prog
,
111 vers
, nconf
, svc_taddr
, hostname
) == FALSE
) {
117 rpc_createerr
.cf_stat
= RPC_SUCCESS
;
118 cl
= __nis_clnt_create(fd
, nconf
, 0, svc_taddr
, 0, prog
, vers
, 0, 0);
120 if (rpc_createerr
.cf_stat
== RPC_SUCCESS
)
121 rpc_createerr
.cf_stat
= RPC_TLIERROR
;
130 * __rpcb_getaddr_bootstrap()
132 * This is our internal function that replaces rpcb_getaddr(). We
133 * build our own to prevent calling netdir_getbyname() which could
134 * recurse to the nameservice.
137 __rpcb_getaddr_bootstrap(program
, version
, nconf
, address
, hostname
)
140 struct netconfig
*nconf
;
141 struct netbuf
*address
; /* populate with the taddr of the service */
145 struct hostent
*hent
, tmphent
;
146 struct sockaddr_in
*sa
;
147 struct sockaddr_in6
*sa6
;
148 struct netbuf rpcb_taddr
;
149 struct sockaddr_in local_sa
;
150 struct sockaddr_in6 local_sa6
;
156 char addr
[sizeof (in6_addr_t
)];
157 char *tmphost_addrs
[2];
159 if (strcmp(nconf
->nc_protofmly
, NC_INET6
) == 0) {
161 } else if (strcmp(nconf
->nc_protofmly
, NC_INET
) == 0) {
164 rpc_createerr
.cf_stat
= RPC_UNKNOWNADDR
;
168 /* Get the address of the RPCBIND at hostname */
169 hent
= __files_gethostbyname(hostname
, type
);
171 /* Make sure this is not an IP address before giving up */
172 if (inet_pton(type
, hostname
, addr
) == 1) {
173 /* This is a numeric address, fill in the blanks */
175 memset(&tmphent
, 0, sizeof (struct hostent
));
176 hent
->h_addrtype
= type
;
177 hent
->h_length
= (type
== AF_INET6
) ?
178 sizeof (in6_addr_t
) : sizeof (in_addr_t
);
179 hent
->h_addr_list
= tmphost_addrs
;
180 tmphost_addrs
[0] = addr
;
181 tmphost_addrs
[1] = NULL
;
183 rpc_createerr
.cf_stat
= RPC_UNKNOWNHOST
;
184 hostNotKnownLocally
= 1;
189 switch (hent
->h_addrtype
) {
191 local_sa
.sin_family
= AF_INET
;
192 local_sa
.sin_port
= htons(111); /* RPCBIND port */
193 memcpy((char *)&(local_sa
.sin_addr
.s_addr
),
194 hent
->h_addr_list
[0], hent
->h_length
);
195 rpcb_taddr
.buf
= (char *)&local_sa
;
196 rpcb_taddr
.maxlen
= sizeof (local_sa
);
197 rpcb_taddr
.len
= rpcb_taddr
.maxlen
;
200 local_sa6
.sin6_family
= AF_INET6
;
201 local_sa6
.sin6_port
= htons(111); /* RPCBIND port */
202 memcpy((char *)&(local_sa6
.sin6_addr
.s6_addr
),
203 hent
->h_addr_list
[0], hent
->h_length
);
204 rpcb_taddr
.buf
= (char *)&local_sa6
;
205 rpcb_taddr
.maxlen
= sizeof (local_sa6
);
206 rpcb_taddr
.len
= rpcb_taddr
.maxlen
;
209 rpc_createerr
.cf_stat
= RPC_N2AXLATEFAILURE
;
213 svc_uaddr
= __map_addr(nconf
, &rpcb_taddr
, program
, version
);
217 /* do a local uaddr2taddr and stuff in the memory supplied by the caller */
219 ipaddrlen
= strlen(ipaddr
);
220 /* Look for the first '.' starting from the end */
221 for (i
= ipaddrlen
-1; i
>= 0; i
--)
222 if (ipaddr
[i
] == '.')
224 /* Find the second dot (still counting from the end) */
225 for (i
--; i
>= 0; i
--)
226 if (ipaddr
[i
] == '.')
228 /* If we didn't find it, the uaddr has a syntax error */
230 rpc_createerr
.cf_stat
= RPC_N2AXLATEFAILURE
;
235 sscanf(port
, "%d.%d", &p1
, &p2
);
236 inport
= (p1
<< 8) + p2
;
237 if (hent
->h_addrtype
== AF_INET
) {
238 sa
= (struct sockaddr_in
*)address
->buf
;
239 address
->len
= sizeof (*sa
);
240 if (inet_pton(AF_INET
, ipaddr
, &sa
->sin_addr
) != 1) {
241 rpc_createerr
.cf_stat
= RPC_N2AXLATEFAILURE
;
244 sa
->sin_port
= htons(inport
);
245 sa
->sin_family
= AF_INET
;
247 sa6
= (struct sockaddr_in6
*)address
->buf
;
248 address
->len
= sizeof (*sa6
);
249 if (inet_pton(AF_INET6
, ipaddr
, &sa6
->sin6_addr
) != 1) {
250 rpc_createerr
.cf_stat
= RPC_N2AXLATEFAILURE
;
253 sa6
->sin6_port
= htons(inport
);
254 sa6
->sin6_family
= AF_INET6
;
264 __map_addr(nc
, rpcb_taddr
, prog
, ver
)
265 struct netconfig
*nc
; /* Our transport */
266 struct netbuf
*rpcb_taddr
; /* RPCBIND address */
267 ulong_t prog
, ver
; /* Name service Prog/vers */
269 register CLIENT
*client
;
270 RPCB parms
; /* Parameters for RPC binder */
271 enum clnt_stat clnt_st
; /* Result from the rpc call */
272 int fd
; /* Stream file descriptor */
273 char *ua
= NULL
; /* Universal address of service */
274 struct timeval tv
; /* Timeout for our rpcb call */
277 * First we open a connection to the remote rpcbind process.
279 if ((fd
= t_open(nc
->nc_device
, O_RDWR
, NULL
)) == -1) {
280 rpc_createerr
.cf_stat
= RPC_TLIERROR
;
284 client
= __nis_clnt_create(fd
, nc
, 0, rpcb_taddr
, 0,
285 RPCBPROG
, RPCBVERS
, 0, 0);
288 rpc_createerr
.cf_stat
= RPC_TLIERROR
;
293 * Now make the call to get the NIS service address.
299 parms
.r_netid
= nc
->nc_netid
; /* not needed */
300 parms
.r_addr
= ""; /* not needed; just for xdring */
301 parms
.r_owner
= ""; /* not needed; just for xdring */
302 clnt_st
= clnt_call(client
, RPCBPROC_GETADDR
, xdr_rpcb
, (char *)&parms
,
303 xdr_wrapstring
, (char *)&ua
, tv
);
305 rpc_createerr
.cf_stat
= clnt_st
;
306 if (clnt_st
== RPC_SUCCESS
) {
308 clnt_destroy(client
);
311 xdr_free(xdr_wrapstring
, (char *)&ua
);
315 } else if (((clnt_st
== RPC_PROGVERSMISMATCH
) ||
316 (clnt_st
== RPC_PROGUNAVAIL
) ||
317 (clnt_st
== RPC_TIMEDOUT
)) &&
318 (strcmp(nc
->nc_protofmly
, NC_INET
) == 0)) {
320 * version 3 not available. Try version 2
321 * The assumption here is that the netbuf
322 * is arranged in the sockaddr_in
323 * style for IP cases.
326 struct sockaddr_in
*sa
;
327 struct netbuf remote
;
332 clnt_control(client
, CLGET_SVC_ADDR
, (char *)&remote
);
333 sa
= (struct sockaddr_in
*)(remote
.buf
);
334 protocol
= strcmp(nc
->nc_proto
, NC_TCP
) ? IPPROTO_UDP
:
336 port
= (ushort_t
)pmap_getport(sa
, prog
, ver
, protocol
);
339 /* print s_addr (and port) in host byte order */
340 sa
->sin_addr
.s_addr
= ntohl(sa
->sin_addr
.s_addr
);
341 sprintf(buf
, "%d.%d.%d.%d.%d.%d",
342 (sa
->sin_addr
.s_addr
>> 24) & 0xff,
343 (sa
->sin_addr
.s_addr
>> 16) & 0xff,
344 (sa
->sin_addr
.s_addr
>> 8) & 0xff,
345 (sa
->sin_addr
.s_addr
) & 0xff,
350 rpc_createerr
.cf_stat
= RPC_SUCCESS
;
352 rpc_createerr
.cf_stat
= RPC_SYSTEMERROR
;
355 rpc_createerr
.cf_stat
= RPC_UNKNOWNADDR
;
358 clnt_destroy(client
);
362 clnt_destroy(client
);
367 #define bcmp(s1, s2, len) memcmp(s1, s2, len)
368 #define bcopy(s1, s2, len) memcpy(s2, s1, len)
370 #define MAXALIASES 35
372 static char line
[BUFSIZ
+1];
374 static char *_hosts4_6
[] = { "/etc/inet/hosts", "/etc/inet/ipnodes", 0 };
378 static struct hostent
*__files_gethostent();
381 __files_gethostbyname(char *nam
, sa_family_t af
)
383 register struct hostent
*hp
;
385 char **file
= _hosts4_6
;
388 if ((af
!= AF_INET
) && (af
!= AF_INET6
))
391 for (; *file
!= 0; file
++) {
393 if ((hostf
= fopen(*file
, "r")) == 0)
396 while (hp
= __files_gethostent(hostf
)) {
397 if (hp
->h_addrtype
!= af
)
399 if (strcasecmp(hp
->h_name
, nam
) == 0) {
400 (void) fclose(hostf
);
403 for (cp
= hp
->h_aliases
; cp
!= 0 && *cp
!= 0; cp
++)
404 if (strcasecmp(*cp
, nam
) == 0) {
405 (void) fclose(hostf
);
410 (void) fclose(hostf
);
416 #define isV6Addr(s) (strchr(s, (int)':') != 0)
418 static struct hostent
*
419 __files_gethostent(FILE *hostf
)
422 register char *cp
, **q
;
432 if ((p
= fgets(line
, BUFSIZ
, hostf
)) == NULL
)
444 /* THIS STUFF IS INTERNET SPECIFIC */
445 host
.h_addr_list
= host_addrs
;
455 if (inet_pton(af
, p
, addr
) != 1)
457 bcopy(addr
, host
.h_addr_list
[0], len
);
459 host
.h_addrtype
= af
;
460 while (*cp
== ' ' || *cp
== '\t')
463 q
= host
.h_aliases
= host_aliases
;
468 if (*cp
== ' ' || *cp
== '\t') {
472 if (q
< &host_aliases
[MAXALIASES
- 1])
487 register char *mp
, c
;
490 for (mp
= match
; *mp
; mp
++)