Home | History | Annotate | Download | only in dservd
      1 /*
      2  * CDDL HEADER START
      3  *
      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.
      7  *
      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.
     12  *
     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]
     18  *
     19  * CDDL HEADER END
     20  */
     21 /*
     22  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
     23  * Use is subject to license terms.
     24  */
     25 
     26 #include <nfs/nfs.h>
     27 #include <nfs/nfs4.h>
     28 #include <libintl.h>
     29 #include <sys/param.h>
     30 #include <sys/tiuser.h>
     31 #include <rpc/svc.h>
     32 #include "nfs_tbind.h"
     33 #include <nfs/nfssys.h>
     34 #include <libdserv.h>
     35 #include <dservd.h>
     36 
     37 #define	PNFSCTLMDS	104000
     38 #define	PNFSCTLMDS_V1	1
     39 
     40 #ifndef TEXT_DOMAIN
     41 #define	TEXT_DOMAIN	"SUNW_OST_OSCMD"
     42 #endif /* TEXT_DOMAIN */
     43 
     44 /*
     45  * The following are all globals used by routines in nfs_tbind.c.
     46  */
     47 size_t	end_listen_fds;		/* used by conn_close_oldest() */
     48 size_t	num_fds = 0;		/* used by multiple routines */
     49 int	listen_backlog = 32;	/* used by bind_to_{provider,proto}() */
     50 int	num_servers;		/* used by cots_listen_event() */
     51 int	(*Mysvc)(int, struct netbuf, struct netconfig *) = NULL;
     52 				/* used by cots_listen_event() */
     53 int	max_conns_allowed = -1;	/* used by cots_listen_event() */
     54 
     55 #define	MAXHOSTNAMELEN 64
     56 
     57 static dserv_handle_t *do_all_handle;
     58 
     59 static char *
     60 get_uaddr(struct netconfig *nconf, struct netbuf *nb)
     61 {
     62 	struct nfs_svc_args nsa;
     63 	char *ua, *ua2, *mua = NULL;
     64 	char me[MAXHOSTNAMELEN];
     65 	struct nd_addrlist *nas;
     66 	struct nd_hostserv hs;
     67 	struct nd_mergearg ma;
     68 
     69 	ua = taddr2uaddr(nconf, nb);
     70 
     71 	if (ua == NULL) {
     72 		return (NULL);
     73 	}
     74 
     75 	gethostname(me, MAXHOSTNAMELEN);
     76 
     77 	hs.h_host = me;
     78 	hs.h_serv = "nfs";
     79 	if (netdir_getbyname(nconf, &hs, &nas)) {
     80 		return (NULL);
     81 	}
     82 
     83 	ua2 = taddr2uaddr(nconf, nas->n_addrs);
     84 
     85 	if (ua2 == NULL) {
     86 		return (NULL);
     87 	}
     88 
     89 	ma.s_uaddr = ua;
     90 	ma.c_uaddr = ua2;
     91 	ma.m_uaddr = NULL;
     92 
     93 	if (netdir_options(nconf, ND_MERGEADDR, 0, (char *)&ma)) {
     94 		return (NULL);
     95 	}
     96 
     97 	mua = ma.m_uaddr;
     98 	return (mua);
     99 }
    100 
    101 /*
    102  * dserv_service is called either with a command of
    103  * NFS4_KRPC_START or SETPORT. Any other value is
    104  * invalid.
    105  */
    106 static int
    107 dserv_service(int fd, struct netbuf *addrmask, struct netconfig *nconf,
    108     int cmd, struct netbuf *addr)
    109 {
    110 	dserv_svc_args_t svcargs;
    111 	dserv_setport_args_t setportargs;
    112 	char *uaddr;
    113 	int result;
    114 
    115 	switch (cmd) {
    116 	case NFS4_KRPC_START:
    117 		svcargs.fd = fd;
    118 		bcopy(addr->buf, &svcargs.sin, addr->len);
    119 		(void) strlcpy(svcargs.netid,
    120 		    nconf->nc_netid, sizeof (svcargs.netid));
    121 		uaddr = get_uaddr(nconf, addr);
    122 		if (uaddr != NULL) {
    123 			dserv_log(do_all_handle, LOG_INFO,
    124 			    gettext("NFS4_KRPC_START: %s"), uaddr);
    125 			free(uaddr);
    126 		}
    127 		result = dserv_kmod_svc(do_all_handle, &svcargs);
    128 		break;
    129 
    130 	case NFS4_SETPORT:
    131 		uaddr = get_uaddr(nconf, addr);
    132 		if (uaddr == NULL) {
    133 			dserv_log(do_all_handle, LOG_INFO,
    134 			    gettext("NFS4_SETPORT: get_uaddr failed"));
    135 			return (1);
    136 		}
    137 		(void) strlcpy(setportargs.dsa_uaddr, uaddr,
    138 		    sizeof (setportargs.dsa_uaddr));
    139 		(void) strlcpy(setportargs.dsa_proto, nconf->nc_proto,
    140 		    sizeof (setportargs.dsa_proto));
    141 		(void) strlcpy(setportargs.dsa_name, getenv("SMF_FMRI"),
    142 		    sizeof (setportargs.dsa_name));
    143 
    144 		result = dserv_kmod_setport(do_all_handle, &setportargs);
    145 
    146 		if (result == 0)
    147 			result = dserv_kmod_reportavail(do_all_handle);
    148 		break;
    149 
    150 	default:
    151 		dserv_log(do_all_handle, LOG_ERR,
    152 		    gettext("bad cmd: %d"), cmd);
    153 		return (1);
    154 	}
    155 
    156 	if (result != 0) {
    157 		dserv_log(do_all_handle, LOG_ERR, NULL);
    158 		return (1); /* XXX errno? */
    159 	}
    160 
    161 	return (0);
    162 }
    163 
    164 void
    165 dserv_daemon(dserv_handle_t *handle)
    166 {
    167 	struct svcpool_args dserv_svcpool;
    168 	struct protob dservproto;
    169 
    170 	bzero(&dserv_svcpool, sizeof (dserv_svcpool));
    171 
    172 	dserv_svcpool.id = UNIQUE_SVCPOOL_ID;
    173 
    174 	if (_nfssys(SVCPOOL_CREATE, &dserv_svcpool)) {
    175 		dserv_log(handle, LOG_ERR,
    176 		    gettext("SVCPOOL_CREATE failed: %m"));
    177 		exit(1);
    178 	}
    179 
    180 	dserv_set_pool_id(handle, dserv_svcpool.id);
    181 
    182 	if (svcwait(dserv_svcpool.id)) {
    183 		dserv_log(handle, LOG_ERR,
    184 		    gettext("svcwait(DSERV_SVCPOOL_ID) failed: %m"));
    185 		exit(1);
    186 	}
    187 
    188 	dservproto.serv = "DSERV";
    189 	dservproto.versmin = PNFSCTLMDS_V1;
    190 	dservproto.versmax = PNFSCTLMDS_V1;
    191 	dservproto.program = PNFSCTLMDS;
    192 	dservproto.flags = PROTOB_NO_REGISTER;
    193 	dservproto.next = NULL;
    194 
    195 	/*
    196 	 * We love globals!
    197 	 */
    198 	Mysvc4 = dserv_service;
    199 	do_all_handle = handle;
    200 	if (do_all(&dservproto, NULL, 0) == -1) {
    201 		dserv_log(handle, LOG_ERR,
    202 		    gettext("do_all(): %m"));
    203 		exit(1);
    204 	}
    205 	if (num_fds == 0) {
    206 		dserv_log(handle, LOG_ERR,
    207 		    gettext("Could not start DSERV service for any protocol"));
    208 		exit(1);
    209 	}
    210 
    211 	end_listen_fds = num_fds;
    212 	poll_for_action();
    213 
    214 	dserv_log(handle, LOG_INFO,
    215 	    gettext("I am shutting down now"));
    216 
    217 	exit(1);
    218 }
    219