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
)
66 free(k
->knc_protofmly
);
72 get_knconf(struct netconfig
*nconf
)
75 struct knetconfig
*k
= NULL
;
78 if (stat(nconf
->nc_device
, &stbuf
) < 0) {
79 syslog(LOG_ERR
, "get_knconf: stat %s: %m", nconf
->nc_device
);
82 k
= (struct knetconfig
*)malloc(sizeof (*k
));
85 k
->knc_semantics
= nconf
->nc_semantics
;
87 len
= strlen(nconf
->nc_protofmly
);
90 k
->knc_protofmly
= malloc(KNC_STRSIZE
);
91 if (k
->knc_protofmly
== NULL
)
93 bzero(k
->knc_protofmly
, KNC_STRSIZE
);
94 bcopy(nconf
->nc_protofmly
, k
->knc_protofmly
, len
);
96 len
= strlen(nconf
->nc_proto
);
99 k
->knc_proto
= malloc(KNC_STRSIZE
);
100 if (k
->knc_proto
== NULL
)
102 bzero(k
->knc_proto
, KNC_STRSIZE
);
103 bcopy(nconf
->nc_proto
, k
->knc_proto
, len
);
105 k
->knc_rdev
= stbuf
.st_rdev
;
110 syslog(LOG_ERR
, "get_knconf: no memory");
113 (void) free_knconf(k
);
118 * Get the information needed for an NFSv4.x referral. This
119 * information includes the netbuf, netname and knconfig.
121 struct nfs_fsl_info
*
122 get_nfs4ref_info(char *host
, int port
, int nfsver
)
124 char netname
[MAXNETNAMELEN
+ 1];
125 enum clnt_stat cstat
;
126 struct nfs_fsl_info
*fsl_retp
= NULL
;
127 struct netconfig
*netconf
= NULL
;
128 char *nametemp
, *namex
= NULL
;
129 struct netbuf
*nb
= NULL
;
130 NCONF_HANDLE
*nc
= NULL
;
132 fsl_retp
= calloc(1, sizeof (struct nfs_fsl_info
));
133 if (fsl_retp
== NULL
) {
134 syslog(LOG_ERR
, "get_nfs4ref_info: no memory\n");
138 nametemp
= malloc(MAXNETNAMELEN
+ 1);
139 if (nametemp
== NULL
) {
143 host2netname(nametemp
, host
, NULL
);
144 namex
= calloc(1, strlen(nametemp
) + 1);
150 strncpy(namex
, nametemp
, strlen(nametemp
));
152 fsl_retp
->netname
= namex
;
153 fsl_retp
->netnm_len
= strlen(namex
) + 1;
155 fsl_retp
->addr
= resolve_netconf(host
, NFS_PROGRAM
, nfsver
,
156 &netconf
, port
, NULL
, NULL
, TRUE
, NULL
, &cstat
);
158 if (netconf
== NULL
|| fsl_retp
->addr
== NULL
)
161 fsl_retp
->knconf
= get_knconf(netconf
);
162 if (fsl_retp
->knconf
== NULL
)
164 fsl_retp
->knconf_len
= (sizeof (struct knetconfig
) +
166 fsl_retp
->netbuf_len
= (sizeof (struct netbuf
) +
167 fsl_retp
->addr
->maxlen
);
170 free_nfs4ref_info(fsl_retp
);
175 free_nfs4ref_info(struct nfs_fsl_info
*fsl_retp
)
177 if (fsl_retp
== NULL
)
179 free_knconf(fsl_retp
->knconf
);
180 free(fsl_retp
->netname
);
181 if (fsl_retp
->addr
!= NULL
) {
182 free(fsl_retp
->addr
->buf
);
183 free(fsl_retp
->addr
);
189 cleanup_tli_parms(struct t_bind
*tbind
, int fd
)
192 t_free((char *)tbind
, T_BIND
);
201 resolve_netconf(char *host
, rpcprog_t prog
, rpcvers_t nfsver
,
202 struct netconfig
**netconf
, ushort_t port
,
203 struct t_info
*tinfo
, caddr_t
*fhp
, bool_t direct_to_server
,
204 char *fspath
, enum clnt_stat
*cstatp
)
207 struct netconfig
*nconf
= NULL
;
208 int nthtry
= FIRST_TRY
;
210 enum clnt_stat cstat
;
216 while (nconf
= getnetpath(nc
)) {
217 if (nconf
->nc_flag
& NC_VISIBLE
) {
218 if (nthtry
== FIRST_TRY
) {
219 if ((nconf
->nc_semantics
==
221 (nconf
->nc_semantics
==
225 if ((strcmp(nconf
->nc_protofmly
,
227 strcmp(nconf
->nc_protofmly
,
229 (strcmp(nconf
->nc_proto
,
234 if (nthtry
== SECOND_TRY
) {
235 if (nconf
->nc_semantics
==
239 if ((strcmp(nconf
->nc_protofmly
,
241 strcmp(nconf
->nc_protofmly
,
243 (strcmp(nconf
->nc_proto
,
251 if (++nthtry
<= MNT_PREF_LISTLEN
) {
253 if ((nc
= setnetpath()) == NULL
)
259 nb
= get_server_addr(host
, NFS_PROGRAM
, nfsver
,
260 nconf
, port
, NULL
, NULL
, TRUE
, NULL
, &cstat
);
261 if (cstat
!= RPC_SUCCESS
)
273 setup_nb_parms(struct netconfig
*nconf
, struct t_bind
*tbind
,
274 struct t_info
*tinfo
, char *hostname
, int fd
, bool_t direct_to_server
,
275 ushort_t port
, rpcprog_t prog
, rpcvers_t vers
, bool_t file_handle
)
280 if (direct_to_server
== TRUE
) {
281 struct nd_hostserv hs
;
282 struct nd_addrlist
*retaddrs
;
283 hs
.h_host
= hostname
;
290 if (netdir_getbyname(nconf
, &hs
, &retaddrs
) != ND_OK
) {
293 memcpy(tbind
->addr
.buf
, retaddrs
->n_addrs
->buf
,
294 retaddrs
->n_addrs
->len
);
295 tbind
->addr
.len
= retaddrs
->n_addrs
->len
;
296 tbind
->addr
.maxlen
= retaddrs
->n_addrs
->maxlen
;
297 netdir_free((void *)retaddrs
, ND_ADDRLIST
);
299 /* LINTED pointer alignment */
300 if (strcmp(nconf
->nc_protofmly
, NC_INET
) == 0)
301 ((struct sockaddr_in
*)
302 tbind
->addr
.buf
)->sin_port
=
303 htons((ushort_t
)port
);
304 else if (strcmp(nconf
->nc_protofmly
, NC_INET6
) == 0)
305 ((struct sockaddr_in6
*)
306 tbind
->addr
.buf
)->sin6_port
=
307 htons((ushort_t
)port
);
311 if (netdir_options(nconf
, ND_SET_RESERVEDPORT
, fd
,
315 } else if (!file_handle
) {
317 /* LINTED pointer alignment */
318 if (strcmp(nconf
->nc_protofmly
, NC_INET
) == 0)
319 ((struct sockaddr_in
*)
320 tbind
->addr
.buf
)->sin_port
=
321 htons((ushort_t
)port
);
322 else if (strcmp(nconf
->nc_protofmly
, NC_INET6
) == 0)
323 ((struct sockaddr_in6
*)
324 tbind
->addr
.buf
)->sin6_port
=
325 htons((ushort_t
)port
);
334 * Sets up TLI interface and finds the address withe netdir_getbyname().
335 * returns the address returned from the call.
336 * Caller frees up the memory allocated here.
339 get_server_addr(char *hostname
, rpcprog_t prog
, rpcvers_t vers
,
340 struct netconfig
*nconf
, ushort_t port
,
341 struct t_info
*tinfo
, caddr_t
*fhp
, bool_t direct_to_server
,
342 char *fspath
, enum clnt_stat
*cstat
)
345 struct t_bind
*tbind
= NULL
;
346 enum clnt_stat cs
= RPC_SYSTEMERROR
;
347 struct netbuf
*nb
= NULL
;
350 if (prog
== NFS_PROGRAM
&& vers
== NFS_V4
)
351 if (strncasecmp(nconf
->nc_proto
, NC_UDP
, strlen(NC_UDP
)) == 0)
354 if ((fd
= t_open(nconf
->nc_device
, O_RDWR
, tinfo
)) < 0)
357 if ((tbind
= (struct t_bind
*)t_alloc(fd
, T_BIND
, T_ADDR
)) == NULL
)
360 if (setup_nb_parms(nconf
, tbind
, tinfo
, hostname
, fd
, direct_to_server
,
361 port
, prog
, vers
, 0) < 0)
364 nb
= (struct netbuf
*)malloc(sizeof (struct netbuf
));
366 syslog(LOG_ERR
, "no memory\n");
369 nb
->buf
= (char *)malloc(tbind
->addr
.maxlen
);
370 if (nb
->buf
== NULL
) {
371 syslog(LOG_ERR
, "no memory\n");
376 (void) memcpy(nb
->buf
, tbind
->addr
.buf
, tbind
->addr
.len
);
377 nb
->len
= tbind
->addr
.len
;
378 nb
->maxlen
= tbind
->addr
.maxlen
;
382 cleanup_tli_parms(tbind
, fd
);