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