xref: /onnv-gate/usr/src/lib/libshare/autofs/libshare_autofs.c (revision 13080:fcc1e406c13f)
1*13080SPavan.Mettu@Oracle.COM /*
2*13080SPavan.Mettu@Oracle.COM  * CDDL HEADER START
3*13080SPavan.Mettu@Oracle.COM  *
4*13080SPavan.Mettu@Oracle.COM  * The contents of this file are subject to the terms of the
5*13080SPavan.Mettu@Oracle.COM  * Common Development and Distribution License (the "License").
6*13080SPavan.Mettu@Oracle.COM  * You may not use this file except in compliance with the License.
7*13080SPavan.Mettu@Oracle.COM  *
8*13080SPavan.Mettu@Oracle.COM  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*13080SPavan.Mettu@Oracle.COM  * or http://www.opensolaris.org/os/licensing.
10*13080SPavan.Mettu@Oracle.COM  * See the License for the specific language governing permissions
11*13080SPavan.Mettu@Oracle.COM  * and limitations under the License.
12*13080SPavan.Mettu@Oracle.COM  *
13*13080SPavan.Mettu@Oracle.COM  * When distributing Covered Code, include this CDDL HEADER in each
14*13080SPavan.Mettu@Oracle.COM  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*13080SPavan.Mettu@Oracle.COM  * If applicable, add the following below this CDDL HEADER, with the
16*13080SPavan.Mettu@Oracle.COM  * fields enclosed by brackets "[]" replaced with your own identifying
17*13080SPavan.Mettu@Oracle.COM  * information: Portions Copyright [yyyy] [name of copyright owner]
18*13080SPavan.Mettu@Oracle.COM  *
19*13080SPavan.Mettu@Oracle.COM  * CDDL HEADER END
20*13080SPavan.Mettu@Oracle.COM  */
21*13080SPavan.Mettu@Oracle.COM 
22*13080SPavan.Mettu@Oracle.COM /*
23*13080SPavan.Mettu@Oracle.COM  * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
24*13080SPavan.Mettu@Oracle.COM  */
25*13080SPavan.Mettu@Oracle.COM 
26*13080SPavan.Mettu@Oracle.COM /*
27*13080SPavan.Mettu@Oracle.COM  * AUTOMOUNT specific functions
28*13080SPavan.Mettu@Oracle.COM  */
29*13080SPavan.Mettu@Oracle.COM #include <stdio.h>
30*13080SPavan.Mettu@Oracle.COM #include <string.h>
31*13080SPavan.Mettu@Oracle.COM #include <ctype.h>
32*13080SPavan.Mettu@Oracle.COM #include <stdlib.h>
33*13080SPavan.Mettu@Oracle.COM #include <unistd.h>
34*13080SPavan.Mettu@Oracle.COM #include <zone.h>
35*13080SPavan.Mettu@Oracle.COM #include <errno.h>
36*13080SPavan.Mettu@Oracle.COM #include <locale.h>
37*13080SPavan.Mettu@Oracle.COM #include <fcntl.h>
38*13080SPavan.Mettu@Oracle.COM #include <sys/types.h>
39*13080SPavan.Mettu@Oracle.COM #include <sys/stat.h>
40*13080SPavan.Mettu@Oracle.COM #include <syslog.h>
41*13080SPavan.Mettu@Oracle.COM #include "libshare.h"
42*13080SPavan.Mettu@Oracle.COM #include "libshare_impl.h"
43*13080SPavan.Mettu@Oracle.COM #include <pwd.h>
44*13080SPavan.Mettu@Oracle.COM #include <limits.h>
45*13080SPavan.Mettu@Oracle.COM #include <libscf.h>
46*13080SPavan.Mettu@Oracle.COM #include <strings.h>
47*13080SPavan.Mettu@Oracle.COM #include <libdlpi.h>
48*13080SPavan.Mettu@Oracle.COM #include "smfcfg.h"
49*13080SPavan.Mettu@Oracle.COM 
50*13080SPavan.Mettu@Oracle.COM 
51*13080SPavan.Mettu@Oracle.COM static int autofs_init();
52*13080SPavan.Mettu@Oracle.COM static void autofs_fini();
53*13080SPavan.Mettu@Oracle.COM static int autofs_validate_property(sa_handle_t, sa_property_t, sa_optionset_t);
54*13080SPavan.Mettu@Oracle.COM static int autofs_set_proto_prop(sa_property_t);
55*13080SPavan.Mettu@Oracle.COM static sa_protocol_properties_t autofs_get_proto_set();
56*13080SPavan.Mettu@Oracle.COM static char *autofs_get_status();
57*13080SPavan.Mettu@Oracle.COM static uint64_t autofs_features();
58*13080SPavan.Mettu@Oracle.COM 
59*13080SPavan.Mettu@Oracle.COM static int initautofsprotofromsmf();
60*13080SPavan.Mettu@Oracle.COM static int true_false_validator(int index, char *value);
61*13080SPavan.Mettu@Oracle.COM static int strlen_validator(int index, char *value);
62*13080SPavan.Mettu@Oracle.COM static int range_check_validator(int index, char *value);
63*13080SPavan.Mettu@Oracle.COM 
64*13080SPavan.Mettu@Oracle.COM /*
65*13080SPavan.Mettu@Oracle.COM  * ops vector that provides the protocol specific info and operations
66*13080SPavan.Mettu@Oracle.COM  * for share management.
67*13080SPavan.Mettu@Oracle.COM  */
68*13080SPavan.Mettu@Oracle.COM struct sa_plugin_ops sa_plugin_ops = {
69*13080SPavan.Mettu@Oracle.COM 	SA_PLUGIN_VERSION,
70*13080SPavan.Mettu@Oracle.COM 	"autofs",
71*13080SPavan.Mettu@Oracle.COM 	autofs_init, 		/* Init autofs */
72*13080SPavan.Mettu@Oracle.COM 	autofs_fini, 		/* Fini autofs */
73*13080SPavan.Mettu@Oracle.COM 	NULL,			/* Start Sharing */
74*13080SPavan.Mettu@Oracle.COM 	NULL,			/* stop sharing */
75*13080SPavan.Mettu@Oracle.COM 	autofs_validate_property,
76*13080SPavan.Mettu@Oracle.COM 	NULL,			/* valid_space */
77*13080SPavan.Mettu@Oracle.COM 	NULL,			/* security_prop */
78*13080SPavan.Mettu@Oracle.COM 	NULL,			/* parse optstring */
79*13080SPavan.Mettu@Oracle.COM 	NULL,			/* format optstring */
80*13080SPavan.Mettu@Oracle.COM 	autofs_set_proto_prop,	/* Set properties */
81*13080SPavan.Mettu@Oracle.COM 	autofs_get_proto_set,	/* get properties */
82*13080SPavan.Mettu@Oracle.COM 	autofs_get_status,	/* get status */
83*13080SPavan.Mettu@Oracle.COM 	NULL,			/* space_alias */
84*13080SPavan.Mettu@Oracle.COM 	NULL,			/* update_legacy */
85*13080SPavan.Mettu@Oracle.COM 	NULL,			/* delete_legacy */
86*13080SPavan.Mettu@Oracle.COM 	NULL,			/* change notify */
87*13080SPavan.Mettu@Oracle.COM 	NULL,			/* enable resource */
88*13080SPavan.Mettu@Oracle.COM 	NULL,			/* disable resource */
89*13080SPavan.Mettu@Oracle.COM 	autofs_features,	/* features */
90*13080SPavan.Mettu@Oracle.COM 	NULL,			/* transient shares */
91*13080SPavan.Mettu@Oracle.COM 	NULL,			/* notify resource */
92*13080SPavan.Mettu@Oracle.COM 	NULL,			/* rename resource */
93*13080SPavan.Mettu@Oracle.COM 	NULL,			/* run_command */
94*13080SPavan.Mettu@Oracle.COM 	NULL,			/* command_help */
95*13080SPavan.Mettu@Oracle.COM 	NULL			/* delete_proto_section */
96*13080SPavan.Mettu@Oracle.COM };
97*13080SPavan.Mettu@Oracle.COM 
98*13080SPavan.Mettu@Oracle.COM 
99*13080SPavan.Mettu@Oracle.COM static sa_protocol_properties_t protoset;
100*13080SPavan.Mettu@Oracle.COM 
101*13080SPavan.Mettu@Oracle.COM #define	AUTOMOUNT_VERBOSE_DEFAULT	0
102*13080SPavan.Mettu@Oracle.COM #define	AUTOMOUNTD_VERBOSE_DEFAULT	0
103*13080SPavan.Mettu@Oracle.COM #define	AUTOMOUNT_NOBROWSE_DEFAULT	0
104*13080SPavan.Mettu@Oracle.COM #define	AUTOMOUNT_TIMEOUT_DEFAULT	600
105*13080SPavan.Mettu@Oracle.COM #define	AUTOMOUNT_TRACE_DEFAULT		0
106*13080SPavan.Mettu@Oracle.COM /*
107*13080SPavan.Mettu@Oracle.COM  * Protocol Management functions
108*13080SPavan.Mettu@Oracle.COM  */
109*13080SPavan.Mettu@Oracle.COM struct proto_option_defs {
110*13080SPavan.Mettu@Oracle.COM 	char *tag;
111*13080SPavan.Mettu@Oracle.COM 	char *name;	/* display name -- remove protocol identifier */
112*13080SPavan.Mettu@Oracle.COM 	int index;
113*13080SPavan.Mettu@Oracle.COM 	scf_type_t type;
114*13080SPavan.Mettu@Oracle.COM 	union {
115*13080SPavan.Mettu@Oracle.COM 	    int intval;
116*13080SPavan.Mettu@Oracle.COM 	    char *string;
117*13080SPavan.Mettu@Oracle.COM 	} defvalue;
118*13080SPavan.Mettu@Oracle.COM 	int32_t minval;
119*13080SPavan.Mettu@Oracle.COM 	int32_t maxval;
120*13080SPavan.Mettu@Oracle.COM 	int (*check)(int, char *);
121*13080SPavan.Mettu@Oracle.COM } proto_options[] = {
122*13080SPavan.Mettu@Oracle.COM #define	PROTO_OPT_AUTOMOUNT_TIMEOUT	0
123*13080SPavan.Mettu@Oracle.COM 	{ "timeout",
124*13080SPavan.Mettu@Oracle.COM 	    "timeout",	PROTO_OPT_AUTOMOUNT_TIMEOUT,
125*13080SPavan.Mettu@Oracle.COM 	    SCF_TYPE_INTEGER, AUTOMOUNT_TIMEOUT_DEFAULT,
126*13080SPavan.Mettu@Oracle.COM 	    1, INT32_MAX, range_check_validator},
127*13080SPavan.Mettu@Oracle.COM #define	PROTO_OPT_AUTOMOUNT_VERBOSE	1
128*13080SPavan.Mettu@Oracle.COM 	{ "automount_verbose",
129*13080SPavan.Mettu@Oracle.COM 	    "automount_verbose", PROTO_OPT_AUTOMOUNT_VERBOSE,
130*13080SPavan.Mettu@Oracle.COM 	    SCF_TYPE_BOOLEAN, AUTOMOUNT_VERBOSE_DEFAULT, 0, 1,
131*13080SPavan.Mettu@Oracle.COM 	    true_false_validator},
132*13080SPavan.Mettu@Oracle.COM #define	PROTO_OPT_AUTOMOUNTD_VERBOSE	2
133*13080SPavan.Mettu@Oracle.COM 	{ "automountd_verbose",
134*13080SPavan.Mettu@Oracle.COM 	    "automountd_verbose", PROTO_OPT_AUTOMOUNTD_VERBOSE,
135*13080SPavan.Mettu@Oracle.COM 	    SCF_TYPE_BOOLEAN, AUTOMOUNTD_VERBOSE_DEFAULT, 0, 1,
136*13080SPavan.Mettu@Oracle.COM 	    true_false_validator},
137*13080SPavan.Mettu@Oracle.COM #define	PROTO_OPT_AUTOMOUNTD_NOBROWSE	3
138*13080SPavan.Mettu@Oracle.COM 	{ "nobrowse",
139*13080SPavan.Mettu@Oracle.COM 	    "nobrowse", PROTO_OPT_AUTOMOUNTD_NOBROWSE, SCF_TYPE_BOOLEAN,
140*13080SPavan.Mettu@Oracle.COM 	    AUTOMOUNT_NOBROWSE_DEFAULT, 0, 1, true_false_validator},
141*13080SPavan.Mettu@Oracle.COM #define	PROTO_OPT_AUTOMOUNTD_TRACE	4
142*13080SPavan.Mettu@Oracle.COM 	{ "trace",
143*13080SPavan.Mettu@Oracle.COM 	    "trace", PROTO_OPT_AUTOMOUNTD_TRACE,
144*13080SPavan.Mettu@Oracle.COM 	    SCF_TYPE_INTEGER, AUTOMOUNT_TRACE_DEFAULT,
145*13080SPavan.Mettu@Oracle.COM 	    0, 20, range_check_validator},
146*13080SPavan.Mettu@Oracle.COM #define	PROTO_OPT_AUTOMOUNTD_ENV	5
147*13080SPavan.Mettu@Oracle.COM 	{ "environment",
148*13080SPavan.Mettu@Oracle.COM 	    "environment", PROTO_OPT_AUTOMOUNTD_ENV, SCF_TYPE_ASTRING,
149*13080SPavan.Mettu@Oracle.COM 	    NULL, 0, 1024, strlen_validator},
150*13080SPavan.Mettu@Oracle.COM 	{NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL}
151*13080SPavan.Mettu@Oracle.COM };
152*13080SPavan.Mettu@Oracle.COM 
153*13080SPavan.Mettu@Oracle.COM #define	AUTOFS_PROP_MAX	(sizeof (proto_options) / sizeof (proto_options[0]))
154*13080SPavan.Mettu@Oracle.COM 
155*13080SPavan.Mettu@Oracle.COM static void
add_defaults()156*13080SPavan.Mettu@Oracle.COM add_defaults()
157*13080SPavan.Mettu@Oracle.COM {
158*13080SPavan.Mettu@Oracle.COM 	int i;
159*13080SPavan.Mettu@Oracle.COM 	char number[MAXDIGITS];
160*13080SPavan.Mettu@Oracle.COM 
161*13080SPavan.Mettu@Oracle.COM 	for (i = 0; proto_options[i].tag != NULL; i++) {
162*13080SPavan.Mettu@Oracle.COM 		sa_property_t prop;
163*13080SPavan.Mettu@Oracle.COM 		prop = sa_get_protocol_property(protoset,
164*13080SPavan.Mettu@Oracle.COM 		    proto_options[i].name);
165*13080SPavan.Mettu@Oracle.COM 		if (prop == NULL) {
166*13080SPavan.Mettu@Oracle.COM 			/* add the default value */
167*13080SPavan.Mettu@Oracle.COM 			switch (proto_options[i].type) {
168*13080SPavan.Mettu@Oracle.COM 			case SCF_TYPE_INTEGER:
169*13080SPavan.Mettu@Oracle.COM 				(void) snprintf(number, sizeof (number), "%d",
170*13080SPavan.Mettu@Oracle.COM 				    proto_options[i].defvalue.intval);
171*13080SPavan.Mettu@Oracle.COM 				prop = sa_create_property(proto_options[i].name,
172*13080SPavan.Mettu@Oracle.COM 				    number);
173*13080SPavan.Mettu@Oracle.COM 				break;
174*13080SPavan.Mettu@Oracle.COM 
175*13080SPavan.Mettu@Oracle.COM 			case SCF_TYPE_BOOLEAN:
176*13080SPavan.Mettu@Oracle.COM 				prop = sa_create_property(proto_options[i].name,
177*13080SPavan.Mettu@Oracle.COM 				    proto_options[i].defvalue.intval ?
178*13080SPavan.Mettu@Oracle.COM 				    "true" : "false");
179*13080SPavan.Mettu@Oracle.COM 				break;
180*13080SPavan.Mettu@Oracle.COM 
181*13080SPavan.Mettu@Oracle.COM 			default:
182*13080SPavan.Mettu@Oracle.COM 				/* treat as strings of zero length */
183*13080SPavan.Mettu@Oracle.COM 				prop = sa_create_property(proto_options[i].name,
184*13080SPavan.Mettu@Oracle.COM 				    "");
185*13080SPavan.Mettu@Oracle.COM 				break;
186*13080SPavan.Mettu@Oracle.COM 			}
187*13080SPavan.Mettu@Oracle.COM 			if (prop != NULL)
188*13080SPavan.Mettu@Oracle.COM 				(void) sa_add_protocol_property(protoset, prop);
189*13080SPavan.Mettu@Oracle.COM 		}
190*13080SPavan.Mettu@Oracle.COM 	}
191*13080SPavan.Mettu@Oracle.COM }
192*13080SPavan.Mettu@Oracle.COM 
193*13080SPavan.Mettu@Oracle.COM static int
autofs_init()194*13080SPavan.Mettu@Oracle.COM autofs_init()
195*13080SPavan.Mettu@Oracle.COM {
196*13080SPavan.Mettu@Oracle.COM 	int ret = SA_OK;
197*13080SPavan.Mettu@Oracle.COM 
198*13080SPavan.Mettu@Oracle.COM 	if (sa_plugin_ops.sa_init != autofs_init) {
199*13080SPavan.Mettu@Oracle.COM 		(void) printf(dgettext(TEXT_DOMAIN,
200*13080SPavan.Mettu@Oracle.COM 		    "AUTOFS plugin not installed properly\n"));
201*13080SPavan.Mettu@Oracle.COM 		return (SA_CONFIG_ERR);
202*13080SPavan.Mettu@Oracle.COM 	}
203*13080SPavan.Mettu@Oracle.COM 
204*13080SPavan.Mettu@Oracle.COM 	ret = initautofsprotofromsmf();
205*13080SPavan.Mettu@Oracle.COM 	if (ret != SA_OK) {
206*13080SPavan.Mettu@Oracle.COM 		(void) printf(dgettext(TEXT_DOMAIN,
207*13080SPavan.Mettu@Oracle.COM 		    "AUTOFS plugin problem with SMF properties: %s\n"),
208*13080SPavan.Mettu@Oracle.COM 		    sa_errorstr(ret));
209*13080SPavan.Mettu@Oracle.COM 		ret = SA_OK;
210*13080SPavan.Mettu@Oracle.COM 	}
211*13080SPavan.Mettu@Oracle.COM 	add_defaults();
212*13080SPavan.Mettu@Oracle.COM 	return (ret);
213*13080SPavan.Mettu@Oracle.COM }
214*13080SPavan.Mettu@Oracle.COM 
215*13080SPavan.Mettu@Oracle.COM static void
free_protoprops()216*13080SPavan.Mettu@Oracle.COM free_protoprops()
217*13080SPavan.Mettu@Oracle.COM {
218*13080SPavan.Mettu@Oracle.COM 	if (protoset != NULL) {
219*13080SPavan.Mettu@Oracle.COM 		xmlFreeNode(protoset);
220*13080SPavan.Mettu@Oracle.COM 		protoset = NULL;
221*13080SPavan.Mettu@Oracle.COM 	}
222*13080SPavan.Mettu@Oracle.COM }
223*13080SPavan.Mettu@Oracle.COM 
224*13080SPavan.Mettu@Oracle.COM static void
autofs_fini()225*13080SPavan.Mettu@Oracle.COM autofs_fini()
226*13080SPavan.Mettu@Oracle.COM {
227*13080SPavan.Mettu@Oracle.COM 	free_protoprops();
228*13080SPavan.Mettu@Oracle.COM }
229*13080SPavan.Mettu@Oracle.COM 
230*13080SPavan.Mettu@Oracle.COM static int
findprotoopt(char * propname)231*13080SPavan.Mettu@Oracle.COM findprotoopt(char *propname)
232*13080SPavan.Mettu@Oracle.COM {
233*13080SPavan.Mettu@Oracle.COM 	int i;
234*13080SPavan.Mettu@Oracle.COM 
235*13080SPavan.Mettu@Oracle.COM 	for (i = 0; proto_options[i].tag != NULL; i++)
236*13080SPavan.Mettu@Oracle.COM 		if (strcmp(proto_options[i].name, propname) == 0)
237*13080SPavan.Mettu@Oracle.COM 			return (i);
238*13080SPavan.Mettu@Oracle.COM 	return (-1);
239*13080SPavan.Mettu@Oracle.COM }
240*13080SPavan.Mettu@Oracle.COM 
241*13080SPavan.Mettu@Oracle.COM static int
autofs_validate_property(sa_handle_t handle,sa_property_t property,sa_optionset_t parent)242*13080SPavan.Mettu@Oracle.COM autofs_validate_property(sa_handle_t handle, sa_property_t property,
243*13080SPavan.Mettu@Oracle.COM     sa_optionset_t parent)
244*13080SPavan.Mettu@Oracle.COM {
245*13080SPavan.Mettu@Oracle.COM 	int ret = SA_OK;
246*13080SPavan.Mettu@Oracle.COM 	char *propname;
247*13080SPavan.Mettu@Oracle.COM 	int optionindex;
248*13080SPavan.Mettu@Oracle.COM 	char *value;
249*13080SPavan.Mettu@Oracle.COM 
250*13080SPavan.Mettu@Oracle.COM #ifdef lint
251*13080SPavan.Mettu@Oracle.COM 	handle = handle;
252*13080SPavan.Mettu@Oracle.COM 	parent = parent;
253*13080SPavan.Mettu@Oracle.COM #endif
254*13080SPavan.Mettu@Oracle.COM 	propname = sa_get_property(property, "type");
255*13080SPavan.Mettu@Oracle.COM 	if (propname == NULL)
256*13080SPavan.Mettu@Oracle.COM 		return (SA_NO_SUCH_PROP);
257*13080SPavan.Mettu@Oracle.COM 
258*13080SPavan.Mettu@Oracle.COM 	if ((optionindex = findprotoopt(propname)) < 0)
259*13080SPavan.Mettu@Oracle.COM 		ret = SA_NO_SUCH_PROP;
260*13080SPavan.Mettu@Oracle.COM 
261*13080SPavan.Mettu@Oracle.COM 	if (ret != SA_OK) {
262*13080SPavan.Mettu@Oracle.COM 		if (propname != NULL)
263*13080SPavan.Mettu@Oracle.COM 			sa_free_attr_string(propname);
264*13080SPavan.Mettu@Oracle.COM 		return (ret);
265*13080SPavan.Mettu@Oracle.COM 	}
266*13080SPavan.Mettu@Oracle.COM 
267*13080SPavan.Mettu@Oracle.COM 	value = sa_get_property_attr(property, "value");
268*13080SPavan.Mettu@Oracle.COM 	if (value != NULL) {
269*13080SPavan.Mettu@Oracle.COM 		/*
270*13080SPavan.Mettu@Oracle.COM 		 * If any property is added to AUTOFS, which is a different
271*13080SPavan.Mettu@Oracle.COM 		 * type than the below list, a case needs to be added for that
272*13080SPavan.Mettu@Oracle.COM 		 * to check the values. For now AUTOFS type are just integers,
273*13080SPavan.Mettu@Oracle.COM 		 * string and boolean properties. Just taking care of them.
274*13080SPavan.Mettu@Oracle.COM 		 */
275*13080SPavan.Mettu@Oracle.COM 		switch (proto_options[optionindex].type) {
276*13080SPavan.Mettu@Oracle.COM 		case SCF_TYPE_INTEGER:
277*13080SPavan.Mettu@Oracle.COM 		case SCF_TYPE_BOOLEAN:
278*13080SPavan.Mettu@Oracle.COM 		case SCF_TYPE_ASTRING:
279*13080SPavan.Mettu@Oracle.COM 			ret = proto_options[optionindex].check(optionindex,
280*13080SPavan.Mettu@Oracle.COM 			    value);
281*13080SPavan.Mettu@Oracle.COM 			break;
282*13080SPavan.Mettu@Oracle.COM 		default:
283*13080SPavan.Mettu@Oracle.COM 			break;
284*13080SPavan.Mettu@Oracle.COM 		}
285*13080SPavan.Mettu@Oracle.COM 	}
286*13080SPavan.Mettu@Oracle.COM 
287*13080SPavan.Mettu@Oracle.COM 	/* Free the value */
288*13080SPavan.Mettu@Oracle.COM 	if (value != NULL)
289*13080SPavan.Mettu@Oracle.COM 		sa_free_attr_string(value);
290*13080SPavan.Mettu@Oracle.COM 	if (propname != NULL)
291*13080SPavan.Mettu@Oracle.COM 		sa_free_attr_string(propname);
292*13080SPavan.Mettu@Oracle.COM 	return (ret);
293*13080SPavan.Mettu@Oracle.COM }
294*13080SPavan.Mettu@Oracle.COM 
295*13080SPavan.Mettu@Oracle.COM /*
296*13080SPavan.Mettu@Oracle.COM  * service_in_state(service, chkstate)
297*13080SPavan.Mettu@Oracle.COM  *
298*13080SPavan.Mettu@Oracle.COM  * Want to know if the specified service is in the desired state
299*13080SPavan.Mettu@Oracle.COM  * (chkstate) or not. Return true (1) if it is and false (0) if it
300*13080SPavan.Mettu@Oracle.COM  * isn't.
301*13080SPavan.Mettu@Oracle.COM  */
302*13080SPavan.Mettu@Oracle.COM static int
service_in_state(char * service,const char * chkstate)303*13080SPavan.Mettu@Oracle.COM service_in_state(char *service, const char *chkstate)
304*13080SPavan.Mettu@Oracle.COM {
305*13080SPavan.Mettu@Oracle.COM 	char *state;
306*13080SPavan.Mettu@Oracle.COM 	int ret = B_FALSE;
307*13080SPavan.Mettu@Oracle.COM 
308*13080SPavan.Mettu@Oracle.COM 	state = smf_get_state(service);
309*13080SPavan.Mettu@Oracle.COM 	if (state != NULL) {
310*13080SPavan.Mettu@Oracle.COM 		/* got the state so get the equality for the return value */
311*13080SPavan.Mettu@Oracle.COM 		ret = strcmp(state, chkstate) == 0 ? B_TRUE : B_FALSE;
312*13080SPavan.Mettu@Oracle.COM 		free(state);
313*13080SPavan.Mettu@Oracle.COM 	}
314*13080SPavan.Mettu@Oracle.COM 	return (ret);
315*13080SPavan.Mettu@Oracle.COM }
316*13080SPavan.Mettu@Oracle.COM 
317*13080SPavan.Mettu@Oracle.COM static void
restart_service(char * service)318*13080SPavan.Mettu@Oracle.COM restart_service(char *service)
319*13080SPavan.Mettu@Oracle.COM {
320*13080SPavan.Mettu@Oracle.COM 	int ret = -1;
321*13080SPavan.Mettu@Oracle.COM 
322*13080SPavan.Mettu@Oracle.COM 	/*
323*13080SPavan.Mettu@Oracle.COM 	 * Only attempt to restart the service if it is
324*13080SPavan.Mettu@Oracle.COM 	 * currently running. In the future, it may be
325*13080SPavan.Mettu@Oracle.COM 	 * desirable to use smf_refresh_instance if the AUTOFS
326*13080SPavan.Mettu@Oracle.COM 	 * services ever implement the refresh method.
327*13080SPavan.Mettu@Oracle.COM 	 */
328*13080SPavan.Mettu@Oracle.COM 	if (service_in_state(service, SCF_STATE_STRING_ONLINE)) {
329*13080SPavan.Mettu@Oracle.COM 		ret = smf_restart_instance(service);
330*13080SPavan.Mettu@Oracle.COM 		/*
331*13080SPavan.Mettu@Oracle.COM 		 * There are only a few SMF errors at this point, but
332*13080SPavan.Mettu@Oracle.COM 		 * it is also possible that a bad value may have put
333*13080SPavan.Mettu@Oracle.COM 		 * the service into maintenance if there wasn't an
334*13080SPavan.Mettu@Oracle.COM 		 * SMF level error.
335*13080SPavan.Mettu@Oracle.COM 		 */
336*13080SPavan.Mettu@Oracle.COM 		if (ret != 0) {
337*13080SPavan.Mettu@Oracle.COM 			(void) fprintf(stderr,
338*13080SPavan.Mettu@Oracle.COM 			    dgettext(TEXT_DOMAIN,
339*13080SPavan.Mettu@Oracle.COM 			    "%s failed to restart: %s\n"),
340*13080SPavan.Mettu@Oracle.COM 			    scf_strerror(scf_error()));
341*13080SPavan.Mettu@Oracle.COM 		} else {
342*13080SPavan.Mettu@Oracle.COM 			/*
343*13080SPavan.Mettu@Oracle.COM 			 * Check whether it has gone to "maintenance"
344*13080SPavan.Mettu@Oracle.COM 			 * mode or not. Maintenance implies something
345*13080SPavan.Mettu@Oracle.COM 			 * went wrong.
346*13080SPavan.Mettu@Oracle.COM 			 */
347*13080SPavan.Mettu@Oracle.COM 			if (service_in_state(service,
348*13080SPavan.Mettu@Oracle.COM 			    SCF_STATE_STRING_MAINT)) {
349*13080SPavan.Mettu@Oracle.COM 				(void) fprintf(stderr,
350*13080SPavan.Mettu@Oracle.COM 				    dgettext(TEXT_DOMAIN,
351*13080SPavan.Mettu@Oracle.COM 				    "%s failed to restart\n"),
352*13080SPavan.Mettu@Oracle.COM 				    service);
353*13080SPavan.Mettu@Oracle.COM 			}
354*13080SPavan.Mettu@Oracle.COM 		}
355*13080SPavan.Mettu@Oracle.COM 	}
356*13080SPavan.Mettu@Oracle.COM }
357*13080SPavan.Mettu@Oracle.COM 
358*13080SPavan.Mettu@Oracle.COM static int
is_a_number(char * number)359*13080SPavan.Mettu@Oracle.COM is_a_number(char *number)
360*13080SPavan.Mettu@Oracle.COM {
361*13080SPavan.Mettu@Oracle.COM 	int ret = 1;
362*13080SPavan.Mettu@Oracle.COM 	int hex = 0;
363*13080SPavan.Mettu@Oracle.COM 
364*13080SPavan.Mettu@Oracle.COM 	if (strncmp(number, "0x", 2) == 0) {
365*13080SPavan.Mettu@Oracle.COM 		number += 2;
366*13080SPavan.Mettu@Oracle.COM 		hex = 1;
367*13080SPavan.Mettu@Oracle.COM 	} else if (*number == '-') {
368*13080SPavan.Mettu@Oracle.COM 		number++; /* skip the minus */
369*13080SPavan.Mettu@Oracle.COM 	}
370*13080SPavan.Mettu@Oracle.COM 	while (ret == 1 && *number != '\0') {
371*13080SPavan.Mettu@Oracle.COM 		if (hex) {
372*13080SPavan.Mettu@Oracle.COM 			ret = isxdigit(*number++);
373*13080SPavan.Mettu@Oracle.COM 		} else {
374*13080SPavan.Mettu@Oracle.COM 			ret = isdigit(*number++);
375*13080SPavan.Mettu@Oracle.COM 		}
376*13080SPavan.Mettu@Oracle.COM 	}
377*13080SPavan.Mettu@Oracle.COM 	return (ret);
378*13080SPavan.Mettu@Oracle.COM }
379*13080SPavan.Mettu@Oracle.COM 
380*13080SPavan.Mettu@Oracle.COM /*
381*13080SPavan.Mettu@Oracle.COM  * fixcaselower(str)
382*13080SPavan.Mettu@Oracle.COM  *
383*13080SPavan.Mettu@Oracle.COM  * convert a string to lower case (inplace).
384*13080SPavan.Mettu@Oracle.COM  */
385*13080SPavan.Mettu@Oracle.COM 
386*13080SPavan.Mettu@Oracle.COM static void
fixcaselower(char * str)387*13080SPavan.Mettu@Oracle.COM fixcaselower(char *str)
388*13080SPavan.Mettu@Oracle.COM {
389*13080SPavan.Mettu@Oracle.COM 	while (*str) {
390*13080SPavan.Mettu@Oracle.COM 		*str = tolower(*str);
391*13080SPavan.Mettu@Oracle.COM 		str++;
392*13080SPavan.Mettu@Oracle.COM 	}
393*13080SPavan.Mettu@Oracle.COM }
394*13080SPavan.Mettu@Oracle.COM 
395*13080SPavan.Mettu@Oracle.COM /*
396*13080SPavan.Mettu@Oracle.COM  * skipwhitespace(str)
397*13080SPavan.Mettu@Oracle.COM  *
398*13080SPavan.Mettu@Oracle.COM  * Skip leading white space. It is assumed that it is called with a
399*13080SPavan.Mettu@Oracle.COM  * valid pointer.
400*13080SPavan.Mettu@Oracle.COM  */
401*13080SPavan.Mettu@Oracle.COM static char *
skipwhitespace(char * str)402*13080SPavan.Mettu@Oracle.COM skipwhitespace(char *str)
403*13080SPavan.Mettu@Oracle.COM {
404*13080SPavan.Mettu@Oracle.COM 	while (*str && isspace(*str))
405*13080SPavan.Mettu@Oracle.COM 		str++;
406*13080SPavan.Mettu@Oracle.COM 
407*13080SPavan.Mettu@Oracle.COM 	return (str);
408*13080SPavan.Mettu@Oracle.COM }
409*13080SPavan.Mettu@Oracle.COM 
410*13080SPavan.Mettu@Oracle.COM /*
411*13080SPavan.Mettu@Oracle.COM  * extractprop()
412*13080SPavan.Mettu@Oracle.COM  *
413*13080SPavan.Mettu@Oracle.COM  * Extract the property and value out of the line and create the
414*13080SPavan.Mettu@Oracle.COM  * property in the optionset.
415*13080SPavan.Mettu@Oracle.COM  */
416*13080SPavan.Mettu@Oracle.COM static int
extractprop(char * name,char * value)417*13080SPavan.Mettu@Oracle.COM extractprop(char *name, char *value)
418*13080SPavan.Mettu@Oracle.COM {
419*13080SPavan.Mettu@Oracle.COM 	sa_property_t prop;
420*13080SPavan.Mettu@Oracle.COM 	int index;
421*13080SPavan.Mettu@Oracle.COM 	int ret = SA_OK;
422*13080SPavan.Mettu@Oracle.COM 	/*
423*13080SPavan.Mettu@Oracle.COM 	 * Remove any leading
424*13080SPavan.Mettu@Oracle.COM 	 * white space.
425*13080SPavan.Mettu@Oracle.COM 	 */
426*13080SPavan.Mettu@Oracle.COM 	name = skipwhitespace(name);
427*13080SPavan.Mettu@Oracle.COM 
428*13080SPavan.Mettu@Oracle.COM 	index = findprotoopt(name);
429*13080SPavan.Mettu@Oracle.COM 	if (index >= 0) {
430*13080SPavan.Mettu@Oracle.COM 		fixcaselower(name);
431*13080SPavan.Mettu@Oracle.COM 		prop = sa_create_property(proto_options[index].name, value);
432*13080SPavan.Mettu@Oracle.COM 		if (prop != NULL)
433*13080SPavan.Mettu@Oracle.COM 			ret = sa_add_protocol_property(protoset, prop);
434*13080SPavan.Mettu@Oracle.COM 		else
435*13080SPavan.Mettu@Oracle.COM 			ret = SA_NO_MEMORY;
436*13080SPavan.Mettu@Oracle.COM 	}
437*13080SPavan.Mettu@Oracle.COM 	return (ret);
438*13080SPavan.Mettu@Oracle.COM }
439*13080SPavan.Mettu@Oracle.COM 
440*13080SPavan.Mettu@Oracle.COM static int
initautofsprotofromsmf(void)441*13080SPavan.Mettu@Oracle.COM initautofsprotofromsmf(void)
442*13080SPavan.Mettu@Oracle.COM {
443*13080SPavan.Mettu@Oracle.COM 	char name[PATH_MAX];
444*13080SPavan.Mettu@Oracle.COM 	char value[PATH_MAX];
445*13080SPavan.Mettu@Oracle.COM 	int ret = SA_OK, bufsz = 0, i;
446*13080SPavan.Mettu@Oracle.COM 	char *instance = NULL;
447*13080SPavan.Mettu@Oracle.COM 	scf_type_t sctype;
448*13080SPavan.Mettu@Oracle.COM 
449*13080SPavan.Mettu@Oracle.COM 	protoset = sa_create_protocol_properties("autofs");
450*13080SPavan.Mettu@Oracle.COM 	if (protoset != NULL) {
451*13080SPavan.Mettu@Oracle.COM 		for (i = 0; proto_options[i].tag != NULL; i++) {
452*13080SPavan.Mettu@Oracle.COM 			bzero(value, PATH_MAX);
453*13080SPavan.Mettu@Oracle.COM 			(void) strncpy(name, proto_options[i].name, PATH_MAX);
454*13080SPavan.Mettu@Oracle.COM 			sctype = proto_options[i].type;
455*13080SPavan.Mettu@Oracle.COM 			bufsz = PATH_MAX;
456*13080SPavan.Mettu@Oracle.COM 			ret = autofs_smf_get_prop(name, value,
457*13080SPavan.Mettu@Oracle.COM 			    instance, sctype, AUTOFS_FMRI, &bufsz);
458*13080SPavan.Mettu@Oracle.COM 			if (ret == SA_OK) {
459*13080SPavan.Mettu@Oracle.COM 				ret = extractprop(name, value);
460*13080SPavan.Mettu@Oracle.COM 			}
461*13080SPavan.Mettu@Oracle.COM 		}
462*13080SPavan.Mettu@Oracle.COM 	} else {
463*13080SPavan.Mettu@Oracle.COM 		ret = SA_NO_MEMORY;
464*13080SPavan.Mettu@Oracle.COM 	}
465*13080SPavan.Mettu@Oracle.COM 	return (ret);
466*13080SPavan.Mettu@Oracle.COM }
467*13080SPavan.Mettu@Oracle.COM 
468*13080SPavan.Mettu@Oracle.COM static int
range_check_validator(int index,char * value)469*13080SPavan.Mettu@Oracle.COM range_check_validator(int index, char *value)
470*13080SPavan.Mettu@Oracle.COM {
471*13080SPavan.Mettu@Oracle.COM 	int ret = SA_OK;
472*13080SPavan.Mettu@Oracle.COM 	if (!is_a_number(value)) {
473*13080SPavan.Mettu@Oracle.COM 		ret = SA_BAD_VALUE;
474*13080SPavan.Mettu@Oracle.COM 	} else {
475*13080SPavan.Mettu@Oracle.COM 		int val;
476*13080SPavan.Mettu@Oracle.COM 		errno = 0;
477*13080SPavan.Mettu@Oracle.COM 		val = strtoul(value, NULL, 0);
478*13080SPavan.Mettu@Oracle.COM 		if (errno != 0)
479*13080SPavan.Mettu@Oracle.COM 			return (SA_BAD_VALUE);
480*13080SPavan.Mettu@Oracle.COM 
481*13080SPavan.Mettu@Oracle.COM 		if (val < proto_options[index].minval ||
482*13080SPavan.Mettu@Oracle.COM 		    val > proto_options[index].maxval)
483*13080SPavan.Mettu@Oracle.COM 			ret = SA_BAD_VALUE;
484*13080SPavan.Mettu@Oracle.COM 	}
485*13080SPavan.Mettu@Oracle.COM 	return (ret);
486*13080SPavan.Mettu@Oracle.COM }
487*13080SPavan.Mettu@Oracle.COM 
488*13080SPavan.Mettu@Oracle.COM static int
true_false_validator(int index,char * value)489*13080SPavan.Mettu@Oracle.COM true_false_validator(int index, char *value)
490*13080SPavan.Mettu@Oracle.COM {
491*13080SPavan.Mettu@Oracle.COM 
492*13080SPavan.Mettu@Oracle.COM #ifdef lint
493*13080SPavan.Mettu@Oracle.COM 	index = index;
494*13080SPavan.Mettu@Oracle.COM #endif
495*13080SPavan.Mettu@Oracle.COM 	if ((strcasecmp(value, "true") == 0) ||
496*13080SPavan.Mettu@Oracle.COM 	    (strcasecmp(value, "on") == 0) ||
497*13080SPavan.Mettu@Oracle.COM 	    (strcasecmp(value, "yes") == 0) ||
498*13080SPavan.Mettu@Oracle.COM 	    (strcmp(value, "1") == 0) ||
499*13080SPavan.Mettu@Oracle.COM 	    (strcasecmp(value, "false") == 0) ||
500*13080SPavan.Mettu@Oracle.COM 	    (strcasecmp(value, "off") == 0) ||
501*13080SPavan.Mettu@Oracle.COM 	    (strcasecmp(value, "no") == 0) ||
502*13080SPavan.Mettu@Oracle.COM 	    (strcmp(value, "0") == 0)) {
503*13080SPavan.Mettu@Oracle.COM 		return (SA_OK);
504*13080SPavan.Mettu@Oracle.COM 	}
505*13080SPavan.Mettu@Oracle.COM 	return (SA_BAD_VALUE);
506*13080SPavan.Mettu@Oracle.COM }
507*13080SPavan.Mettu@Oracle.COM 
508*13080SPavan.Mettu@Oracle.COM static int
strlen_validator(int index,char * value)509*13080SPavan.Mettu@Oracle.COM strlen_validator(int index, char *value)
510*13080SPavan.Mettu@Oracle.COM {
511*13080SPavan.Mettu@Oracle.COM 	int ret = SA_OK;
512*13080SPavan.Mettu@Oracle.COM 	if (value == NULL) {
513*13080SPavan.Mettu@Oracle.COM 		if (proto_options[index].minval == 0) {
514*13080SPavan.Mettu@Oracle.COM 			return (ret);
515*13080SPavan.Mettu@Oracle.COM 		} else {
516*13080SPavan.Mettu@Oracle.COM 			return (SA_BAD_VALUE);
517*13080SPavan.Mettu@Oracle.COM 		}
518*13080SPavan.Mettu@Oracle.COM 	}
519*13080SPavan.Mettu@Oracle.COM 	if (strlen(value) > proto_options[index].maxval ||
520*13080SPavan.Mettu@Oracle.COM 	    strlen(value) < proto_options[index].minval)
521*13080SPavan.Mettu@Oracle.COM 		ret = SA_BAD_VALUE;
522*13080SPavan.Mettu@Oracle.COM 	return (ret);
523*13080SPavan.Mettu@Oracle.COM }
524*13080SPavan.Mettu@Oracle.COM 
525*13080SPavan.Mettu@Oracle.COM static int
autofs_validate_proto_prop(int index,char * name,char * value)526*13080SPavan.Mettu@Oracle.COM autofs_validate_proto_prop(int index, char *name, char *value)
527*13080SPavan.Mettu@Oracle.COM {
528*13080SPavan.Mettu@Oracle.COM #ifdef lint
529*13080SPavan.Mettu@Oracle.COM 	name = name;
530*13080SPavan.Mettu@Oracle.COM #endif
531*13080SPavan.Mettu@Oracle.COM 	return (proto_options[index].check(index, value));
532*13080SPavan.Mettu@Oracle.COM }
533*13080SPavan.Mettu@Oracle.COM 
534*13080SPavan.Mettu@Oracle.COM static int
autofs_set_proto_prop(sa_property_t prop)535*13080SPavan.Mettu@Oracle.COM autofs_set_proto_prop(sa_property_t prop)
536*13080SPavan.Mettu@Oracle.COM {
537*13080SPavan.Mettu@Oracle.COM 	int ret = SA_OK;
538*13080SPavan.Mettu@Oracle.COM 	char *name;
539*13080SPavan.Mettu@Oracle.COM 	char *value, *instance = NULL;
540*13080SPavan.Mettu@Oracle.COM 	scf_type_t sctype;
541*13080SPavan.Mettu@Oracle.COM 
542*13080SPavan.Mettu@Oracle.COM 	name = sa_get_property_attr(prop, "type");
543*13080SPavan.Mettu@Oracle.COM 	value = sa_get_property_attr(prop, "value");
544*13080SPavan.Mettu@Oracle.COM 	if (name != NULL && value != NULL) {
545*13080SPavan.Mettu@Oracle.COM 		int index = findprotoopt(name);
546*13080SPavan.Mettu@Oracle.COM 		if (index >= 0) {
547*13080SPavan.Mettu@Oracle.COM 			ret = autofs_validate_proto_prop(index, name, value);
548*13080SPavan.Mettu@Oracle.COM 			if (ret == SA_OK) {
549*13080SPavan.Mettu@Oracle.COM 				sctype = proto_options[index].type;
550*13080SPavan.Mettu@Oracle.COM 				if (sctype == SCF_TYPE_BOOLEAN) {
551*13080SPavan.Mettu@Oracle.COM 					if (value != NULL)
552*13080SPavan.Mettu@Oracle.COM 						sa_free_attr_string(value);
553*13080SPavan.Mettu@Oracle.COM 					if (string_to_boolean(value) == 0)
554*13080SPavan.Mettu@Oracle.COM 						value = strdup("0");
555*13080SPavan.Mettu@Oracle.COM 					else
556*13080SPavan.Mettu@Oracle.COM 						value = strdup("1");
557*13080SPavan.Mettu@Oracle.COM 				}
558*13080SPavan.Mettu@Oracle.COM 				ret = autofs_smf_set_prop(name, value,
559*13080SPavan.Mettu@Oracle.COM 				    instance, sctype, AUTOFS_FMRI);
560*13080SPavan.Mettu@Oracle.COM 				/*
561*13080SPavan.Mettu@Oracle.COM 				 * Make an instance based FMRI.
562*13080SPavan.Mettu@Oracle.COM 				 * For now its DEFAULT_AUTOFS_FMRI.
563*13080SPavan.Mettu@Oracle.COM 				 */
564*13080SPavan.Mettu@Oracle.COM 				if (ret == SA_OK)
565*13080SPavan.Mettu@Oracle.COM 					restart_service(AUTOFS_DEFAULT_FMRI);
566*13080SPavan.Mettu@Oracle.COM 			}
567*13080SPavan.Mettu@Oracle.COM 		} else {
568*13080SPavan.Mettu@Oracle.COM 			ret = SA_NO_SUCH_PROP;
569*13080SPavan.Mettu@Oracle.COM 		}
570*13080SPavan.Mettu@Oracle.COM 	} else {
571*13080SPavan.Mettu@Oracle.COM 		ret = SA_CONFIG_ERR;
572*13080SPavan.Mettu@Oracle.COM 	}
573*13080SPavan.Mettu@Oracle.COM 
574*13080SPavan.Mettu@Oracle.COM 	if (name != NULL)
575*13080SPavan.Mettu@Oracle.COM 		sa_free_attr_string(name);
576*13080SPavan.Mettu@Oracle.COM 	if (value != NULL)
577*13080SPavan.Mettu@Oracle.COM 		sa_free_attr_string(value);
578*13080SPavan.Mettu@Oracle.COM 	return (ret);
579*13080SPavan.Mettu@Oracle.COM }
580*13080SPavan.Mettu@Oracle.COM 
581*13080SPavan.Mettu@Oracle.COM 
582*13080SPavan.Mettu@Oracle.COM static sa_protocol_properties_t
autofs_get_proto_set(void)583*13080SPavan.Mettu@Oracle.COM autofs_get_proto_set(void)
584*13080SPavan.Mettu@Oracle.COM {
585*13080SPavan.Mettu@Oracle.COM 	return (protoset);
586*13080SPavan.Mettu@Oracle.COM }
587*13080SPavan.Mettu@Oracle.COM 
588*13080SPavan.Mettu@Oracle.COM static uint64_t
autofs_features(void)589*13080SPavan.Mettu@Oracle.COM autofs_features(void)
590*13080SPavan.Mettu@Oracle.COM {
591*13080SPavan.Mettu@Oracle.COM 	return (0);
592*13080SPavan.Mettu@Oracle.COM }
593*13080SPavan.Mettu@Oracle.COM 
594*13080SPavan.Mettu@Oracle.COM static char *
autofs_get_status(void)595*13080SPavan.Mettu@Oracle.COM autofs_get_status(void)
596*13080SPavan.Mettu@Oracle.COM {
597*13080SPavan.Mettu@Oracle.COM 	char *state = NULL;
598*13080SPavan.Mettu@Oracle.COM 	state = smf_get_state(AUTOFS_DEFAULT_FMRI);
599*13080SPavan.Mettu@Oracle.COM 	return (state != NULL ? state : "-");
600*13080SPavan.Mettu@Oracle.COM }
601