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