xref: /onnv-gate/usr/src/cmd/fs.d/nfs/mountd/nfs_cmd.c (revision 12393:a4df3ee2f129)
17961SNatalie.Li@Sun.COM /*
27961SNatalie.Li@Sun.COM  * CDDL HEADER START
37961SNatalie.Li@Sun.COM  *
47961SNatalie.Li@Sun.COM  * The contents of this file are subject to the terms of the
57961SNatalie.Li@Sun.COM  * Common Development and Distribution License (the "License").
67961SNatalie.Li@Sun.COM  * You may not use this file except in compliance with the License.
77961SNatalie.Li@Sun.COM  *
87961SNatalie.Li@Sun.COM  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97961SNatalie.Li@Sun.COM  * or http://www.opensolaris.org/os/licensing.
107961SNatalie.Li@Sun.COM  * See the License for the specific language governing permissions
117961SNatalie.Li@Sun.COM  * and limitations under the License.
127961SNatalie.Li@Sun.COM  *
137961SNatalie.Li@Sun.COM  * When distributing Covered Code, include this CDDL HEADER in each
147961SNatalie.Li@Sun.COM  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157961SNatalie.Li@Sun.COM  * If applicable, add the following below this CDDL HEADER, with the
167961SNatalie.Li@Sun.COM  * fields enclosed by brackets "[]" replaced with your own identifying
177961SNatalie.Li@Sun.COM  * information: Portions Copyright [yyyy] [name of copyright owner]
187961SNatalie.Li@Sun.COM  *
197961SNatalie.Li@Sun.COM  * CDDL HEADER END
207961SNatalie.Li@Sun.COM  */
217961SNatalie.Li@Sun.COM 
227961SNatalie.Li@Sun.COM /*
23*12393SJan.Kryl@Sun.COM  * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
247961SNatalie.Li@Sun.COM  */
257961SNatalie.Li@Sun.COM 
267961SNatalie.Li@Sun.COM #include <sys/types.h>
277961SNatalie.Li@Sun.COM #include <rpc/rpc.h>
287961SNatalie.Li@Sun.COM #include <netconfig.h>
297961SNatalie.Li@Sun.COM #include <netdir.h>
307961SNatalie.Li@Sun.COM #include <netinet/in.h>
317961SNatalie.Li@Sun.COM #include <arpa/inet.h>
327961SNatalie.Li@Sun.COM #include <netdb.h>
337961SNatalie.Li@Sun.COM #include <libtsnet.h>
347961SNatalie.Li@Sun.COM #include <nfs/nfssys.h>
357961SNatalie.Li@Sun.COM #include <nfs/export.h>
367961SNatalie.Li@Sun.COM #include <nfs/nfs_cmd.h>
377961SNatalie.Li@Sun.COM #include <door.h>
387961SNatalie.Li@Sun.COM #include <syslog.h>
397961SNatalie.Li@Sun.COM #include <locale.h>
407961SNatalie.Li@Sun.COM #include <strings.h>
417961SNatalie.Li@Sun.COM #include <sharefs/share.h>
427961SNatalie.Li@Sun.COM 
437961SNatalie.Li@Sun.COM extern struct share *findentry(char *);
447961SNatalie.Li@Sun.COM /*
457961SNatalie.Li@Sun.COM  * The following codesets must match what is in libshare_nfs.c until we can
467961SNatalie.Li@Sun.COM  * request them from the kernel.
477961SNatalie.Li@Sun.COM  */
487961SNatalie.Li@Sun.COM char *charopts[] = {
497961SNatalie.Li@Sun.COM 	"euc-cn",
507961SNatalie.Li@Sun.COM 	"euc-jp",
517961SNatalie.Li@Sun.COM 	"euc-jpms",
527961SNatalie.Li@Sun.COM 	"euc-kr",
537961SNatalie.Li@Sun.COM 	"euc-tw",
547961SNatalie.Li@Sun.COM 	"iso8859-1",
557961SNatalie.Li@Sun.COM 	"iso8859-2",
567961SNatalie.Li@Sun.COM 	"iso8859-5",
577961SNatalie.Li@Sun.COM 	"iso8859-6",
587961SNatalie.Li@Sun.COM 	"iso8859-7",
597961SNatalie.Li@Sun.COM 	"iso8859-8",
607961SNatalie.Li@Sun.COM 	"iso8859-9",
617961SNatalie.Li@Sun.COM 	"iso8859-13",
627961SNatalie.Li@Sun.COM 	"iso8859-15",
637961SNatalie.Li@Sun.COM 	"koi8-r",
647961SNatalie.Li@Sun.COM 	NULL
657961SNatalie.Li@Sun.COM };
667961SNatalie.Li@Sun.COM 
677961SNatalie.Li@Sun.COM /*
687961SNatalie.Li@Sun.COM  * nfscmd_err(dp, args, err)
697961SNatalie.Li@Sun.COM  * Return an error for the door call.
707961SNatalie.Li@Sun.COM  */
717961SNatalie.Li@Sun.COM 
727961SNatalie.Li@Sun.COM static void
nfscmd_err(door_desc_t * dp,nfscmd_arg_t * args,int err)737961SNatalie.Li@Sun.COM nfscmd_err(door_desc_t *dp, nfscmd_arg_t *args, int err)
747961SNatalie.Li@Sun.COM {
757961SNatalie.Li@Sun.COM 	nfscmd_res_t res;
767961SNatalie.Li@Sun.COM 
777961SNatalie.Li@Sun.COM 	res.version = NFSCMD_VERS_1;
787961SNatalie.Li@Sun.COM 	res.cmd = NFSCMD_ERROR;
797961SNatalie.Li@Sun.COM 	res.error = err;
807961SNatalie.Li@Sun.COM 	(void) door_return((char *)&res, sizeof (nfscmd_res_t), NULL, 0);
817961SNatalie.Li@Sun.COM 	(void) door_return(NULL, 0, NULL, 0);
827961SNatalie.Li@Sun.COM 	/* NOTREACHED */
837961SNatalie.Li@Sun.COM 
847961SNatalie.Li@Sun.COM }
857961SNatalie.Li@Sun.COM 
867961SNatalie.Li@Sun.COM /*
877961SNatalie.Li@Sun.COM  * charmap_search(netbuf, opts)
887961SNatalie.Li@Sun.COM  *
897961SNatalie.Li@Sun.COM  * Check to see if the address in the netbuf is found in
907961SNatalie.Li@Sun.COM  * a character map spec in the opts option string. Returns the charset
917961SNatalie.Li@Sun.COM  * name if found.
927961SNatalie.Li@Sun.COM  */
937961SNatalie.Li@Sun.COM 
947961SNatalie.Li@Sun.COM static char *
charmap_search(struct netbuf * nbuf,char * opts)957961SNatalie.Li@Sun.COM charmap_search(struct netbuf *nbuf, char *opts)
967961SNatalie.Li@Sun.COM {
977961SNatalie.Li@Sun.COM 	char *copts;
987961SNatalie.Li@Sun.COM 	char *next;
997961SNatalie.Li@Sun.COM 	char *name;
1007961SNatalie.Li@Sun.COM 	char *result = NULL;
1017961SNatalie.Li@Sun.COM 	char *netid;
1027961SNatalie.Li@Sun.COM 	struct netconfig *nconf;
1037961SNatalie.Li@Sun.COM 	struct nd_hostservlist  *hl = NULL;
1047961SNatalie.Li@Sun.COM 	struct sockaddr *sa;
1057961SNatalie.Li@Sun.COM 
1067961SNatalie.Li@Sun.COM 	/* eventually charopts should be dynamically setup */
1077961SNatalie.Li@Sun.COM 	if (charopts == NULL) {
1087961SNatalie.Li@Sun.COM 		free(copts);
1097961SNatalie.Li@Sun.COM 		return (NULL);
1107961SNatalie.Li@Sun.COM 	}
1117961SNatalie.Li@Sun.COM 
1127961SNatalie.Li@Sun.COM 	sa = (struct sockaddr *)nbuf->buf;
1137961SNatalie.Li@Sun.COM 
1147961SNatalie.Li@Sun.COM 	switch (sa->sa_family) {
1157961SNatalie.Li@Sun.COM 	case AF_INET:
1167961SNatalie.Li@Sun.COM 		nconf = getnetconfigent("tcp");
1177961SNatalie.Li@Sun.COM 		break;
1187961SNatalie.Li@Sun.COM 	case AF_INET6:
1197961SNatalie.Li@Sun.COM 		nconf = getnetconfigent("tcp6");
1207961SNatalie.Li@Sun.COM 		break;
1217961SNatalie.Li@Sun.COM 	default:
1227961SNatalie.Li@Sun.COM 		return (NULL);
1237961SNatalie.Li@Sun.COM 	}
1247961SNatalie.Li@Sun.COM 
1257961SNatalie.Li@Sun.COM 	if (nconf == NULL) {
1267961SNatalie.Li@Sun.COM 		return (NULL);
1277961SNatalie.Li@Sun.COM 	}
1287961SNatalie.Li@Sun.COM 
1297961SNatalie.Li@Sun.COM 	/*
1307961SNatalie.Li@Sun.COM 	 * Use the this API instead of the netdir_getbyaddr()
1317961SNatalie.Li@Sun.COM 	 * to avoid service lookup.
1327961SNatalie.Li@Sun.COM 	 */
1337961SNatalie.Li@Sun.COM 	if (__netdir_getbyaddr_nosrv(nconf, &hl, nbuf)) {
1347961SNatalie.Li@Sun.COM 		syslog(LOG_ERR, "netdir: %s\n", netdir_sperror());
1357961SNatalie.Li@Sun.COM 		freenetconfigent(nconf);
1367961SNatalie.Li@Sun.COM 		return (NULL);
1377961SNatalie.Li@Sun.COM 	}
1387961SNatalie.Li@Sun.COM 
1397961SNatalie.Li@Sun.COM 	copts = strdup(opts);
1407961SNatalie.Li@Sun.COM 	if (copts == NULL) {
1417961SNatalie.Li@Sun.COM 		freenetconfigent(nconf);
1427961SNatalie.Li@Sun.COM 		return (NULL);
1437961SNatalie.Li@Sun.COM 	}
1447961SNatalie.Li@Sun.COM 
1457961SNatalie.Li@Sun.COM 	next = copts;
1467961SNatalie.Li@Sun.COM 	while (*next != '\0') {
1477961SNatalie.Li@Sun.COM 		char *val;
1487961SNatalie.Li@Sun.COM 		name = next;
1497961SNatalie.Li@Sun.COM 		if (getsubopt(&next, charopts, &val) >= 0) {
1507961SNatalie.Li@Sun.COM 			char *cp;
1517961SNatalie.Li@Sun.COM 			/*
1527961SNatalie.Li@Sun.COM 			 * name will have the whole opt and val the value. Set
1537961SNatalie.Li@Sun.COM 			 * the '=' to '\0' and we have the charmap in name and
1547961SNatalie.Li@Sun.COM 			 * the access list in val.
1557961SNatalie.Li@Sun.COM 			 */
1567961SNatalie.Li@Sun.COM 			cp = strchr(name, '=');
1577961SNatalie.Li@Sun.COM 			if (cp != NULL)
1587961SNatalie.Li@Sun.COM 				*cp = '\0';
159*12393SJan.Kryl@Sun.COM 			if (in_access_list(NULL, &nbuf, &hl, val)) {
1607961SNatalie.Li@Sun.COM 				result = name;
1617961SNatalie.Li@Sun.COM 				break;
1627961SNatalie.Li@Sun.COM 			}
1637961SNatalie.Li@Sun.COM 		}
1647961SNatalie.Li@Sun.COM 	}
1657961SNatalie.Li@Sun.COM 
1667961SNatalie.Li@Sun.COM 	if (result != NULL)
1677961SNatalie.Li@Sun.COM 		result = strdup(result);
1687961SNatalie.Li@Sun.COM 
1697961SNatalie.Li@Sun.COM 	free(copts);
1707961SNatalie.Li@Sun.COM 	freenetconfigent(nconf);
1717961SNatalie.Li@Sun.COM 
1727961SNatalie.Li@Sun.COM 	return (result);
1737961SNatalie.Li@Sun.COM }
1747961SNatalie.Li@Sun.COM 
1757961SNatalie.Li@Sun.COM /*
1767961SNatalie.Li@Sun.COM  * nfscmd_charmap_lookup(door, args)
1777961SNatalie.Li@Sun.COM  *
1787961SNatalie.Li@Sun.COM  * Check to see if there is a translation requested for the path
1797961SNatalie.Li@Sun.COM  * specified in the request. If there is, return the charset name.
1807961SNatalie.Li@Sun.COM  */
1817961SNatalie.Li@Sun.COM 
1827961SNatalie.Li@Sun.COM static void
nfscmd_charmap_lookup(door_desc_t * dp,nfscmd_arg_t * args)1837961SNatalie.Li@Sun.COM nfscmd_charmap_lookup(door_desc_t *dp, nfscmd_arg_t *args)
1847961SNatalie.Li@Sun.COM {
1857961SNatalie.Li@Sun.COM 	nfscmd_res_t res;
1867961SNatalie.Li@Sun.COM 	struct netbuf nb;
1877961SNatalie.Li@Sun.COM 	struct sockaddr sa;
1887961SNatalie.Li@Sun.COM 	struct share *sh = NULL;
1897961SNatalie.Li@Sun.COM 	char *opts;
1907961SNatalie.Li@Sun.COM 	char *name;
1917961SNatalie.Li@Sun.COM 
1927961SNatalie.Li@Sun.COM 	memset(&res, '\0', sizeof (res));
1937961SNatalie.Li@Sun.COM 	res.version = NFSCMD_VERS_1;
1947961SNatalie.Li@Sun.COM 	res.cmd = NFSCMD_CHARMAP_LOOKUP;
1957961SNatalie.Li@Sun.COM 
1967961SNatalie.Li@Sun.COM 	sh = findentry(args->arg.charmap.path);
1977961SNatalie.Li@Sun.COM 
1987961SNatalie.Li@Sun.COM 	if (sh != NULL) {
1997961SNatalie.Li@Sun.COM 		nb.len = nb.maxlen = sizeof (struct sockaddr);
2007961SNatalie.Li@Sun.COM 		nb.buf = (char *)&sa;
2017961SNatalie.Li@Sun.COM 
2027961SNatalie.Li@Sun.COM 		sa = args->arg.charmap.addr;
2037961SNatalie.Li@Sun.COM 
2047961SNatalie.Li@Sun.COM 		name = charmap_search(&nb, sh->sh_opts);
2057961SNatalie.Li@Sun.COM 		if (name != NULL) {
2067961SNatalie.Li@Sun.COM 			strcpy(res.result.charmap.codeset, name);
2077961SNatalie.Li@Sun.COM 			res.result.charmap.apply = B_TRUE;
2087961SNatalie.Li@Sun.COM 			res.error = NFSCMD_ERR_SUCCESS;
2097961SNatalie.Li@Sun.COM 			free(name);
2107961SNatalie.Li@Sun.COM 		} else {
2117961SNatalie.Li@Sun.COM 			res.result.charmap.apply = B_FALSE;
2127961SNatalie.Li@Sun.COM 			res.error = NFSCMD_ERR_NOTFOUND;
2137961SNatalie.Li@Sun.COM 		}
2147961SNatalie.Li@Sun.COM 		sharefree(sh);
2157961SNatalie.Li@Sun.COM 	} else {
2167961SNatalie.Li@Sun.COM 		res.error = NFSCMD_ERR_NOTFOUND;
2177961SNatalie.Li@Sun.COM 	}
2187961SNatalie.Li@Sun.COM 
2197961SNatalie.Li@Sun.COM 	(void) door_return((char *)&res, sizeof (nfscmd_res_t), NULL, 0);
2207961SNatalie.Li@Sun.COM 	(void) door_return(NULL, 0, NULL, 0);
2217961SNatalie.Li@Sun.COM 	/* NOTREACHED */
2227961SNatalie.Li@Sun.COM }
2237961SNatalie.Li@Sun.COM 
2247961SNatalie.Li@Sun.COM /*
2257961SNatalie.Li@Sun.COM  * nfscmd_ver_1(door, args, size)
2267961SNatalie.Li@Sun.COM  *
2277961SNatalie.Li@Sun.COM  * Version 1 of the door command processor for nfs cmds.
2287961SNatalie.Li@Sun.COM  */
2297961SNatalie.Li@Sun.COM 
2307961SNatalie.Li@Sun.COM static void
nfscmd_vers_1(door_desc_t * dp,nfscmd_arg_t * args,size_t size)2317961SNatalie.Li@Sun.COM nfscmd_vers_1(door_desc_t *dp, nfscmd_arg_t *args, size_t size)
2327961SNatalie.Li@Sun.COM {
2337961SNatalie.Li@Sun.COM 	switch (args->cmd) {
2347961SNatalie.Li@Sun.COM 	case NFSCMD_CHARMAP_LOOKUP:
2357961SNatalie.Li@Sun.COM 		nfscmd_charmap_lookup(dp, args);
2367961SNatalie.Li@Sun.COM 		break;
2377961SNatalie.Li@Sun.COM 	default:
2387961SNatalie.Li@Sun.COM 		nfscmd_err(dp, args, NFSCMD_ERR_BADCMD);
2397961SNatalie.Li@Sun.COM 		break;
2407961SNatalie.Li@Sun.COM 	}
2417961SNatalie.Li@Sun.COM }
2427961SNatalie.Li@Sun.COM 
2437961SNatalie.Li@Sun.COM /*
2447961SNatalie.Li@Sun.COM  * nfscmd_func(cookie, dataptr, size, door, ndesc)
2457961SNatalie.Li@Sun.COM  *
2467961SNatalie.Li@Sun.COM  * The function called by the door thread for processing
2477961SNatalie.Li@Sun.COM  * nfscmd type commands.
2487961SNatalie.Li@Sun.COM  */
2497961SNatalie.Li@Sun.COM 
2507961SNatalie.Li@Sun.COM void
nfscmd_func(void * cookie,char * dataptr,size_t arg_size,door_desc_t * dp,uint_t n_desc)2517961SNatalie.Li@Sun.COM nfscmd_func(void *cookie, char *dataptr, size_t arg_size,
2527961SNatalie.Li@Sun.COM 	door_desc_t *dp, uint_t n_desc)
2537961SNatalie.Li@Sun.COM {
2547961SNatalie.Li@Sun.COM 	nfscmd_arg_t	*args;
2557961SNatalie.Li@Sun.COM 
2567961SNatalie.Li@Sun.COM 	args = (nfscmd_arg_t *)dataptr;
2577961SNatalie.Li@Sun.COM 
2587961SNatalie.Li@Sun.COM 	switch (args->version) {
2597961SNatalie.Li@Sun.COM 	case NFSCMD_VERS_1:
2607961SNatalie.Li@Sun.COM 		nfscmd_vers_1(dp, args, arg_size);
2617961SNatalie.Li@Sun.COM 		break;
2627961SNatalie.Li@Sun.COM 	default:
2637961SNatalie.Li@Sun.COM 		syslog(LOG_ERR, gettext("Invalid nfscmd version"));
2647961SNatalie.Li@Sun.COM 		break;
2657961SNatalie.Li@Sun.COM 	}
2667961SNatalie.Li@Sun.COM 
2677961SNatalie.Li@Sun.COM 	(void) door_return((caddr_t)args, sizeof (nfscmd_res_t), NULL, 0);
2687961SNatalie.Li@Sun.COM 	(void) door_return(NULL, 0, NULL, 0);
2697961SNatalie.Li@Sun.COM 	/* NOTREACHED */
2707961SNatalie.Li@Sun.COM 
2717961SNatalie.Li@Sun.COM }
272