dmake: do not set MAKEFLAGS=k
[unleashed/tickless.git] / usr / src / cmd / fs.d / nfs / lib / nfs_resolve.c
blob0874585f0fb2214ad147b8e0dfba243b239802a7
1 /*
2 * CDDL HEADER START
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]
19 * CDDL HEADER END
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.
31 #include <stdio.h>
32 #include <stdlib.h>
33 #include <alloca.h>
34 #include <signal.h>
35 #include <libintl.h>
36 #include <limits.h>
37 #include <errno.h>
38 #include <sys/types.h>
39 #include <string.h>
40 #include <memory.h>
41 #include <pwd.h>
42 #include <grp.h>
43 #include <door.h>
44 #include <syslog.h>
45 #include <fcntl.h>
46 #include <unistd.h>
47 #include <assert.h>
48 #include <deflt.h>
49 #include <netdir.h>
50 #include <nfs/nfs4.h>
51 #include <nfs/nfssys.h>
52 #include <nfs/nfsid_map.h>
53 #include <nfs/mapid.h>
54 #include <nfs/nfs_sec.h>
55 #include <sys/sdt.h>
56 #include <sys/idmap.h>
57 #include <idmap.h>
58 #include <sys/fs/autofs.h>
59 #include "nfs_resolve.h"
61 void
62 free_knconf(struct knetconfig *k)
64 if (k == NULL)
65 return;
66 free(k->knc_protofmly);
67 free(k->knc_proto);
68 free(k);
71 struct knetconfig *
72 get_knconf(struct netconfig *nconf)
74 struct stat stbuf;
75 struct knetconfig *k = NULL;
76 int len;
78 if (stat(nconf->nc_device, &stbuf) < 0) {
79 syslog(LOG_ERR, "get_knconf: stat %s: %m", nconf->nc_device);
80 return (NULL);
82 k = (struct knetconfig *)malloc(sizeof (*k));
83 if (k == NULL)
84 goto nomem;
85 k->knc_semantics = nconf->nc_semantics;
87 len = strlen(nconf->nc_protofmly);
88 if (len <= 0)
89 goto err_out;
90 k->knc_protofmly = malloc(KNC_STRSIZE);
91 if (k->knc_protofmly == NULL)
92 goto nomem;
93 bzero(k->knc_protofmly, KNC_STRSIZE);
94 bcopy(nconf->nc_protofmly, k->knc_protofmly, len);
96 len = strlen(nconf->nc_proto);
97 if (len <= 0)
98 goto err_out;
99 k->knc_proto = malloc(KNC_STRSIZE);
100 if (k->knc_proto == NULL)
101 goto nomem;
102 bzero(k->knc_proto, KNC_STRSIZE);
103 bcopy(nconf->nc_proto, k->knc_proto, len);
105 k->knc_rdev = stbuf.st_rdev;
107 return (k);
109 nomem:
110 syslog(LOG_ERR, "get_knconf: no memory");
111 err_out:
112 if (k != NULL)
113 (void) free_knconf(k);
114 return (NULL);
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");
135 return (NULL);
138 nametemp = malloc(MAXNETNAMELEN + 1);
139 if (nametemp == NULL) {
140 free(fsl_retp);
141 return (NULL);
143 host2netname(nametemp, host, NULL);
144 namex = calloc(1, strlen(nametemp) + 1);
145 if (namex == NULL) {
146 free(nametemp);
147 free(fsl_retp);
148 return (NULL);
150 strncpy(namex, nametemp, strlen(nametemp));
151 free(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)
159 goto done;
161 fsl_retp->knconf = get_knconf(netconf);
162 if (fsl_retp->knconf == NULL)
163 goto done;
164 fsl_retp->knconf_len = (sizeof (struct knetconfig) +
165 (KNC_STRSIZE * 2));
166 fsl_retp->netbuf_len = (sizeof (struct netbuf) +
167 fsl_retp->addr->maxlen);
168 return (fsl_retp);
169 done:
170 free_nfs4ref_info(fsl_retp);
171 return (NULL);
174 void
175 free_nfs4ref_info(struct nfs_fsl_info *fsl_retp)
177 if (fsl_retp == NULL)
178 return;
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);
185 free(fsl_retp);
188 void
189 cleanup_tli_parms(struct t_bind *tbind, int fd)
191 if (tbind != NULL) {
192 t_free((char *)tbind, T_BIND);
193 tbind = NULL;
195 if (fd >= 0)
196 (void) t_close(fd);
197 fd = -1;
200 struct netbuf *
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)
206 NCONF_HANDLE *nc;
207 struct netconfig *nconf = NULL;
208 int nthtry = FIRST_TRY;
209 struct netbuf *nb;
210 enum clnt_stat cstat;
212 nc = setnetpath();
213 if (nc == NULL)
214 goto done;
215 retry:
216 while (nconf = getnetpath(nc)) {
217 if (nconf->nc_flag & NC_VISIBLE) {
218 if (nthtry == FIRST_TRY) {
219 if ((nconf->nc_semantics ==
220 NC_TPI_COTS_ORD) ||
221 (nconf->nc_semantics ==
222 NC_TPI_COTS)) {
223 if (port == 0)
224 break;
225 if ((strcmp(nconf->nc_protofmly,
226 NC_INET) == 0 ||
227 strcmp(nconf->nc_protofmly,
228 NC_INET6) == 0) &&
229 (strcmp(nconf->nc_proto,
230 NC_TCP) == 0))
231 break;
234 if (nthtry == SECOND_TRY) {
235 if (nconf->nc_semantics ==
236 NC_TPI_CLTS) {
237 if (port == 0)
238 break;
239 if ((strcmp(nconf->nc_protofmly,
240 NC_INET) == 0 ||
241 strcmp(nconf->nc_protofmly,
242 NC_INET6) == 0) &&
243 (strcmp(nconf->nc_proto,
244 NC_UDP) == 0))
245 break;
249 } /* while */
250 if (nconf == NULL) {
251 if (++nthtry <= MNT_PREF_LISTLEN) {
252 endnetpath(nc);
253 if ((nc = setnetpath()) == NULL)
254 goto done;
255 goto retry;
256 } else
257 return (NULL);
258 } else {
259 nb = get_server_addr(host, NFS_PROGRAM, nfsver,
260 nconf, port, NULL, NULL, TRUE, NULL, &cstat);
261 if (cstat != RPC_SUCCESS)
262 goto retry;
264 done:
265 *netconf = nconf;
266 *cstatp = cstat;
267 if (nc)
268 endnetpath(nc);
269 return (nb);
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)
277 if (nconf == NULL) {
278 return (-1);
280 if (direct_to_server == TRUE) {
281 struct nd_hostserv hs;
282 struct nd_addrlist *retaddrs;
283 hs.h_host = hostname;
285 if (port == 0)
286 hs.h_serv = "nfs";
287 else
288 hs.h_serv = NULL;
290 if (netdir_getbyname(nconf, &hs, &retaddrs) != ND_OK) {
291 return (-1);
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);
298 if (port) {
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);
310 if (file_handle) {
311 if (netdir_options(nconf, ND_SET_RESERVEDPORT, fd,
312 NULL) == -1)
313 return (-1);
315 } else if (!file_handle) {
316 if (port) {
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);
327 } else {
328 return (-1);
330 return (1);
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.
338 struct netbuf *
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)
344 int fd = -1;
345 struct t_bind *tbind = NULL;
346 enum clnt_stat cs = RPC_SYSTEMERROR;
347 struct netbuf *nb = NULL;
348 int ret = -1;
350 if (prog == NFS_PROGRAM && vers == NFS_V4)
351 if (strncasecmp(nconf->nc_proto, NC_UDP, strlen(NC_UDP)) == 0)
352 goto done;
354 if ((fd = t_open(nconf->nc_device, O_RDWR, tinfo)) < 0)
355 goto done;
357 if ((tbind = (struct t_bind *)t_alloc(fd, T_BIND, T_ADDR)) == NULL)
358 goto done;
360 if (setup_nb_parms(nconf, tbind, tinfo, hostname, fd, direct_to_server,
361 port, prog, vers, 0) < 0)
362 goto done;
364 nb = (struct netbuf *)malloc(sizeof (struct netbuf));
365 if (nb == NULL) {
366 syslog(LOG_ERR, "no memory\n");
367 goto done;
369 nb->buf = (char *)malloc(tbind->addr.maxlen);
370 if (nb->buf == NULL) {
371 syslog(LOG_ERR, "no memory\n");
372 free(nb);
373 nb = NULL;
374 goto done;
376 (void) memcpy(nb->buf, tbind->addr.buf, tbind->addr.len);
377 nb->len = tbind->addr.len;
378 nb->maxlen = tbind->addr.maxlen;
379 cs = RPC_SUCCESS;
380 done:
381 *cstat = cs;
382 cleanup_tli_parms(tbind, fd);
383 return (nb);