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]
22 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
28 * Helper routines for nfsmapid and autod daemon
29 * to translate hostname to IP address and Netinfo.
38 #include <sys/types.h>
51 #include <nfs/nfssys.h>
52 #include <nfs/nfsid_map.h>
53 #include <nfs/mapid.h>
54 #include <nfs/nfs_sec.h>
56 #include <sys/idmap.h>
58 #include <sys/fs/autofs.h>
59 #include "nfs_resolve.h"
62 free_knconf(struct knetconfig
*k
)
67 free(k
->knc_protofmly
);
74 get_knconf(struct netconfig
*nconf
)
77 struct knetconfig
*k
= NULL
;
80 if (stat(nconf
->nc_device
, &stbuf
) < 0) {
81 syslog(LOG_ERR
, "get_knconf: stat %s: %m", nconf
->nc_device
);
84 k
= (struct knetconfig
*)malloc(sizeof (*k
));
87 k
->knc_semantics
= nconf
->nc_semantics
;
89 len
= strlen(nconf
->nc_protofmly
);
92 k
->knc_protofmly
= malloc(KNC_STRSIZE
);
93 if (k
->knc_protofmly
== NULL
)
95 bzero(k
->knc_protofmly
, KNC_STRSIZE
);
96 bcopy(nconf
->nc_protofmly
, k
->knc_protofmly
, len
);
98 len
= strlen(nconf
->nc_proto
);
101 k
->knc_proto
= malloc(KNC_STRSIZE
);
102 if (k
->knc_proto
== NULL
)
104 bzero(k
->knc_proto
, KNC_STRSIZE
);
105 bcopy(nconf
->nc_proto
, k
->knc_proto
, len
);
107 k
->knc_rdev
= stbuf
.st_rdev
;
112 syslog(LOG_ERR
, "get_knconf: no memory");
115 (void) free_knconf(k
);
120 * Get the information needed for an NFSv4.x referral. This
121 * information includes the netbuf, netname and knconfig.
123 struct nfs_fsl_info
*
124 get_nfs4ref_info(char *host
, int port
, int nfsver
)
126 char netname
[MAXNETNAMELEN
+ 1];
127 enum clnt_stat cstat
;
128 struct nfs_fsl_info
*fsl_retp
= NULL
;
129 struct netconfig
*netconf
= NULL
;
130 char *nametemp
, *namex
= NULL
;
131 struct netbuf
*nb
= NULL
;
132 NCONF_HANDLE
*nc
= NULL
;
134 fsl_retp
= calloc(1, sizeof (struct nfs_fsl_info
));
135 if (fsl_retp
== NULL
) {
136 syslog(LOG_ERR
, "get_nfs4ref_info: no memory\n");
140 nametemp
= malloc(MAXNETNAMELEN
+ 1);
141 if (nametemp
== NULL
) {
145 host2netname(nametemp
, host
, NULL
);
146 namex
= calloc(1, strlen(nametemp
) + 1);
152 strncpy(namex
, nametemp
, strlen(nametemp
));
154 fsl_retp
->netname
= namex
;
155 fsl_retp
->netnm_len
= strlen(namex
) + 1;
157 fsl_retp
->addr
= resolve_netconf(host
, NFS_PROGRAM
, nfsver
,
158 &netconf
, port
, NULL
, NULL
, TRUE
, NULL
, &cstat
);
160 if (netconf
== NULL
|| fsl_retp
->addr
== NULL
)
163 fsl_retp
->knconf
= get_knconf(netconf
);
164 if (fsl_retp
->knconf
== NULL
)
166 fsl_retp
->knconf_len
= (sizeof (struct knetconfig
) +
168 fsl_retp
->netbuf_len
= (sizeof (struct netbuf
) +
169 fsl_retp
->addr
->maxlen
);
172 free_nfs4ref_info(fsl_retp
);
177 free_nfs4ref_info(struct nfs_fsl_info
*fsl_retp
)
179 if (fsl_retp
== NULL
)
181 free_knconf(fsl_retp
->knconf
);
182 free(fsl_retp
->netname
);
183 if (fsl_retp
->addr
!= NULL
) {
184 free(fsl_retp
->addr
->buf
);
185 free(fsl_retp
->addr
);
191 cleanup_tli_parms(struct t_bind
*tbind
, int fd
)
194 t_free((char *)tbind
, T_BIND
);
203 resolve_netconf(char *host
, rpcprog_t prog
, rpcvers_t nfsver
,
204 struct netconfig
**netconf
, ushort_t port
,
205 struct t_info
*tinfo
, caddr_t
*fhp
, bool_t direct_to_server
,
206 char *fspath
, enum clnt_stat
*cstatp
)
209 struct netconfig
*nconf
= NULL
;
210 int nthtry
= FIRST_TRY
;
212 enum clnt_stat cstat
;
218 while (nconf
= getnetpath(nc
)) {
219 if (nconf
->nc_flag
& NC_VISIBLE
) {
220 if (nthtry
== FIRST_TRY
) {
221 if ((nconf
->nc_semantics
==
223 (nconf
->nc_semantics
==
227 if ((strcmp(nconf
->nc_protofmly
,
229 strcmp(nconf
->nc_protofmly
,
231 (strcmp(nconf
->nc_proto
,
236 if (nthtry
== SECOND_TRY
) {
237 if (nconf
->nc_semantics
==
241 if ((strcmp(nconf
->nc_protofmly
,
243 strcmp(nconf
->nc_protofmly
,
245 (strcmp(nconf
->nc_proto
,
253 if (++nthtry
<= MNT_PREF_LISTLEN
) {
255 if ((nc
= setnetpath()) == NULL
)
261 nb
= get_server_addr(host
, NFS_PROGRAM
, nfsver
,
262 nconf
, port
, NULL
, NULL
, TRUE
, NULL
, &cstat
);
263 if (cstat
!= RPC_SUCCESS
)
275 setup_nb_parms(struct netconfig
*nconf
, struct t_bind
*tbind
,
276 struct t_info
*tinfo
, char *hostname
, int fd
, bool_t direct_to_server
,
277 ushort_t port
, rpcprog_t prog
, rpcvers_t vers
, bool_t file_handle
)
282 if (direct_to_server
== TRUE
) {
283 struct nd_hostserv hs
;
284 struct nd_addrlist
*retaddrs
;
285 hs
.h_host
= hostname
;
292 if (netdir_getbyname(nconf
, &hs
, &retaddrs
) != ND_OK
) {
295 memcpy(tbind
->addr
.buf
, retaddrs
->n_addrs
->buf
,
296 retaddrs
->n_addrs
->len
);
297 tbind
->addr
.len
= retaddrs
->n_addrs
->len
;
298 tbind
->addr
.maxlen
= retaddrs
->n_addrs
->maxlen
;
299 netdir_free((void *)retaddrs
, ND_ADDRLIST
);
301 /* LINTED pointer alignment */
302 if (strcmp(nconf
->nc_protofmly
, NC_INET
) == NULL
)
303 ((struct sockaddr_in
*)
304 tbind
->addr
.buf
)->sin_port
=
305 htons((ushort_t
)port
);
306 else if (strcmp(nconf
->nc_protofmly
, NC_INET6
) == NULL
)
307 ((struct sockaddr_in6
*)
308 tbind
->addr
.buf
)->sin6_port
=
309 htons((ushort_t
)port
);
313 if (netdir_options(nconf
, ND_SET_RESERVEDPORT
, fd
,
317 } else if (!file_handle
) {
319 /* LINTED pointer alignment */
320 if (strcmp(nconf
->nc_protofmly
, NC_INET
) == NULL
)
321 ((struct sockaddr_in
*)
322 tbind
->addr
.buf
)->sin_port
=
323 htons((ushort_t
)port
);
324 else if (strcmp(nconf
->nc_protofmly
, NC_INET6
) == NULL
)
325 ((struct sockaddr_in6
*)
326 tbind
->addr
.buf
)->sin6_port
=
327 htons((ushort_t
)port
);
336 * Sets up TLI interface and finds the address withe netdir_getbyname().
337 * returns the address returned from the call.
338 * Caller frees up the memory allocated here.
341 get_server_addr(char *hostname
, rpcprog_t prog
, rpcvers_t vers
,
342 struct netconfig
*nconf
, ushort_t port
,
343 struct t_info
*tinfo
, caddr_t
*fhp
, bool_t direct_to_server
,
344 char *fspath
, enum clnt_stat
*cstat
)
347 struct t_bind
*tbind
= NULL
;
348 enum clnt_stat cs
= RPC_SYSTEMERROR
;
349 struct netbuf
*nb
= NULL
;
352 if (prog
== NFS_PROGRAM
&& vers
== NFS_V4
)
353 if (strncasecmp(nconf
->nc_proto
, NC_UDP
, strlen(NC_UDP
)) == 0)
356 if ((fd
= t_open(nconf
->nc_device
, O_RDWR
, tinfo
)) < 0)
359 if ((tbind
= (struct t_bind
*)t_alloc(fd
, T_BIND
, T_ADDR
)) == NULL
)
362 if (setup_nb_parms(nconf
, tbind
, tinfo
, hostname
, fd
, direct_to_server
,
363 port
, prog
, vers
, 0) < 0)
366 nb
= (struct netbuf
*)malloc(sizeof (struct netbuf
));
368 syslog(LOG_ERR
, "no memory\n");
371 nb
->buf
= (char *)malloc(tbind
->addr
.maxlen
);
372 if (nb
->buf
== NULL
) {
373 syslog(LOG_ERR
, "no memory\n");
378 (void) memcpy(nb
->buf
, tbind
->addr
.buf
, tbind
->addr
.len
);
379 nb
->len
= tbind
->addr
.len
;
380 nb
->maxlen
= tbind
->addr
.maxlen
;
384 cleanup_tli_parms(tbind
, fd
);