ldapclient.c revision 2830:5228d1267a01
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 2006 Sun Microsystems, Inc.  All rights reserved.
23 * Use is subject to license terms.
24 */
25
26#pragma ident	"%Z%%M%	%I%	%E% SMI"
27
28/*
29 * ldapclient command. To make (initiailize) or uninitialize a machines as
30 * and LDAP client.  This command MUST be run as root (or it will simply exit).
31 *
32 *	-I	Install. No file_backup/recover for installing only (no doc).
33 *
34 *	init	Initialze (create) an LDAP client from a profile stored
35 *		in a directory-server.
36 *	manual	Initialze (create) an LDAP client by hand (-file option
37 *		reads from file).
38 *	mod	Modify the LDAP client configuration on this machine by hand.
39 *	list	List the contents of the LDAP client cache files.
40 *	uninit	Uninitialize this machine.
41 *
42 *	-v	Verbose flag.
43 *	-q	Quiet flag (mutually exclusive with -v).
44 *
45 *	-a attrName=attrVal
46 *	<attrName> can be one of the following:
47 *
48 *	attributeMap
49 *		Attribute map.  Can be multiple instances of this option.
50 *		(no former option)
51 *	authenticationMethod
52 *		Authentication method (formerly -a)
53 *	bindTimeLimit
54 *		Bind time limit. (no former option)
55 *	certificatePath
56 *		Path to certificates used for secure bind (no former option)
57 *	credentialLevel
58 *		Client credential level (no former option)
59 *	defaultServerList
60 *		Default server (no former option) Refer to DUA Config
61 *		Schema draft.
62 *	defaultSearchBase
63 *		Search Base DN. e.g. dc=eng,dc=sun,dc=com (formerly -b)
64 *	defaultSearchScope
65 *		Search scope. (formerly -s)
66 *	domainName
67 *		Hosts lookup domain (DNS)  Ex. eng.sun.com (formerly -d)
68 *	followReferrals
69 *		Search dereference. followref or noref (default followref)
70 *		(formerly -r)
71 *	objectclassMap
72 *		Objectclass map.  Can be multiple instances of this option.
73 *		(no former option)
74 *	preferredServerList
75 *		Server preference list. Comma ',' seperated list of IPaddr.
76 *		(formerly -p)
77 *	profileName
78 *		Profile name to use for init (ldapclient) or
79 *		generate (gen_profile). (formerly -P)
80 *	profileTTL
81 *		Client info TTL.  If set to 0 this information will not be
82 *		automatically updated by the ldap_cachemgr(1M).
83 *		(formerly -e)
84 *	proxyDN
85 *		Binding DN.  Ex. cn=client,ou=people,cd=eng,dc=sun,dc=com
86 *		(formerly -D)
87 *	proxyPassword
88 *		Client password not needed for authentication "none".
89 *		(formerly -w)
90 *	searchTimeLimit
91 *		Timeout value. (formerly -o)
92 *	serviceSearchDescriptor
93 *		Service search scope. (no former option)
94 *	serviceAuthenticationMethod
95 *		Service authenticaion method (no former option)
96 *	serviceCredentialLevel
97 *		Service credential level (no former option)
98 *
99 */
100
101#include <stdlib.h>
102#include <stdio.h>
103#include <unistd.h>
104#include <errno.h>
105#include <sys/types.h>
106#include <time.h>
107#include <sys/param.h>
108#include <sys/stat.h>
109#include <sys/systeminfo.h>
110#include <fcntl.h>
111#include <xti.h>
112#include <strings.h>
113#include <limits.h>
114#include <locale.h>
115#include <syslog.h>
116#include <libscf.h>
117#include <assert.h>
118#include "ns_sldap.h"
119#include "ns_internal.h"
120
121#if !defined(TEXT_DOMAIN)
122#define	TEXT_DOMAIN "SUNW_OST_OSCMD"
123#endif
124
125/* error codes */
126/* The manpage doc only allows for SUCCESS(0), FAIL(1) and CRED(2) on exit */
127#define	CLIENT_SUCCESS		0
128#define	CLIENT_ERR_PARSE	-1
129#define	CLIENT_ERR_FAIL		1
130#define	CLIENT_ERR_CREDENTIAL	2
131#define	CLIENT_ERR_MEMORY	3
132#define	CLIENT_ERR_RESTORE	4
133#define	CLIENT_ERR_RENAME	5
134#define	CLIENT_ERR_RECOVER	6
135#define	CLIENT_ERR_TIMEDOUT	7
136#define	CLIENT_ERR_MAINTENANCE	8
137
138/* Reset flag for start_services() */
139#define	START_INIT	1
140#define	START_RESET	2
141#define	START_UNINIT	3
142
143/* Reset flag for stop_services() */
144#define	STATE_NOSAVE	0
145#define	STATE_SAVE	1
146
147/* files to (possibiliy) restore */
148#define	LDAP_RESTORE_DIR	"/var/ldap/restore"
149
150#define	DOMAINNAME_DIR		"/etc"
151#define	DOMAINNAME_FILE		"defaultdomain"
152#define	DOMAINNAME		DOMAINNAME_DIR "/" DOMAINNAME_FILE
153#define	DOMAINNAME_BACK		LDAP_RESTORE_DIR "/" DOMAINNAME_FILE
154
155#define	NSSWITCH_DIR		"/etc"
156#define	NSSWITCH_FILE		"nsswitch.conf"
157#define	NSSWITCH_CONF		NSSWITCH_DIR "/" NSSWITCH_FILE
158#define	NSSWITCH_BACK		LDAP_RESTORE_DIR "/" NSSWITCH_FILE
159#define	NSSWITCH_LDAP		"/etc/nsswitch.ldap"
160
161#define	NIS_COLDSTART_DIR	"/var/nis"
162#define	NIS_COLDSTART_FILE	"NIS_COLD_START"
163#define	NIS_COLDSTART		NIS_COLDSTART_DIR "/" NIS_COLDSTART_FILE
164#define	NIS_COLDSTART_BACK	LDAP_RESTORE_DIR "/" NIS_COLDSTART_FILE
165
166#define	YP_BIND_DIR		"/var/yp/binding"
167
168/* Define the service FMRIs */
169#define	SENDMAIL_FMRI		"network/smtp:sendmail"
170#define	NSCD_FMRI		"system/name-service-cache:default"
171#define	AUTOFS_FMRI		"system/filesystem/autofs:default"
172#define	LDAP_FMRI		"network/ldap/client:default"
173#define	NISD_FMRI		"network/rpc/nisplus:default"
174#define	YP_FMRI			"network/nis/client:default"
175#define	NS_MILESTONE_FMRI	"milestone/name-services:default"
176
177/* Define flags for checking if services were enabled */
178#define	SENDMAIL_ON	0x1
179#define	NSCD_ON		0x10
180#define	AUTOFS_ON	0x100
181
182#define	CMD_DOMAIN_START	"/usr/bin/domainname"
183
184/* Command to copy files */
185#define	CMD_CP			"/bin/cp -f"
186#define	CMD_MV			"/bin/mv -f"
187#define	CMD_RM			"/bin/rm -f"
188
189#define	TO_DEV_NULL		" >/dev/null 2>&1"
190
191/* Files that need to be just removed */
192#define	NIS_PRIVATE_CACHE	"/var/nis/.NIS_PRIVATE_DIRCACHE"
193#define	NIS_SHARED_CACHE	"/var/nis/NIS_SHARED_DIRCACHE"
194#define	NIS_CLIENT_INFO		"/var/nis/client_info"
195#define	LDAP_CACHE_LOG		"/var/ldap/cachemgr.log"
196
197/* Output defines to supress if quiet mode set */
198#define	CLIENT_FPUTS if (!mode_quiet) (void) fputs
199#define	CLIENT_FPRINTF if (!mode_quiet) (void) fprintf
200#define	CLIENT_FPUTC if (!mode_quiet) (void) fputc
201
202#define	restart_service(fmri, waitflag)\
203		do_service(fmri, waitflag, RESTART_SERVICE,\
204		SCF_STATE_STRING_ONLINE)
205#define	start_service(fmri, waitflag)	\
206		do_service(fmri, waitflag, START_SERVICE,\
207		SCF_STATE_STRING_ONLINE)
208#define	disable_service(fmri, waitflag)	\
209		do_service(fmri, waitflag, STOP_SERVICE,\
210		SCF_STATE_STRING_DISABLED)
211
212/*
213 * There isn't a domainName defined as a param, so we set a value here
214 * (1001) should be big enough
215 */
216#define	LOCAL_DOMAIN_P 1001
217
218#define	START_SERVICE	1
219#define	STOP_SERVICE	2
220#define	RESTART_SERVICE	3
221
222#define	DEFAULT_TIMEOUT	60000000
223
224#define	INIT_WAIT_USECS	50000
225
226/* Used to turn off profile checking */
227#define	CACHETTL_OFF "0"
228
229/* Globals */
230static char *cmd;
231
232static char *dname = NULL;
233static char dname_buf[BUFSIZ];
234
235static boolean_t sysid_install = B_FALSE;
236
237static int mode_verbose = 0;
238static int mode_quiet = 0;
239static int gen = 0;
240
241static int gStartLdap = 0;
242static int gStartYp = 0;
243static int gStartNisd = 0;
244
245static int enableFlag = 0;
246
247/* multival_t is used to hold params that can have more than one value */
248typedef struct {
249	int count;
250	char **optlist;
251} multival_t;
252
253static multival_t *multival_new();
254static int multival_add(multival_t *list, char *opt);
255static void multival_free(multival_t *list);
256
257/*
258 * clientopts_t is used to hold and pass around the param values from
259 * the cmd line
260 */
261typedef struct {
262	multival_t	*attributeMap;
263	char		*authenticationMethod;
264	char		*bindTimeLimit;
265	char		*certificatePath;
266	char		*credentialLevel;
267	char		*defaultSearchBase;
268	char		*defaultServerList;
269	char		*domainName;
270	char		*followReferrals;
271	multival_t	*objectclassMap;
272	char		*preferredServerList;
273	char		*profileName;
274	char		*profileTTL;
275	char		*proxyDN;
276	char		*proxyPassword;
277	char		*defaultSearchScope;
278	char		*searchTimeLimit;
279	multival_t	*serviceAuthenticationMethod;
280	multival_t	*serviceCredentialLevel;
281	multival_t	*serviceSearchDescriptor;
282} clientopts_t;
283
284static clientopts_t *clientopts_new();
285static void clientopts_free(clientopts_t *list);
286
287extern ns_ldap_error_t *__ns_ldap_print_config(int);
288extern void __ns_ldap_default_config();
289extern int __ns_ldap_download(const char *, char *, char *, ns_ldap_error_t **);
290
291/* Function prototypes (these could be static) */
292static void usage(void);
293
294static int credCheck(clientopts_t *arglist);
295static char *findBaseDN(char *);
296static int clientSetParam(clientopts_t *optlist, int paramFlag, char *attrVal);
297static int parseParam(char *param, char **paramVal);
298static void dumpargs(clientopts_t *arglist);
299static int num_args(clientopts_t *arglist);
300
301static int file_backup(void);
302static int recover(int saveState);
303static int mod_backup(void);
304static int mod_recover(void);
305static void mod_cleanup(void);
306
307static int client_list(clientopts_t *arglist);
308static int client_manual(clientopts_t *arglist);
309static int client_mod(clientopts_t *arglist);
310static int client_uninit(clientopts_t *arglist);
311static int client_genProfile(clientopts_t *arglist);
312static int client_init(clientopts_t *arglist);
313static boolean_t is_config_ok(const clientopts_t *list, boolean_t get_config);
314static int file_move(const char *from, const char *to);
315
316static int start_services(int flag);
317static int stop_services(int saveState);
318static boolean_t is_service(const char *fmri, const char *state);
319static int wait_till(const char *fmri, const char *state, useconds_t max,
320		const char *what, boolean_t check_maint);
321static int do_service(const char *fmri, boolean_t waitflag, int dowhat,
322		const char *state);
323static useconds_t get_timeout_value(int dowhat, const char *fmri,
324		useconds_t default_val);
325
326int
327main(int argc, char **argv)
328{
329	char *ret_locale, *ret_textdomain;
330	int retcode;
331	int paramFlag;
332	char *attrVal;
333	int sysinfostatus;
334	clientopts_t *optlist = NULL;
335	int op_manual = 0, op_mod = 0, op_uninit = 0;
336	int op_list = 0, op_init = 0, op_genprofile = 0;
337	extern char *optarg;
338	extern int optind;
339	int option;
340
341
342	ret_locale = setlocale(LC_ALL, "");
343	if (ret_locale == NULL) {
344		CLIENT_FPUTS(gettext("Unable to set locale.\n"), stderr);
345	}
346	ret_textdomain = textdomain(TEXT_DOMAIN);
347	if (ret_textdomain == NULL) {
348		CLIENT_FPUTS(gettext("Unable to set textdomain.\n"), stderr);
349	}
350
351	openlog("ldapclient", LOG_PID, LOG_USER);
352
353	/* get name that invoked us */
354	if (cmd = strrchr(argv[0], '/'))
355		++cmd;
356	else
357		cmd = argv[0];
358
359	sysinfostatus = sysinfo(SI_SRPC_DOMAIN, dname_buf, BUFSIZ);
360	if (0 < sysinfostatus)
361		dname = &dname_buf[0];
362
363	optlist = clientopts_new();
364	if (optlist == NULL) {
365		CLIENT_FPUTS(
366			gettext("Error getting optlist (malloc fail)\n"),
367			stderr);
368		exit(CLIENT_ERR_FAIL);
369	}
370
371	optind = 1;
372	while (optind < argc) {
373		option = getopt(argc, argv, "vqa:I");
374
375		switch (option) {
376		case 'v':
377			mode_verbose = 1;
378			break;
379		case 'q':
380			mode_quiet = 1;
381			break;
382		case 'a':
383			attrVal = NULL;
384			paramFlag = parseParam(optarg, &attrVal);
385			if (paramFlag == CLIENT_ERR_PARSE) {
386				CLIENT_FPRINTF(stderr,
387					gettext("Unrecognized "
388						"parameter \"%s\"\n"),
389					optarg);
390				usage();
391				exit(CLIENT_ERR_FAIL);
392			}
393			retcode = clientSetParam(optlist, paramFlag, attrVal);
394			if (retcode != CLIENT_SUCCESS) {
395				CLIENT_FPRINTF(
396					stderr,
397					gettext("Error (%d) setting "
398						"param \"%s\"\n"),
399					retcode, optarg);
400				usage();
401				exit(CLIENT_ERR_FAIL);
402			}
403			break;
404		case EOF:
405			if (strcmp(argv[optind], "init") == 0) {
406				op_init = 1;
407			} else if (strcmp(argv[optind], "manual") == 0) {
408				op_manual = 1;
409			} else if (strcmp(argv[optind], "mod") == 0) {
410				op_mod = 1;
411			} else if (strcmp(argv[optind], "list") == 0) {
412				op_list = 1;
413			} else if (strcmp(argv[optind], "uninit") == 0) {
414				op_uninit = 1;
415			} else if (strcmp(argv[optind], "genprofile") == 0) {
416				gen = 1;
417				op_genprofile = 1;
418			} else if (optind == argc-1) {
419				retcode = clientSetParam(
420					optlist,
421					NS_LDAP_SERVERS_P,
422					argv[optind]);	/* ipAddr */
423				if (retcode != CLIENT_SUCCESS) {
424					CLIENT_FPRINTF(
425						stderr,
426						gettext("Error (%d) setting "
427							"serverList param.\n"),
428						retcode);
429					usage();
430					exit(CLIENT_ERR_FAIL);
431				}
432			} else {
433				CLIENT_FPUTS(
434					gettext("Error parsing "
435						"command line\n"),
436					stderr);
437				usage();
438				exit(CLIENT_ERR_FAIL);
439			}
440			optind++;	/* get past the verb and keep trying */
441			break;
442		/* Backwards compatibility to support system install */
443		case 'I':
444			sysid_install = B_TRUE;
445			op_init = 1;
446			mode_quiet = 1;
447			break;
448		case '?':
449			usage();
450			CLIENT_FPUTS(gettext("\nOr\n\n"), stderr);
451			gen = 1;
452			usage();
453			exit(CLIENT_ERR_FAIL);
454			break;
455		}
456
457	}
458
459	if ((getuid() != 0) && (!op_genprofile)) {
460		(void) puts(
461			"You must be root (SuperUser) to run this command.");
462		usage();
463		exit(CLIENT_ERR_FAIL);
464	}
465
466/*
467 *	All command line arguments are finished being parsed now
468 */
469
470/* *** Do semantic checking here *** */
471
472/* if gen and no no searchBase then err */
473	if (gen && !optlist->defaultSearchBase) {
474		CLIENT_FPUTS(
475			gettext("ldapclient: Missing required attrName "
476				"defaultSearchBase\n"),
477			stderr);
478		usage();
479		clientopts_free(optlist);
480		exit(CLIENT_ERR_FAIL);
481	}
482
483/* Only one verb can be specified */
484	if ((op_init + op_manual + op_mod + op_uninit +
485		op_list + op_genprofile) != 1) {
486		usage();
487		clientopts_free(optlist);
488		exit(CLIENT_ERR_FAIL);
489	}
490
491/* *** We passed semantic checking, so now do the operation *** */
492
493	if (mode_verbose) {
494		CLIENT_FPUTS(gettext("Arguments parsed:\n"), stderr);
495		dumpargs(optlist);
496	}
497
498
499/* handle "ldapclient list" here.  err checking done in func */
500	if (op_list) {
501		if (mode_verbose)
502			CLIENT_FPUTS(
503				gettext("Handling list option\n"),
504				stderr);
505		retcode = client_list(optlist);
506	}
507
508/* handle "ldapclient uninit" here */
509	if (op_uninit) {
510		if (mode_verbose)
511			CLIENT_FPUTS(
512				gettext("Handling uninit option\n"),
513				stderr);
514		retcode = client_uninit(optlist);
515	}
516
517/* handle "ldapclient init" (profile) */
518	if (op_init) {
519		if (mode_verbose)
520			CLIENT_FPUTS(
521				gettext("Handling init option\n"),
522				stderr);
523		retcode = client_init(optlist);
524	}
525
526/* handle "genprofile" here */
527	if (op_genprofile) {
528		if (mode_verbose)
529			CLIENT_FPUTS(
530				gettext("Handling genProfile\n"),
531				stderr);
532		retcode = client_genProfile(optlist);
533	}
534
535/* handle "ldapclient manual" here */
536	if (op_manual) {
537		if (mode_verbose)
538			CLIENT_FPUTS(
539				gettext("Handling manual option\n"),
540				stderr);
541		retcode = client_manual(optlist);
542	}
543
544/* handle "ldapclient mod" here */
545	if (op_mod) {
546		if (mode_verbose)
547			CLIENT_FPUTS(
548				gettext("Handling mod option\n"),
549				stderr);
550		retcode = client_mod(optlist);
551	}
552
553	clientopts_free(optlist);
554	if ((retcode == CLIENT_SUCCESS) ||
555			(retcode == CLIENT_ERR_FAIL) ||
556			(retcode == CLIENT_ERR_CREDENTIAL))
557		return (retcode);
558	else
559		return (CLIENT_ERR_FAIL);
560}
561
562static int
563client_list(clientopts_t *arglist)
564{
565	ns_ldap_error_t *errorp;
566	int retcode = CLIENT_SUCCESS;
567
568	if (num_args(arglist) > 0) {
569		CLIENT_FPUTS(
570			gettext("No args supported with \"list\" option\n"),
571			stderr);
572		usage();
573		return (CLIENT_ERR_FAIL);	/* exit code here ? */
574	}
575	if ((errorp = __ns_ldap_print_config(mode_verbose)) != NULL) {
576		retcode = CLIENT_ERR_FAIL;
577		CLIENT_FPUTS(
578			gettext("Cannot get print configuration\n"),
579			stderr);
580		CLIENT_FPUTS(errorp->message, stderr);
581		(void) __ns_ldap_freeError(&errorp);
582		CLIENT_FPUTC('\n', stderr);
583	}
584
585	return (retcode);
586}
587
588static int
589client_uninit(clientopts_t *arglist)
590{
591	int retcode = CLIENT_SUCCESS;
592	ns_ldap_self_gssapi_config_t config = NS_LDAP_SELF_GSSAPI_CONFIG_NONE;
593
594	if (mode_verbose) {
595		CLIENT_FPUTS(
596			gettext("Restoring machine to previous "
597				"configuration state\n"),
598			stderr);
599	}
600
601	if (num_args(arglist) > 0) {
602		CLIENT_FPUTS(
603			gettext("No args supported with \"uninit\" option\n"),
604			stderr);
605		usage();
606		return (CLIENT_ERR_FAIL);
607	}
608
609	(void) __ns_ldap_self_gssapi_config(&config);
610
611	retcode = stop_services(STATE_SAVE);
612
613	if (config != NS_LDAP_SELF_GSSAPI_CONFIG_NONE)
614		(void) system("/usr/sbin/cryptoadm enable metaslot");
615
616	if (retcode != CLIENT_SUCCESS) {
617		CLIENT_FPUTS(
618			gettext("Errors stopping network services.\n"), stderr);
619		/* restart whatever services we can */
620		(void) start_services(START_RESET);
621		return (CLIENT_ERR_FAIL);
622	}
623
624	retcode = recover(STATE_SAVE);
625	if (retcode != CLIENT_SUCCESS) {
626		CLIENT_FPUTS(
627			gettext("Cannot recover the configuration on "
628				"this machine.\n"),
629			stderr);
630		(void) start_services(START_RESET);
631	} else {
632		retcode = start_services(START_UNINIT);
633		if (retcode != CLIENT_SUCCESS) {
634			CLIENT_FPUTS(
635				gettext("Config restored but problems "
636					"encountered resetting network "
637					"services.\n"),
638				stderr);
639		}
640	}
641
642	if (retcode == CLIENT_SUCCESS) {
643		CLIENT_FPUTS(
644			gettext("System successfully recovered\n"),
645			stderr);
646	}
647
648	return (retcode);
649}
650
651/*
652 * The following macro is used to do a __ns_ldap_setParam().
653 * On every call, the return code is checked, and if there was
654 * a problem then the error message is printed, the ldaperr
655 * is freed and we return from the function with the offending
656 * error return code.  This macro keeps us from having to
657 * repeat this code for every call to setParam as was done
658 * in the previous incarnation of ldapclient.
659 *
660 * assumes a "retcode" variable is available for status
661 */
662#define	LDAP_SET_PARAM(argval, argdef)	\
663retcode = 0;	\
664if (NULL != argval) {	\
665	ns_ldap_error_t *ldaperr;	\
666	retcode = __ns_ldap_setParam(argdef, (void *)argval, &ldaperr);	\
667	if (retcode != NS_LDAP_SUCCESS) {	\
668		if (NULL != ldaperr) {	\
669			CLIENT_FPUTS(ldaperr->message, stderr);	\
670			CLIENT_FPUTC('\n', stderr);	\
671			(void) __ns_ldap_freeError(&ldaperr);	\
672		}	\
673		return (retcode ? CLIENT_ERR_FAIL : CLIENT_SUCCESS);	\
674	}	\
675}
676
677static int
678client_manual(clientopts_t *arglist)
679{
680	int counter;
681	int domain_fp;
682	ns_ldap_error_t *errorp;
683	int ret_copy;
684	int reset_ret;
685	int retcode = CLIENT_SUCCESS;
686
687	if (dname == NULL) {
688		CLIENT_FPUTS(
689			gettext("Manual failed: System domain not set and "
690				"no domainName specified.\n"),
691			stderr);
692		return (CLIENT_ERR_FAIL);
693	}
694
695	if (arglist->defaultSearchBase == NULL) {
696		CLIENT_FPUTS(
697			gettext("Manual failed: Missing required "
698				"defaultSearchBase attribute.\n"),
699			stderr);
700		return (CLIENT_ERR_FAIL);
701	}
702
703	if ((arglist->defaultServerList == NULL) &&
704		(arglist->preferredServerList == NULL)) {
705		CLIENT_FPUTS(
706			gettext("Manual failed: Missing required "
707				"defaultServerList or preferredServerList "
708				"attribute.\n"),
709			stderr);
710		return (CLIENT_ERR_FAIL);
711	}
712
713	if (arglist->profileTTL != NULL) {
714		CLIENT_FPUTS(
715			gettext("Manual aborted: profileTTL is not supported "
716				"in manual mode.\n"),
717			stderr);
718		return (CLIENT_ERR_FAIL);
719	}
720
721	if (arglist->profileName != NULL) {
722		CLIENT_FPUTS(
723			gettext("Manual aborted: profileName is not supported "
724				"in manual mode.\n"),
725			stderr);
726		return (CLIENT_ERR_FAIL);
727	}
728
729	if (!is_config_ok(arglist, B_FALSE)) {
730		CLIENT_FPRINTF(stderr,
731			gettext("Cannot specify LDAP port with tls\n"));
732		return (CLIENT_ERR_FAIL);
733	}
734
735	__ns_ldap_setServer(TRUE);	/* Need this for _ns_setParam() */
736	__ns_ldap_default_config();
737
738	/* Set version to latest (not version 1) */
739	LDAP_SET_PARAM(NS_LDAP_VERSION, NS_LDAP_FILE_VERSION_P);
740
741	/* Set profileTTL to 0 since NO profile on manual */
742	LDAP_SET_PARAM(CACHETTL_OFF, NS_LDAP_CACHETTL_P);
743
744	/* Set additional valid params from command line */
745	LDAP_SET_PARAM(arglist->authenticationMethod, NS_LDAP_AUTH_P);
746	LDAP_SET_PARAM(arglist->defaultSearchBase, NS_LDAP_SEARCH_BASEDN_P);
747	LDAP_SET_PARAM(arglist->credentialLevel, NS_LDAP_CREDENTIAL_LEVEL_P);
748	LDAP_SET_PARAM(arglist->proxyDN, NS_LDAP_BINDDN_P);
749	LDAP_SET_PARAM(arglist->searchTimeLimit, NS_LDAP_SEARCH_TIME_P);
750	LDAP_SET_PARAM(arglist->preferredServerList, NS_LDAP_SERVER_PREF_P);
751	LDAP_SET_PARAM(arglist->profileName, NS_LDAP_PROFILE_P);
752	LDAP_SET_PARAM(arglist->followReferrals, NS_LDAP_SEARCH_REF_P);
753	LDAP_SET_PARAM(arglist->defaultSearchScope, NS_LDAP_SEARCH_SCOPE_P);
754	LDAP_SET_PARAM(arglist->bindTimeLimit, NS_LDAP_BIND_TIME_P);
755	LDAP_SET_PARAM(arglist->proxyPassword, NS_LDAP_BINDPASSWD_P);
756	LDAP_SET_PARAM(arglist->defaultServerList, NS_LDAP_SERVERS_P);
757	LDAP_SET_PARAM(arglist->certificatePath, NS_LDAP_HOST_CERTPATH_P);
758
759	for (counter = 0;
760		counter < arglist->serviceAuthenticationMethod->count;
761		counter++) {
762
763		LDAP_SET_PARAM(
764			arglist->serviceAuthenticationMethod->optlist[counter],
765			NS_LDAP_SERVICE_AUTH_METHOD_P);
766	}
767	for (counter = 0;
768		counter < arglist->serviceCredentialLevel->count;
769		counter++) {
770
771		LDAP_SET_PARAM(
772			arglist->serviceCredentialLevel->optlist[counter],
773			NS_LDAP_SERVICE_CRED_LEVEL_P);
774	}
775	for (counter = 0;
776		counter < arglist->objectclassMap->count;
777		counter++) {
778
779		LDAP_SET_PARAM(arglist->objectclassMap->optlist[counter],
780			NS_LDAP_OBJECTCLASSMAP_P);
781	}
782	for (counter = 0; counter < arglist->attributeMap->count; counter++) {
783		LDAP_SET_PARAM(arglist->attributeMap->optlist[counter],
784			NS_LDAP_ATTRIBUTEMAP_P);
785	}
786	for (counter = 0;
787		counter < arglist->serviceSearchDescriptor->count;
788		counter++) {
789
790		LDAP_SET_PARAM(
791			arglist->serviceSearchDescriptor->optlist[counter],
792			NS_LDAP_SERVICE_SEARCH_DESC_P);
793	}
794
795	retcode = credCheck(arglist);
796	if (retcode != CLIENT_SUCCESS) {
797		CLIENT_FPUTS(
798			gettext("Error in setting up credentials\n"),
799			stderr);
800		return (retcode);
801	}
802
803	if (mode_verbose)
804		CLIENT_FPUTS(
805			gettext("About to modify this machines "
806				"configuration by writing the files\n"),
807			stderr);
808
809	/* get ready to start playing with files */
810	retcode = stop_services(STATE_SAVE);
811	if (retcode != CLIENT_SUCCESS) {
812		CLIENT_FPUTS(
813			gettext("Errors stopping network services.\n"), stderr);
814		return (CLIENT_ERR_FAIL);
815	}
816
817	/* Save orig versions of files */
818	retcode = file_backup();
819	if (retcode == CLIENT_ERR_RESTORE) {
820		CLIENT_FPUTS(
821			gettext("System not in state to enable ldap client.\n"),
822			stderr);
823
824		reset_ret = start_services(START_RESET);
825		if (reset_ret != CLIENT_SUCCESS) {
826			CLIENT_FPRINTF(stderr, gettext("Error (%d) while "
827					"starting services during reset\n"),
828					reset_ret);
829		}
830		return (retcode);
831	} else if (retcode != CLIENT_SUCCESS) {
832		CLIENT_FPUTS(
833			gettext("Save of system configuration failed!  "
834				"Attempting recovery.\n"),
835			stderr);
836		retcode = recover(STATE_NOSAVE);
837		if (retcode != CLIENT_SUCCESS) {
838			CLIENT_FPUTS(
839				gettext("Recovery of systems configuration "
840					"failed.  Manual intervention of "
841					"config files is required.\n"),
842				stderr);
843			return (retcode);
844		}
845
846		reset_ret = start_services(START_RESET);
847		if (reset_ret != CLIENT_SUCCESS) {
848			CLIENT_FPRINTF(stderr, gettext("Error (%d) while "
849					"starting services during reset\n"),
850					reset_ret);
851		}
852
853		return (retcode);
854	}
855
856	/* Dump new files */
857	errorp = __ns_ldap_DumpConfiguration(NSCONFIGFILE);
858	if (errorp != NULL) {
859		CLIENT_FPRINTF(stderr,
860			gettext("%s manual: errorp is not NULL; %s\n"),
861			cmd, errorp->message);
862		retcode = recover(STATE_NOSAVE);
863		if (retcode != CLIENT_SUCCESS) {
864			CLIENT_FPUTS(
865				gettext("Recovery of systems configuration "
866					"failed.  Manual intervention of "
867					"config files is required.\n"),
868				stderr);
869			return (retcode);
870		}
871		reset_ret = start_services(START_RESET);
872		if (reset_ret != CLIENT_SUCCESS) {
873			CLIENT_FPRINTF(stderr, gettext("Error (%d) while "
874					"starting services during reset\n"),
875					reset_ret);
876		}
877		(void) __ns_ldap_freeError(&errorp);
878		return (CLIENT_ERR_FAIL);
879	}
880
881	/* if (credargs(arglist)) */
882	errorp = __ns_ldap_DumpConfiguration(NSCREDFILE);
883	if (errorp != NULL) {
884		CLIENT_FPRINTF(stderr,
885			gettext("%s init: errorp is not NULL; %s\n"),
886			cmd, errorp->message);
887		retcode = recover(STATE_NOSAVE);
888		if (retcode != CLIENT_SUCCESS) {
889			CLIENT_FPUTS(
890				gettext("Recovery of systems configuration "
891					"failed.  Manual intervention of "
892					"config files is required.\n"),
893				stderr);
894			return (retcode);
895		}
896		reset_ret = start_services(START_RESET);
897		if (reset_ret != CLIENT_SUCCESS) {
898			CLIENT_FPRINTF(stderr, gettext("Error (%d) while "
899					"starting services during reset\n"),
900					reset_ret);
901		}
902		(void) __ns_ldap_freeError(&errorp);
903		return (CLIENT_ERR_FAIL);
904	}
905
906	ret_copy = system(CMD_CP " " NSSWITCH_LDAP " " NSSWITCH_CONF);
907	if (ret_copy != 0) {
908		CLIENT_FPRINTF(stderr,
909			gettext("Error %d copying (%s) -> (%s)\n"),
910			ret_copy, NSSWITCH_LDAP, NSSWITCH_CONF);
911		retcode = recover(STATE_NOSAVE);
912		if (retcode != CLIENT_SUCCESS) {
913			CLIENT_FPUTS(
914				gettext("Recovery of systems configuration "
915					"failed.  Manual intervention of "
916					"config files is required.\n"),
917				stderr);
918		}
919		reset_ret = start_services(START_RESET);
920		if (reset_ret != CLIENT_SUCCESS) {
921			CLIENT_FPRINTF(stderr, gettext("Error (%d) while "
922					"starting services during reset\n"),
923					reset_ret);
924		}
925		return (CLIENT_ERR_FAIL);
926	}
927
928	if ((domain_fp = open(DOMAINNAME, O_WRONLY|O_CREAT|O_TRUNC,
929		S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)) == -1) { /* 0644 */
930		CLIENT_FPRINTF(stderr, gettext("Cannot open %s\n"), DOMAINNAME);
931		retcode = recover(STATE_NOSAVE);
932		if (retcode != CLIENT_SUCCESS) {
933			CLIENT_FPUTS(
934				gettext("Recovery of systems configuration "
935					"failed.  Manual intervention of "
936					"config files is required.\n"),
937				stderr);
938			return (CLIENT_ERR_FAIL);
939		}
940		reset_ret = start_services(START_RESET);
941		if (reset_ret != CLIENT_SUCCESS) {
942			CLIENT_FPRINTF(stderr, gettext("Error (%d) while "
943					"starting services during reset\n"),
944					reset_ret);
945		}
946		return (CLIENT_ERR_FAIL);
947	}
948	(void) write(domain_fp, dname, strlen(dname));
949	(void) write(domain_fp, "\n", 1);
950	(void) close(domain_fp);
951
952	retcode = start_services(START_INIT);
953
954	if (retcode == CLIENT_SUCCESS) {
955		CLIENT_FPUTS(gettext("System successfully configured\n"),
956								stderr);
957	} else {
958		CLIENT_FPUTS(gettext("Error resetting system.\n"
959			"Recovering old system settings.\n"), stderr),
960
961		/* stop any started services for recover */
962		/* don't stomp on history of saved services state */
963		reset_ret = stop_services(STATE_NOSAVE);
964		if (reset_ret != CLIENT_SUCCESS) {
965			CLIENT_FPRINTF(stderr, gettext("Error (%d) while "
966					"stopping services during reset\n"),
967					reset_ret);
968			/* Coninue and try to recover what we can */
969		}
970		reset_ret = recover(STATE_NOSAVE);
971		if (reset_ret != CLIENT_SUCCESS) {
972			CLIENT_FPRINTF(stderr, gettext("Error (%d) while "
973					"recovering service files during "
974					"reset\n"), reset_ret);
975			/* Continue and start what we can */
976		}
977		reset_ret = start_services(START_RESET);
978		if (reset_ret != CLIENT_SUCCESS) {
979			CLIENT_FPRINTF(stderr, gettext("Error (%d) while "
980					"starting services during reset\n"),
981					reset_ret);
982		}
983	}
984
985	return (retcode);
986}
987
988static int
989client_mod(clientopts_t *arglist)
990{
991	int counter;
992	int domain_fp;
993	ns_ldap_error_t *errorp;
994	int reset_ret;
995	int retcode = CLIENT_SUCCESS;
996
997	__ns_ldap_setServer(TRUE);	/* Need this for _ns_setParam() */
998	if ((errorp = __ns_ldap_LoadConfiguration()) != NULL) {
999		CLIENT_FPUTS(gettext("Cannot get load configuration\n"),
1000			stderr);
1001		CLIENT_FPUTS(errorp->message, stderr);
1002		CLIENT_FPUTC('\n', stderr);
1003		(void) __ns_ldap_freeError(&errorp);
1004		return (CLIENT_ERR_FAIL);
1005	}
1006
1007	if (arglist->profileTTL != NULL) {
1008		CLIENT_FPUTS(
1009			gettext("Mod aborted: profileTTL modification is "
1010				"not allowed in mod mode.\n"),
1011			stderr);
1012		return (CLIENT_ERR_FAIL);
1013	}
1014
1015	if (arglist->profileName != NULL) {
1016		CLIENT_FPUTS(
1017			gettext("Mod aborted: profileName modification is "
1018				"not allowed.  If you want to use profiles "
1019				"generate one with genProfile and load it "
1020				"on the server with ldapadd.\n"),
1021			stderr);
1022		return (CLIENT_ERR_FAIL);
1023	}
1024
1025	if (!is_config_ok(arglist, B_TRUE)) {
1026		CLIENT_FPRINTF(stderr,
1027			gettext("Cannot specify LDAP port with tls\n"));
1028		return (CLIENT_ERR_FAIL);
1029	}
1030
1031	/* Set additional valid params from command line */
1032	LDAP_SET_PARAM(arglist->authenticationMethod, NS_LDAP_AUTH_P);
1033	LDAP_SET_PARAM(arglist->defaultSearchBase, NS_LDAP_SEARCH_BASEDN_P);
1034	LDAP_SET_PARAM(arglist->credentialLevel, NS_LDAP_CREDENTIAL_LEVEL_P);
1035	LDAP_SET_PARAM(arglist->proxyDN, NS_LDAP_BINDDN_P);
1036	LDAP_SET_PARAM(arglist->profileTTL, NS_LDAP_CACHETTL_P);
1037	LDAP_SET_PARAM(arglist->searchTimeLimit, NS_LDAP_SEARCH_TIME_P);
1038	LDAP_SET_PARAM(arglist->preferredServerList, NS_LDAP_SERVER_PREF_P);
1039	LDAP_SET_PARAM(arglist->profileName, NS_LDAP_PROFILE_P);
1040	LDAP_SET_PARAM(arglist->followReferrals, NS_LDAP_SEARCH_REF_P);
1041	LDAP_SET_PARAM(arglist->defaultSearchScope, NS_LDAP_SEARCH_SCOPE_P);
1042	LDAP_SET_PARAM(arglist->bindTimeLimit, NS_LDAP_BIND_TIME_P);
1043	LDAP_SET_PARAM(arglist->proxyPassword, NS_LDAP_BINDPASSWD_P);
1044	LDAP_SET_PARAM(arglist->defaultServerList, NS_LDAP_SERVERS_P);
1045	LDAP_SET_PARAM(arglist->certificatePath, NS_LDAP_HOST_CERTPATH_P);
1046
1047	for (counter = 0;
1048		counter < arglist->serviceAuthenticationMethod->count;
1049		counter++) {
1050
1051		LDAP_SET_PARAM(
1052			arglist->serviceAuthenticationMethod->optlist[counter],
1053			NS_LDAP_SERVICE_AUTH_METHOD_P);
1054	}
1055	for (counter = 0;
1056		counter < arglist->serviceCredentialLevel->count;
1057		counter++) {
1058
1059		LDAP_SET_PARAM(
1060			arglist->serviceCredentialLevel->optlist[counter],
1061			NS_LDAP_SERVICE_CRED_LEVEL_P);
1062	}
1063	for (counter = 0;
1064		counter < arglist->objectclassMap->count;
1065		counter++) {
1066
1067		LDAP_SET_PARAM(
1068			arglist->objectclassMap->optlist[counter],
1069			NS_LDAP_OBJECTCLASSMAP_P);
1070	}
1071	for (counter = 0;
1072		counter < arglist->attributeMap->count;
1073		counter++) {
1074
1075		LDAP_SET_PARAM(
1076			arglist->attributeMap->optlist[counter],
1077			NS_LDAP_ATTRIBUTEMAP_P);
1078	}
1079	for (counter = 0;
1080		counter < arglist->serviceSearchDescriptor->count;
1081		counter++) {
1082
1083		LDAP_SET_PARAM(
1084			arglist->serviceSearchDescriptor->optlist[counter],
1085			NS_LDAP_SERVICE_SEARCH_DESC_P);
1086	}
1087
1088	retcode = credCheck(arglist);
1089	if (retcode != CLIENT_SUCCESS) {
1090		CLIENT_FPUTS(
1091			gettext("Error in setting up credentials\n"),
1092			stderr);
1093		return (retcode);
1094	}
1095
1096	if (mode_verbose)
1097		CLIENT_FPUTS(
1098			gettext("About to modify this machines configuration "
1099				"by writing the files\n"),
1100			stderr);
1101
1102	/* get ready to start playing with files */
1103	retcode = stop_services(STATE_SAVE);
1104	if (retcode != CLIENT_SUCCESS) {
1105		CLIENT_FPUTS(
1106			gettext("Errors stopping network services.\n"), stderr);
1107		return (CLIENT_ERR_FAIL);
1108	}
1109
1110	/* Temporarily save orig versions of files */
1111	retcode = mod_backup();
1112	if (retcode != CLIENT_SUCCESS) {
1113		CLIENT_FPUTS(
1114			gettext("Unable to backup the ldap client files!\n"),
1115			stderr);
1116
1117		return (retcode);
1118
1119	}
1120
1121	/* Dump new files */
1122	errorp = __ns_ldap_DumpConfiguration(NSCONFIGFILE);
1123	if (errorp != NULL) {
1124		CLIENT_FPRINTF(stderr,
1125			gettext("%s mod: errorp is not NULL; %s\n"),
1126			cmd, errorp->message);
1127		retcode = mod_recover();
1128		if (retcode != CLIENT_SUCCESS) {
1129			CLIENT_FPUTS(
1130				gettext("Recovery of systems configuration "
1131					"failed.  Manual intervention of "
1132					"config files is required.\n"),
1133				stderr);
1134		}
1135		(void) __ns_ldap_freeError(&errorp);
1136		reset_ret = start_services(START_RESET);
1137		if (reset_ret != CLIENT_SUCCESS) {
1138			CLIENT_FPRINTF(stderr, gettext("Error (%d) while "
1139					"starting services during reset\n"),
1140					reset_ret);
1141		}
1142		return (CLIENT_ERR_FAIL);
1143	}
1144
1145	/* if (credargs(arglist)) */
1146	errorp = __ns_ldap_DumpConfiguration(NSCREDFILE);
1147	if (errorp != NULL) {
1148		CLIENT_FPRINTF(stderr,
1149			gettext("%s mod: errorp is not NULL; %s\n"),
1150			cmd, errorp->message);
1151		retcode = mod_recover();
1152		if (retcode != CLIENT_SUCCESS) {
1153			CLIENT_FPUTS(
1154				gettext("Recovery of systems configuration "
1155					"failed.  Manual intervention of "
1156					"config files is required.\n"),
1157				stderr);
1158		}
1159		(void) __ns_ldap_freeError(&errorp);
1160		reset_ret = start_services(START_RESET);
1161		if (reset_ret != CLIENT_SUCCESS) {
1162			CLIENT_FPRINTF(stderr, gettext("Error (%d) while "
1163					"starting services during reset\n"),
1164					reset_ret);
1165		}
1166		return (CLIENT_ERR_FAIL);
1167	}
1168
1169	if ((domain_fp = open(DOMAINNAME, O_WRONLY|O_CREAT|O_TRUNC,
1170		S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)) == -1) { /* 0644 */
1171		CLIENT_FPRINTF(stderr, gettext("Cannot open %s\n"), DOMAINNAME);
1172		retcode = mod_recover();
1173		if (retcode != CLIENT_SUCCESS) {
1174			CLIENT_FPUTS(
1175				gettext("Recovery of systems configuration "
1176					"failed!  Machine needs to be "
1177					"fixed!\n"),
1178				stderr);
1179		}
1180		reset_ret = start_services(START_RESET);
1181		if (reset_ret != CLIENT_SUCCESS) {
1182			CLIENT_FPRINTF(stderr, gettext("Error (%d) while "
1183					"starting services during reset\n"),
1184					reset_ret);
1185		}
1186		return (CLIENT_ERR_FAIL);
1187	}
1188	(void) write(domain_fp, dname, strlen(dname));
1189	(void) write(domain_fp, "\n", 1);
1190	(void) close(domain_fp);
1191
1192	retcode = start_services(START_INIT);
1193
1194	if (retcode == CLIENT_SUCCESS) {
1195		CLIENT_FPUTS(gettext("System successfully configured\n"),
1196								stderr);
1197	} else {
1198		CLIENT_FPUTS(gettext("Error resetting system.\n"
1199			"Recovering old system settings.\n"), stderr),
1200
1201		/* stop any started services for recover */
1202		/* don't stomp on history of saved services state */
1203		reset_ret = stop_services(STATE_NOSAVE);
1204		if (reset_ret != CLIENT_SUCCESS) {
1205			CLIENT_FPRINTF(stderr, gettext("Error (%d) while "
1206					"stopping services during reset\n"),
1207					reset_ret);
1208			/* Coninue and try to recover what we can */
1209		}
1210		reset_ret = mod_recover();
1211		if (reset_ret != CLIENT_SUCCESS) {
1212			CLIENT_FPRINTF(stderr, gettext("Error (%d) while "
1213					"recovering service files during "
1214					"reset\n"), reset_ret);
1215			/* Continue and start what we can */
1216		}
1217		reset_ret = start_services(START_RESET);
1218		if (reset_ret != CLIENT_SUCCESS) {
1219			CLIENT_FPRINTF(stderr, gettext("Error (%d) while "
1220					"starting services during reset\n"),
1221					reset_ret);
1222		}
1223	}
1224
1225	/* Cleanup temporary files created by mod_backup() */
1226	mod_cleanup();
1227
1228	return (retcode);
1229}
1230
1231
1232/*
1233 * The following macro is used to check if an arg has already been set
1234 * and issues an error message, a usage message and then returns an error.
1235 * This was made into a macro to avoid the duplication of this code many
1236 * times in the function below.
1237 */
1238#define	LDAP_CHECK_INVALID(arg, param)	\
1239if (arg) {	\
1240	CLIENT_FPRINTF(stderr, gettext("Invalid parameter (%s) " \
1241		"specified\n"), param);	\
1242	usage();	\
1243	return (CLIENT_ERR_FAIL);	\
1244}
1245
1246static int
1247client_genProfile(clientopts_t *arglist)
1248{
1249	int counter;
1250	int retcode;	/* required for LDAP_SET_PARAM macro */
1251	ns_ldap_error_t *errorp;
1252
1253	if (mode_verbose)
1254		CLIENT_FPUTS(gettext("About to generate a profile\n"), stderr);
1255
1256	/* *** Check for invalid args *** */
1257	LDAP_CHECK_INVALID(arglist->proxyDN, "proxyDN");
1258	LDAP_CHECK_INVALID(arglist->proxyPassword, "proxyPassword");
1259	LDAP_CHECK_INVALID(arglist->certificatePath, "certificatePath");
1260	LDAP_CHECK_INVALID(arglist->domainName, "domainName");
1261	/* *** End check for invalid args *** */
1262
1263	if (arglist->profileName == NULL) {
1264		if (mode_verbose)
1265			CLIENT_FPUTS(
1266				gettext("No profile specified. "
1267					"Using \"default\"\n"),
1268				stderr);
1269		arglist->profileName = "default";
1270	}
1271
1272	__ns_ldap_setServer(TRUE);
1273	__ns_ldap_default_config();
1274
1275	/* Set version to latest (not version 1) */
1276	LDAP_SET_PARAM(NS_LDAP_VERSION, NS_LDAP_FILE_VERSION_P);
1277
1278	/* Set additional valid params from command line */
1279	LDAP_SET_PARAM(arglist->authenticationMethod, NS_LDAP_AUTH_P);
1280	LDAP_SET_PARAM(arglist->defaultSearchBase, NS_LDAP_SEARCH_BASEDN_P);
1281	LDAP_SET_PARAM(arglist->credentialLevel, NS_LDAP_CREDENTIAL_LEVEL_P);
1282	LDAP_SET_PARAM(arglist->profileTTL, NS_LDAP_CACHETTL_P);
1283	LDAP_SET_PARAM(arglist->searchTimeLimit, NS_LDAP_SEARCH_TIME_P);
1284	LDAP_SET_PARAM(arglist->preferredServerList, NS_LDAP_SERVER_PREF_P);
1285	LDAP_SET_PARAM(arglist->profileName, NS_LDAP_PROFILE_P);
1286	LDAP_SET_PARAM(arglist->followReferrals, NS_LDAP_SEARCH_REF_P);
1287	LDAP_SET_PARAM(arglist->defaultSearchScope, NS_LDAP_SEARCH_SCOPE_P);
1288	LDAP_SET_PARAM(arglist->bindTimeLimit, NS_LDAP_BIND_TIME_P);
1289	LDAP_SET_PARAM(arglist->defaultServerList, NS_LDAP_SERVERS_P);
1290
1291	for (counter = 0;
1292		counter < arglist->serviceAuthenticationMethod->count;
1293		counter++) {
1294
1295		LDAP_SET_PARAM(
1296			arglist->serviceAuthenticationMethod->optlist[counter],
1297			NS_LDAP_SERVICE_AUTH_METHOD_P);
1298	}
1299	for (counter = 0;
1300		counter < arglist->serviceCredentialLevel->count;
1301		counter++) {
1302
1303		LDAP_SET_PARAM(
1304			arglist->serviceCredentialLevel->optlist[counter],
1305			NS_LDAP_SERVICE_CRED_LEVEL_P);
1306	}
1307	for (counter = 0;
1308		counter < arglist->objectclassMap->count;
1309		counter++) {
1310
1311		LDAP_SET_PARAM(
1312			arglist->objectclassMap->optlist[counter],
1313			NS_LDAP_OBJECTCLASSMAP_P);
1314	}
1315	for (counter = 0;
1316		counter < arglist->attributeMap->count;
1317		counter++) {
1318
1319		LDAP_SET_PARAM(
1320			arglist->attributeMap->optlist[counter],
1321			NS_LDAP_ATTRIBUTEMAP_P);
1322	}
1323	for (counter = 0;
1324		counter < arglist->serviceSearchDescriptor->count;
1325		counter++) {
1326
1327		LDAP_SET_PARAM(
1328			arglist->serviceSearchDescriptor->optlist[counter],
1329			NS_LDAP_SERVICE_SEARCH_DESC_P);
1330	}
1331
1332	if (!is_config_ok(arglist, B_FALSE)) {
1333		CLIENT_FPRINTF(stderr,
1334			gettext("WARNING: some clients do not support an LDAP "
1335				"port with tls\n"));
1336	}
1337
1338	errorp = __ns_ldap_DumpLdif(NULL);
1339	if (errorp != NULL) {
1340		CLIENT_FPUTS(errorp->message, stderr);
1341		CLIENT_FPUTC('\n', stderr);
1342		(void) __ns_ldap_freeError(&errorp);
1343		return (CLIENT_ERR_FAIL);
1344	}
1345
1346	return (CLIENT_SUCCESS);
1347}
1348
1349static int
1350client_init(clientopts_t *arglist)
1351{
1352	int profile_fp;
1353	int retcode = CLIENT_SUCCESS;
1354	char *nisBaseDN = NULL;
1355	ns_ldap_error_t *errorp;
1356	int reset_ret;
1357	int ret_copy;
1358
1359	if (mode_verbose)
1360		CLIENT_FPUTS(
1361			gettext("About to configure machine by downloading "
1362				"a profile\n"),
1363			stderr);
1364
1365	if (dname == NULL) {
1366		CLIENT_FPUTS(
1367			gettext("Init failed: System domain not set and "
1368				"no domainName specified.\n"),
1369			stderr);
1370		return (CLIENT_ERR_FAIL);
1371	}
1372
1373	if (!arglist->defaultServerList) {
1374		CLIENT_FPUTS(gettext("Missing LDAP server address\n"), stderr);
1375		return (CLIENT_ERR_FAIL);
1376	}
1377
1378	/* *** Check for invalid args *** */
1379	LDAP_CHECK_INVALID(arglist->authenticationMethod,
1380		"authenticationMethod");
1381	LDAP_CHECK_INVALID(arglist->defaultSearchBase,
1382		"defaultSearchBase");
1383	LDAP_CHECK_INVALID(arglist->credentialLevel,
1384		"credentialLevel");
1385	LDAP_CHECK_INVALID(arglist->profileTTL,
1386		"profileTTL");
1387	LDAP_CHECK_INVALID(arglist->searchTimeLimit,
1388		"searchTimeLimit");
1389	LDAP_CHECK_INVALID(arglist->preferredServerList,
1390		"preferredServerList");
1391	LDAP_CHECK_INVALID(arglist->followReferrals,
1392		"followReferrals");
1393	LDAP_CHECK_INVALID(arglist->defaultSearchScope,
1394		"defaultSearchScope");
1395	LDAP_CHECK_INVALID(arglist->bindTimeLimit,
1396		"bindTimeLimit");
1397
1398	LDAP_CHECK_INVALID(arglist->objectclassMap->count,
1399		"objectclassMap");
1400	LDAP_CHECK_INVALID(arglist->attributeMap->count,
1401		"attributeMap");
1402	LDAP_CHECK_INVALID(arglist->serviceAuthenticationMethod->count,
1403		"serviceAuthenticationMethod");
1404	LDAP_CHECK_INVALID(arglist->serviceCredentialLevel->count,
1405		"serviceCredentialLevel");
1406	LDAP_CHECK_INVALID(arglist->serviceSearchDescriptor->count,
1407		"serviceSearchDescriptor");
1408	/* *** End check for invalid args *** */
1409
1410	__ns_ldap_setServer(TRUE);
1411
1412	if (arglist->profileName == NULL) {
1413		if (mode_verbose)
1414			CLIENT_FPUTS(
1415				gettext("No profile specified. "
1416					"Using \"default\"\n"),
1417				stderr);
1418		arglist->profileName = "default";
1419	}
1420
1421	/* need to free nisBaseDN */
1422	nisBaseDN = findBaseDN(arglist->defaultServerList);
1423	if (nisBaseDN == NULL) {
1424		CLIENT_FPRINTF(stderr,
1425			gettext("Failed to find defaultSearchBase for "
1426				"domain %s\n"),
1427			dname);
1428
1429		if (gStartLdap == START_RESET)
1430			(void) start_service(LDAP_FMRI, B_TRUE);
1431
1432		return (CLIENT_ERR_FAIL);
1433	}
1434	retcode = __ns_ldap_setParam(
1435			NS_LDAP_SEARCH_BASEDN_P,
1436			(void *)nisBaseDN,
1437			&errorp);
1438	if (retcode != 0) {
1439		CLIENT_FPUTS(
1440			gettext("Unable to set search baseDN.\n"), stderr);
1441		/* non-fatal */
1442	}
1443
1444	LDAP_SET_PARAM(arglist->defaultServerList, NS_LDAP_SERVERS_P);
1445	if (retcode != 0) {
1446		CLIENT_FPUTS(
1447			gettext("Unable to set server address.\n"), stderr);
1448		/* non-fatal */
1449	}
1450
1451	/* Get and set profile params */
1452	retcode = __ns_ldap_download(
1453			(const char *)arglist->profileName,
1454			arglist->defaultServerList,
1455			nisBaseDN,
1456			&errorp);
1457	if (retcode != NS_LDAP_SUCCESS) {
1458		CLIENT_FPRINTF(stderr,
1459			gettext("The download of the profile failed.\n"));
1460		if (errorp != NULL) {
1461			CLIENT_FPRINTF(stderr, "%s\n", errorp->message);
1462			(void) __ns_ldap_freeError(&errorp);
1463		} else if (retcode == NS_LDAP_NOTFOUND) {
1464			CLIENT_FPRINTF(stderr,
1465			gettext("Could not read the profile '%s'.\n"
1466				"Perhaps it does not exist or you don't "
1467				"have sufficient rights to read it.\n"),
1468				arglist->profileName);
1469		}
1470
1471		if (gStartLdap == START_RESET)
1472			(void) start_service(LDAP_FMRI, B_TRUE);
1473
1474		return (CLIENT_ERR_FAIL);
1475	}
1476
1477	/* Set additional valid params from command line */
1478	/* note that the domainName is not used in setParam */
1479	LDAP_SET_PARAM(arglist->proxyDN, NS_LDAP_BINDDN_P);
1480	if (retcode != 0) {
1481		CLIENT_FPUTS(gettext("setParam proxyDN failed.\n"), stderr);
1482		/* non-fatal */
1483	}
1484	LDAP_SET_PARAM(arglist->proxyPassword, NS_LDAP_BINDPASSWD_P);
1485	if (retcode != 0) {
1486		CLIENT_FPUTS(
1487			gettext("setParam proxyPassword failed.\n"), stderr);
1488		/* non-fatal */
1489	}
1490	LDAP_SET_PARAM(arglist->certificatePath, NS_LDAP_HOST_CERTPATH_P);
1491
1492	retcode = credCheck(arglist);
1493	if (retcode != CLIENT_SUCCESS) {
1494		CLIENT_FPUTS(
1495			gettext("Error in setting up credentials\n"), stderr);
1496
1497		if (gStartLdap == START_RESET)
1498			(void) start_service(LDAP_FMRI, B_TRUE);
1499
1500		return (retcode);
1501	}
1502
1503	if (mode_verbose)
1504		CLIENT_FPUTS(
1505			gettext("About to modify this machines configuration "
1506				"by writing the files\n"),
1507			stderr);
1508
1509	/* get ready to start playing with files */
1510	retcode = stop_services(STATE_SAVE);
1511	if (retcode != CLIENT_SUCCESS) {
1512		CLIENT_FPUTS(
1513			gettext("Errors stopping network services.\n"), stderr);
1514
1515		if (gStartLdap == START_RESET)
1516			(void) start_service(LDAP_FMRI, B_TRUE);
1517
1518		return (CLIENT_ERR_FAIL);
1519	}
1520
1521	/* Save orig versions of files */
1522	retcode = file_backup();
1523	if (retcode == CLIENT_ERR_RESTORE) {
1524		CLIENT_FPUTS(
1525			gettext("System not in state to enable ldap client.\n"),
1526			stderr);
1527
1528		return (retcode);
1529
1530	} else if (retcode != CLIENT_SUCCESS) {
1531		CLIENT_FPUTS(
1532			gettext("Save of system configuration failed.  "
1533				"Attempting recovery.\n"),
1534			stderr);
1535		retcode = recover(STATE_NOSAVE);
1536		if (retcode != CLIENT_SUCCESS) {
1537			CLIENT_FPUTS(
1538				gettext("Recovery of systems configuration "
1539					"failed.  Manual intervention of "
1540					"config files is required.\n"),
1541				stderr);
1542		}
1543
1544		reset_ret = start_services(START_RESET);
1545		if (reset_ret != CLIENT_SUCCESS) {
1546			CLIENT_FPRINTF(stderr, gettext("Error (%d) while "
1547					"starting services during reset\n"),
1548					reset_ret);
1549		}
1550
1551		return (retcode);
1552	}
1553
1554	/* Dump new files */
1555	errorp = __ns_ldap_DumpConfiguration(NSCONFIGFILE);
1556	if (NULL != errorp) {
1557		CLIENT_FPRINTF(stderr,
1558			gettext("%s init: errorp is not NULL; %s\n"),
1559			cmd, errorp->message);
1560		retcode = recover(STATE_NOSAVE);
1561		if (retcode != CLIENT_SUCCESS) {
1562			CLIENT_FPUTS(
1563				gettext("Recovery of systems configuration "
1564					"failed.  Manual intervention of "
1565					"config files is required.\n"),
1566				stderr);
1567			return (CLIENT_ERR_FAIL);
1568		}
1569		(void) __ns_ldap_freeError(&errorp);
1570		reset_ret = start_services(START_RESET);
1571		if (reset_ret != CLIENT_SUCCESS) {
1572			CLIENT_FPRINTF(stderr, gettext("Error (%d) while "
1573					"starting services during reset\n"),
1574					reset_ret);
1575		}
1576		return (CLIENT_ERR_FAIL);
1577	}
1578
1579	/* if (credargs(arglist)) */
1580	errorp = __ns_ldap_DumpConfiguration(NSCREDFILE);
1581	if (NULL != errorp) {
1582		CLIENT_FPRINTF(stderr,
1583			gettext("%s init: errorp is not NULL; %s\n"),
1584			cmd, errorp->message);
1585		retcode = recover(STATE_NOSAVE);
1586		if (retcode != CLIENT_SUCCESS) {
1587			CLIENT_FPUTS(
1588				gettext("Recovery of systems configuration "
1589					"failed.  Manual intervention of "
1590					"config files is required.\n"),
1591				stderr);
1592			return (CLIENT_ERR_FAIL);
1593		}
1594		(void) __ns_ldap_freeError(&errorp);
1595		reset_ret = start_services(START_RESET);
1596		if (reset_ret != CLIENT_SUCCESS) {
1597			CLIENT_FPRINTF(stderr, gettext("Error (%d) while "
1598					"starting services during reset\n"),
1599					reset_ret);
1600		}
1601		return (CLIENT_ERR_FAIL);
1602	}
1603
1604	ret_copy = system(CMD_CP " " NSSWITCH_LDAP " " NSSWITCH_CONF);
1605	if (ret_copy != 0) {
1606		CLIENT_FPRINTF(stderr,
1607			gettext("Error %d copying (%s) -> (%s)\n"),
1608			ret_copy, NSSWITCH_LDAP, NSSWITCH_CONF);
1609		retcode = recover(STATE_NOSAVE);
1610		if (retcode != CLIENT_SUCCESS) {
1611			CLIENT_FPUTS(
1612				gettext("Recovery of systems configuration "
1613					"failed.  Manual intervention of "
1614					"config files is required.\n"),
1615				stderr);
1616		}
1617		reset_ret = start_services(START_RESET);
1618		if (reset_ret != CLIENT_SUCCESS) {
1619			CLIENT_FPRINTF(stderr, gettext("Error (%d) while "
1620					"starting services during reset\n"),
1621					reset_ret);
1622		}
1623		return (CLIENT_ERR_FAIL);
1624	}
1625
1626	if ((profile_fp = open(DOMAINNAME, O_WRONLY|O_CREAT|O_TRUNC,
1627		S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)) == -1) { /* 0644 */
1628		CLIENT_FPRINTF(stderr, gettext("Cannot open %s\n"), DOMAINNAME);
1629		retcode = recover(STATE_NOSAVE);
1630		if (retcode != CLIENT_SUCCESS) {
1631			CLIENT_FPUTS(
1632				gettext("Recovery of systems configuration "
1633					"failed.  Manual intervention of "
1634					"config files is required.\n"),
1635				stderr);
1636			return (CLIENT_ERR_FAIL);
1637		}
1638		reset_ret = start_services(START_RESET);
1639		if (reset_ret != CLIENT_SUCCESS) {
1640			CLIENT_FPRINTF(stderr, gettext("Error (%d) while "
1641					"starting services during reset\n"),
1642					reset_ret);
1643		}
1644		return (CLIENT_ERR_FAIL);
1645	}
1646	(void) write(profile_fp, dname, strlen(dname));
1647	(void) write(profile_fp, "\n", 1);
1648	(void) close(profile_fp);
1649
1650	retcode = start_services(START_INIT);
1651
1652	if (retcode == CLIENT_SUCCESS) {
1653		CLIENT_FPUTS(gettext("System successfully configured\n"),
1654								stderr);
1655	} else {
1656		CLIENT_FPUTS(gettext("Error resetting system.\n"
1657			"Recovering old system settings.\n"), stderr),
1658
1659		/* stop any started services for recover */
1660		/* don't stomp on history of saved services state */
1661		reset_ret = stop_services(STATE_NOSAVE);
1662		if (reset_ret != CLIENT_SUCCESS) {
1663			CLIENT_FPRINTF(stderr, gettext("Error (%d) while "
1664					"stopping services during reset\n"),
1665					reset_ret);
1666			/* Coninue and try to recover what we can */
1667		}
1668		reset_ret = recover(STATE_NOSAVE);
1669		if (reset_ret != CLIENT_SUCCESS) {
1670			CLIENT_FPRINTF(stderr, gettext("Error (%d) while "
1671					"recovering service files during "
1672					"reset\n"), reset_ret);
1673			/* Continue and start what we can */
1674		}
1675		reset_ret = start_services(START_RESET);
1676		if (reset_ret != CLIENT_SUCCESS) {
1677			CLIENT_FPRINTF(stderr, gettext("Error (%d) while "
1678					"starting services during reset\n"),
1679					reset_ret);
1680		}
1681	}
1682
1683	return (retcode);
1684}
1685
1686
1687static void
1688usage(void)
1689{
1690	if (mode_quiet)
1691		return;
1692
1693	if (gen == 0) {
1694		CLIENT_FPRINTF(stderr,
1695			gettext("Usage: %s [-v | -q] init | manual | mod | "
1696				"list | uninit [<args>]\n"),
1697			cmd);
1698
1699		CLIENT_FPUTS(
1700			gettext("\nSet up a server or workstation as a "
1701				"client of an LDAP namespace.\n"),
1702			stderr);
1703	} else {	/* genprofile */
1704		CLIENT_FPRINTF(stderr,
1705			gettext("Usage: %s [-v | -q] genprofile "
1706				"-a profileName=<name> "
1707				"-a defaultSearchBase=<base> <args>\n"),
1708			cmd);
1709
1710		CLIENT_FPUTS(
1711			gettext("\nGenerate a profile used to set up clients "
1712				"of an LDAP namespace.\n"),
1713			stderr);
1714	}
1715	CLIENT_FPUTS(
1716		gettext("<args> take the form of \'-a attrName=attrVal\' as "
1717			"described in the\n"),
1718		stderr);
1719	CLIENT_FPUTS(gettext("man page: ldapclient(1M)\n"), stderr);
1720}
1721
1722
1723/*
1724 * stop_services is called to stop network services prior to their
1725 * config files being moved/changed.  In case a later recovery is needed
1726 * (an error occurs during config), we detect whether the service is
1727 * running and store that info so that a reset will only start services
1728 * that were stopped here.
1729 *
1730 * In terms of SMF, this translates to disabling the services. So we
1731 * try to disable them if they are in any other state
1732 *
1733 * Stop order :
1734 * sendmail, nscd, autofs, ldap.client, nisd (rpc), inetinit(domainname)
1735 */
1736static int
1737stop_services(int saveState)
1738{
1739	int ret;
1740
1741	if (mode_verbose) {
1742		CLIENT_FPUTS(gettext("Stopping network services\n"), stderr);
1743	}
1744
1745	if (!is_service(SENDMAIL_FMRI, SCF_STATE_STRING_DISABLED)) {
1746		if (mode_verbose)
1747			CLIENT_FPUTS(gettext("Stopping sendmail\n"), stderr);
1748		ret = disable_service(SENDMAIL_FMRI, B_TRUE);
1749		if (ret != CLIENT_SUCCESS) {
1750			/* Not serious, but tell user what to do */
1751			CLIENT_FPRINTF(stderr, gettext("Stopping sendmail "
1752				"failed with (%d). You may need to restart "
1753				"it manually for changes to take effect.\n"),
1754				ret);
1755		} else enableFlag |= SENDMAIL_ON;
1756	} else {
1757		if (mode_verbose)
1758			CLIENT_FPUTS(gettext("sendmail not running\n"), stderr);
1759	}
1760
1761	if (!is_service(NSCD_FMRI, SCF_STATE_STRING_DISABLED)) {
1762		if (mode_verbose)
1763			CLIENT_FPUTS(gettext("Stopping nscd\n"), stderr);
1764		ret = disable_service(NSCD_FMRI, B_TRUE);
1765		if (ret != CLIENT_SUCCESS) {
1766			CLIENT_FPRINTF(stderr, gettext("Stopping nscd "
1767			    "failed with (%d)\n"), ret);
1768			return (CLIENT_ERR_FAIL);
1769		} else enableFlag |= NSCD_ON;
1770	} else {
1771		if (mode_verbose)
1772			CLIENT_FPUTS(gettext("nscd not running\n"), stderr);
1773	}
1774
1775	if (!is_service(AUTOFS_FMRI, SCF_STATE_STRING_DISABLED)) {
1776		if (mode_verbose)
1777			CLIENT_FPUTS(gettext("Stopping autofs\n"), stderr);
1778		ret = disable_service(AUTOFS_FMRI, B_TRUE);
1779		if (ret != CLIENT_SUCCESS) {
1780			/* Not serious, but tell user what to do */
1781			CLIENT_FPRINTF(stderr, gettext("Stopping autofs "
1782				"failed with (%d). You may need to restart "
1783				"it manually for changes to take effect.\n"),
1784				ret);
1785		} else enableFlag |= AUTOFS_ON;
1786	} else {
1787		if (mode_verbose)
1788			CLIENT_FPUTS(gettext("autofs not running\n"), stderr);
1789	}
1790
1791	if (!is_service(LDAP_FMRI, SCF_STATE_STRING_DISABLED)) {
1792		if (saveState)
1793			gStartLdap = START_RESET;
1794		if (mode_verbose)
1795			CLIENT_FPUTS(gettext("Stopping ldap\n"), stderr);
1796		ret = disable_service(LDAP_FMRI, B_TRUE);
1797		if (ret != CLIENT_SUCCESS) {
1798			CLIENT_FPRINTF(stderr, gettext("Stopping ldap "
1799			    "failed with (%d)\n"), ret);
1800			return (CLIENT_ERR_FAIL);
1801		}
1802	} else {
1803		if (mode_verbose)
1804			CLIENT_FPUTS(gettext("ldap not running\n"),
1805								stderr);
1806	}
1807
1808	if (!is_service(NISD_FMRI, SCF_STATE_STRING_DISABLED)) {
1809		if (mode_verbose)
1810			CLIENT_FPUTS(gettext("Stopping nisd\n"), stderr);
1811		ret = disable_service(NISD_FMRI, B_TRUE);
1812		if (ret != CLIENT_SUCCESS) {
1813			CLIENT_FPRINTF(stderr, gettext("Stopping nisd "
1814			    "failed with (%d)\n"), ret);
1815			return (CLIENT_ERR_FAIL);
1816		}
1817	} else {
1818		if (mode_verbose)
1819			CLIENT_FPUTS(gettext("nisd not running\n"),
1820								stderr);
1821	}
1822
1823	if (!is_service(YP_FMRI, SCF_STATE_STRING_DISABLED)) {
1824		if (saveState)
1825			gStartYp = START_RESET;
1826		if (mode_verbose)
1827			CLIENT_FPUTS(gettext("Stopping nis(yp)\n"), stderr);
1828		ret = disable_service(YP_FMRI, B_TRUE);
1829		if (ret != 0) {
1830			CLIENT_FPRINTF(stderr, gettext("Stopping nis(yp) "
1831			    "failed with (%d)\n"), ret);
1832			return (CLIENT_ERR_FAIL);
1833		}
1834	} else {
1835		if (mode_verbose)
1836			CLIENT_FPUTS(gettext("nis(yp) not running\n"),
1837								stderr);
1838	}
1839
1840	return (CLIENT_SUCCESS);
1841}
1842
1843/*
1844 * start_services is called to start up network services after config
1845 * files have all been setup or recovered.  In the case of an error, the
1846 * files will be recovered and start_services will be called with the
1847 * "reset" flag set so that only those services that were earlier stopped
1848 * will be started.  If it is not a reset, then the services associated
1849 * with files "recovered" will attempt to be started.
1850 */
1851static int
1852start_services(int flag)
1853{
1854	int sysret, retcode = CLIENT_SUCCESS, rc = NS_LDAP_SUCCESS;
1855	FILE *domain_fp;
1856	char domainname[BUFSIZ];
1857	char cmd_domain_start[BUFSIZ];
1858	int domainlen;
1859	ns_ldap_self_gssapi_config_t config = NS_LDAP_SELF_GSSAPI_CONFIG_NONE;
1860	ns_ldap_error_t		*errorp = NULL;
1861
1862	if (mode_verbose) {
1863		CLIENT_FPUTS(gettext("Starting network services\n"), stderr);
1864	}
1865
1866	/* Read in current defaultdomain so we can set it */
1867	domain_fp = fopen(DOMAINNAME, "r");
1868	if (domain_fp == NULL) {
1869		CLIENT_FPRINTF(stderr, gettext("Error opening defaultdomain "
1870							"(%d)\n"), errno);
1871		/* if we did an ldap init, we must have domain */
1872		if (flag == START_INIT)
1873			return (CLIENT_ERR_FAIL);
1874	} else {
1875		if (fgets(domainname, BUFSIZ, domain_fp) == NULL) {
1876			CLIENT_FPUTS(gettext("Error reading defaultdomain\n"),
1877				stderr);
1878			return (CLIENT_ERR_FAIL);
1879		}
1880
1881		if (fclose(domain_fp) != 0) {
1882			CLIENT_FPRINTF(stderr,
1883				gettext("Error closing defaultdomain (%d)\n"),
1884				errno);
1885			return (CLIENT_ERR_FAIL);
1886		}
1887		domainlen = strlen(domainname);
1888		/* sanity check to make sure sprintf will fit */
1889		if (domainlen > (BUFSIZE - sizeof (CMD_DOMAIN_START) -
1890						sizeof (TO_DEV_NULL) - 3)) {
1891			CLIENT_FPUTS(gettext("Specified domainname is "
1892						"too large\n"), stderr);
1893			return (CLIENT_ERR_FAIL);
1894		}
1895		if (domainname[domainlen-1] == '\n')
1896			domainname[domainlen-1] = 0;
1897		/* buffer size is checked above */
1898		(void) snprintf(cmd_domain_start, BUFSIZ, "%s %s %s",
1899				CMD_DOMAIN_START, domainname, TO_DEV_NULL);
1900	}
1901
1902	/*
1903	 * We can be starting services after an init in which case
1904	 * we want to start ldap and not start yp or nis+.
1905	 */
1906	if (flag == START_INIT) {
1907		sysret = system(cmd_domain_start);
1908		if (mode_verbose)
1909			CLIENT_FPRINTF(stderr, "start: %s %s... %s\n",
1910					CMD_DOMAIN_START, domainname,
1911					(sysret == 0) ? gettext("success") :
1912							gettext("failed"));
1913		if (sysret != 0) {
1914			CLIENT_FPRINTF(stderr, gettext("\"%s\" returned: %d\n"),
1915					CMD_DOMAIN_START, sysret);
1916
1917			retcode = CLIENT_ERR_FAIL;
1918		}
1919
1920		if ((rc = __ns_ldap_self_gssapi_config(&config)) !=
1921			NS_LDAP_SUCCESS) {
1922			CLIENT_FPRINTF(stderr, gettext("Error (%d) while "
1923					"checking sasl/GSSAPI configuration\n"),
1924					rc);
1925			retcode = CLIENT_ERR_FAIL;
1926		}
1927
1928		if (config != NS_LDAP_SELF_GSSAPI_CONFIG_NONE) {
1929
1930			rc = __ns_ldap_check_dns_preq(
1931					1, mode_verbose, mode_quiet,
1932					NSSWITCH_LDAP, config, &errorp);
1933			if (errorp)
1934				(void) __ns_ldap_freeError(&errorp);
1935
1936			if (rc != NS_LDAP_SUCCESS)
1937				retcode = CLIENT_ERR_FAIL;
1938		}
1939
1940		if (rc == NS_LDAP_SUCCESS &&
1941			start_service(LDAP_FMRI, B_TRUE) != CLIENT_SUCCESS)
1942			retcode = CLIENT_ERR_FAIL;
1943
1944		if (config != NS_LDAP_SELF_GSSAPI_CONFIG_NONE &&
1945			rc == NS_LDAP_SUCCESS && retcode == CLIENT_SUCCESS) {
1946			rc = __ns_ldap_check_gssapi_preq(
1947					1, mode_verbose, mode_quiet, config,
1948					&errorp);
1949			if (errorp)
1950				(void) __ns_ldap_freeError(&errorp);
1951
1952			if (rc != NS_LDAP_SUCCESS)
1953				retcode = CLIENT_ERR_FAIL;
1954
1955		}
1956		/* No YP or NIS+ after init */
1957	/*
1958	 * Or we can be starting services after an uninit or error
1959	 * recovery.  We want to start whatever services were running
1960	 * before.  In the case of error recovery, it is the services
1961	 * that were running before we stopped them (flags set in
1962	 * stop_services).  If it is an uninit then we determine
1963	 * which services to start based on the files we recovered
1964	 * (flags set in recover).
1965	 */
1966	} else {
1967		/* uninit and recover should set flags of what to start */
1968		if (domain_fp) {
1969			sysret = system(cmd_domain_start);
1970			if (mode_verbose)
1971				CLIENT_FPRINTF(stderr, "start: %s %s... %s\n",
1972					CMD_DOMAIN_START, domainname,
1973					(sysret == 0) ? gettext("success") :
1974							gettext("failed"));
1975			if (sysret != 0) {
1976				CLIENT_FPRINTF(stderr, gettext("\"%s\" "
1977						"returned: %d\n"),
1978						CMD_DOMAIN_START, sysret);
1979
1980				retcode = CLIENT_ERR_FAIL;
1981			}
1982		}
1983
1984		if (gStartLdap == flag) {
1985			if (!(is_service(LDAP_FMRI, SCF_STATE_STRING_ONLINE)))
1986				if (start_service(LDAP_FMRI, B_TRUE)
1987							!= CLIENT_SUCCESS)
1988					retcode = CLIENT_ERR_FAIL;
1989		}
1990
1991		if (gStartYp == flag) {
1992			if (!(is_service(YP_FMRI, SCF_STATE_STRING_ONLINE)))
1993				(void) start_service(YP_FMRI, B_TRUE);
1994		}
1995
1996		if (gStartNisd == flag) {
1997			if (!(is_service(NISD_FMRI, SCF_STATE_STRING_ONLINE)))
1998				(void) start_service(NISD_FMRI, B_TRUE);
1999		}
2000
2001	}
2002	if ((enableFlag & AUTOFS_ON) &&
2003	    !(is_service(AUTOFS_FMRI, SCF_STATE_STRING_ONLINE)))
2004		(void) start_service(AUTOFS_FMRI, B_TRUE);
2005
2006	if ((enableFlag & NSCD_ON) &&
2007	    !(is_service(NSCD_FMRI, SCF_STATE_STRING_ONLINE)))
2008		(void) start_service(NSCD_FMRI, B_TRUE);
2009
2010#if 0
2011	if (flag == START_INIT && config != NS_LDAP_SELF_GSSAPI_CONFIG_NONE &&
2012	    retcode == CLIENT_SUCCESS &&
2013	    !(is_service(NSCD_FMRI, SCF_STATE_STRING_ONLINE))) {
2014		CLIENT_FPRINTF(stderr, "start: %s\n",
2015				gettext("self/sasl/GSSAPI is configured"
2016					" but nscd is not online"));
2017		retcode = CLIENT_ERR_FAIL;
2018	}
2019#endif
2020
2021	if ((enableFlag & SENDMAIL_ON) &&
2022	    !(is_service(SENDMAIL_FMRI, SCF_STATE_STRING_ONLINE)))
2023		(void) start_service(SENDMAIL_FMRI, B_TRUE);
2024
2025	/*
2026	 * Restart name-service milestone so that any consumer
2027	 * which depends on it will be restarted.
2028	 */
2029	(void) restart_service(NS_MILESTONE_FMRI, B_TRUE);
2030	return (retcode);
2031}
2032
2033/*
2034 * credCheck is called to check if credentials are required for this
2035 * configuration.  Currently, this means that if any credentialLevel is
2036 * proxy and any authenticationMethod is something other than none, then
2037 * credential info is required (proxyDN and proxyPassword).
2038 */
2039static int
2040credCheck(clientopts_t *arglist)
2041{
2042	int counter;
2043	int **credLevel;
2044	ns_auth_t **authMethod;
2045	char **proxyDN, **proxyPassword;
2046	ns_ldap_error_t *errorp;
2047	int credProxy, authNotNone;
2048	int retcode;
2049
2050/* If credentialLevel is proxy, make sure we have proxyDN and proxyPassword */
2051	retcode = __ns_ldap_getParam(NS_LDAP_CREDENTIAL_LEVEL_P,
2052			(void ***)&credLevel, &errorp);
2053	if (retcode != 0) {
2054		CLIENT_FPRINTF(stderr,
2055			gettext("Error %d while trying to retrieve "
2056				"credLevel\n"),
2057			retcode);
2058		return (CLIENT_ERR_FAIL);
2059	}
2060	retcode = __ns_ldap_getParam(NS_LDAP_AUTH_P,
2061			(void ***)&authMethod, &errorp);
2062	if (retcode != 0) {
2063		CLIENT_FPRINTF(stderr,
2064			gettext("Error %d while trying to retrieve "
2065				"authMethod\n"), retcode);
2066		return (CLIENT_ERR_FAIL);
2067	}
2068	retcode = __ns_ldap_getParam(NS_LDAP_BINDDN_P,
2069			(void ***)&proxyDN, &errorp);
2070	if (retcode != 0) {
2071		CLIENT_FPRINTF(stderr,
2072			gettext("Error %d while trying to retrieve proxyDN\n"),
2073			retcode);
2074		return (CLIENT_ERR_FAIL);
2075	}
2076	retcode = __ns_ldap_getParam(NS_LDAP_BINDPASSWD_P,
2077			(void ***)&proxyPassword, &errorp);
2078	if (retcode != 0) {
2079		CLIENT_FPRINTF(stderr,
2080			gettext("Error %d while trying to retrieve "
2081				"proxyPassword\n"), retcode);
2082		return (CLIENT_ERR_FAIL);
2083	}
2084
2085	if (mode_verbose) {
2086		CLIENT_FPRINTF(stderr,
2087			gettext("Proxy DN: %s\n"),
2088			(proxyDN && proxyDN[0]) ? proxyDN[0] : "NULL");
2089		CLIENT_FPRINTF(stderr,
2090			gettext("Proxy password: %s\n"),
2091			(proxyPassword && proxyPassword[0]) ?
2092				proxyPassword[0] : "NULL");
2093	}
2094
2095	credProxy = 0;	/* flag to indicate if we have a credLevel of proxy */
2096	for (counter = 0; credLevel && credLevel[counter] != NULL; counter++) {
2097		if (mode_verbose)
2098			CLIENT_FPRINTF(stderr,
2099				gettext("Credential level: %d\n"),
2100				*credLevel[counter]);
2101		if (*credLevel[counter] == NS_LDAP_CRED_PROXY) {
2102			credProxy = 1;
2103			break;
2104		}
2105	}
2106
2107	authNotNone = 0;	/* flag for authMethod other than none */
2108	for (counter = 0;
2109		authMethod && authMethod[counter] != NULL;
2110		counter++) {
2111
2112		if (mode_verbose)
2113			CLIENT_FPRINTF(stderr,
2114				gettext("Authentication method: %d\n"),
2115				authMethod[counter]->type);
2116		if (authMethod[counter]->type != NS_LDAP_AUTH_NONE &&
2117		    !(authMethod[counter]->type == NS_LDAP_AUTH_TLS &&
2118		    authMethod[counter]->tlstype == NS_LDAP_TLS_NONE)) {
2119			authNotNone = 1;
2120			break;
2121		}
2122	}
2123
2124	/* First, if we don't need proxyDN/Password then just return ok */
2125	if (!(credProxy && authNotNone)) {
2126		if (mode_verbose)
2127			CLIENT_FPUTS(
2128				gettext("No proxyDN/proxyPassword required\n"),
2129				stderr);
2130		return (CLIENT_SUCCESS);
2131	}
2132
2133	/* Now let's check if we have the cred stuff we need */
2134	if (!proxyDN || !proxyDN[0]) {
2135		CLIENT_FPUTS(
2136			gettext("credentialLevel is proxy and no proxyDN "
2137				"specified\n"),
2138			stderr);
2139		return (CLIENT_ERR_CREDENTIAL);
2140	}
2141
2142	/* If we need proxyPassword (prompt) */
2143	if (!proxyPassword || !proxyPassword[0]) {
2144		CLIENT_FPUTS(
2145			gettext("credentialLevel requires proxyPassword\n"),
2146			stderr);
2147		arglist->proxyPassword = getpassphrase("Proxy Bind Password:");
2148		if (arglist->proxyPassword == NULL) {
2149			CLIENT_FPUTS(gettext("Get password failed\n"), stderr);
2150			return (CLIENT_ERR_CREDENTIAL);
2151		}
2152		LDAP_SET_PARAM(arglist->proxyPassword, NS_LDAP_BINDPASSWD_P);
2153		if (retcode != 0) {
2154			CLIENT_FPUTS(
2155				gettext("setParam proxyPassword failed.\n"),
2156				stderr);
2157			return (CLIENT_ERR_CREDENTIAL);
2158		}
2159	}
2160
2161	return (CLIENT_SUCCESS);
2162}
2163
2164/*
2165 * try to restore the previous name space on this machine
2166 */
2167static int
2168recover(int saveState)
2169{
2170	struct stat buf;
2171	int stat_ret, retcode, fd;
2172	int domain = 0, domainlen;
2173	char yp_dir[BUFSIZE], yp_dir_back[BUFSIZE];
2174	char name[BUFSIZ];
2175	char *ldap_conf_file, *ldap_cred_file;
2176	char ldap_file_back[BUFSIZE], ldap_cred_back[BUFSIZE];
2177
2178	/* If running as Sysid Install become a no-op */
2179	if (sysid_install == B_TRUE)
2180		return (CLIENT_SUCCESS);
2181
2182	stat_ret = stat(LDAP_RESTORE_DIR, &buf);
2183	if (stat_ret != 0) {
2184		CLIENT_FPUTS(
2185			gettext("Cannot recover.  No backup files "
2186				"found.\n"),
2187			stderr);
2188		CLIENT_FPUTS(
2189			gettext("\t Either this machine was not initialized\n"),
2190			stderr);
2191		CLIENT_FPUTS(
2192			gettext("\t by ldapclient or the backup files "
2193				"have been\n"),
2194			stderr);
2195		CLIENT_FPUTS(
2196			gettext("\t removed manually or with an \"uninit\"\n"),
2197			stderr);
2198		return (CLIENT_ERR_RESTORE);	/* invalid backup */
2199	}
2200
2201	/*
2202	 * Get domainname.  Allow no domainname for the case where "files"
2203	 * config was backed up.
2204	 */
2205	stat_ret = stat(DOMAINNAME_BACK, &buf);
2206	if (mode_verbose)
2207		CLIENT_FPRINTF(stderr,
2208			gettext("recover: stat(%s)=%d\n"),
2209			DOMAINNAME_BACK, stat_ret);
2210	if (stat_ret == 0) {
2211		if (mode_verbose)
2212			CLIENT_FPRINTF(stderr,
2213				gettext("recover: open(%s)\n"),
2214					DOMAINNAME_BACK);
2215		fd = open(DOMAINNAME_BACK, O_RDONLY);
2216		if (mode_verbose)
2217			CLIENT_FPRINTF(stderr,
2218				gettext("recover: read(%s)\n"),
2219					DOMAINNAME_BACK);
2220		domainlen = read(fd, &(name[0]), BUFSIZ-1);
2221		(void) close(fd);
2222		if (domainlen < 0) {
2223			CLIENT_FPUTS(
2224				gettext("Cannot recover.  Cannot determine "
2225					"previous domain name.\n"),
2226				stderr);
2227			return (CLIENT_ERR_RESTORE);	/* invalid backup */
2228		} else 	{
2229			char *ptr;
2230
2231			ptr = strchr(&(name[0]), '\n');
2232			if (ptr != NULL)
2233				*ptr = '\0';
2234			else
2235				name[domainlen] = '\0';
2236
2237			if (mode_verbose)
2238				CLIENT_FPRINTF(stderr,
2239					gettext("recover: old domainname "
2240						"\"%s\"\n"), name);
2241
2242			if (strlen(name) == 0)
2243				domain = 0;
2244			else
2245				domain = 1;	/* flag that we have domain */
2246
2247		}
2248	}
2249
2250
2251	/*
2252	 * we can recover at this point
2253	 * remove LDAP config files before restore
2254	 */
2255	(void) unlink(NSCONFIGFILE);
2256	(void) unlink(NSCREDFILE);
2257
2258	ldap_conf_file = strrchr(NSCONFIGFILE, '/') + 1;
2259	ldap_cred_file = strrchr(NSCREDFILE, '/') + 1;
2260
2261	(void) strlcpy(ldap_file_back, LDAP_RESTORE_DIR "/", BUFSIZE);
2262	(void) strlcat(ldap_file_back, ldap_conf_file, BUFSIZE);
2263
2264	stat_ret = stat(ldap_file_back, &buf);
2265	if (mode_verbose)
2266		CLIENT_FPRINTF(stderr,
2267			gettext("recover: stat(%s)=%d\n"),
2268			ldap_file_back, stat_ret);
2269	if (stat_ret == 0) {
2270		if (saveState)
2271			gStartLdap = START_UNINIT;
2272		retcode = file_move(ldap_file_back, NSCONFIGFILE);
2273		if (mode_verbose)
2274			CLIENT_FPRINTF(stderr,
2275				gettext("recover: file_move(%s, %s)=%d\n"),
2276				ldap_file_back, NSCONFIGFILE, retcode);
2277		if (retcode != 0)
2278			CLIENT_FPRINTF(stderr,
2279				gettext("recover: file_move(%s, %s) failed\n"),
2280				ldap_file_back, NSCONFIGFILE);
2281	}
2282
2283	(void) strlcpy(ldap_cred_back, LDAP_RESTORE_DIR "/", BUFSIZE);
2284	(void) strlcat(ldap_cred_back, ldap_cred_file, BUFSIZE);
2285
2286	stat_ret = stat(ldap_cred_back, &buf);
2287	if (mode_verbose)
2288		CLIENT_FPRINTF(stderr,
2289			gettext("recover: stat(%s)=%d\n"),
2290			ldap_cred_back, stat_ret);
2291	if (stat_ret == 0) {
2292		retcode = file_move(ldap_cred_back, NSCREDFILE);
2293		if (mode_verbose)
2294			CLIENT_FPRINTF(stderr,
2295				gettext("recover: file_move(%s, %s)=%d\n"),
2296				ldap_cred_back, NSCREDFILE, retcode);
2297		if (retcode != 0)
2298			CLIENT_FPRINTF(stderr,
2299				gettext("recover: file_move(%s, %s) failed\n"),
2300				ldap_cred_back, NSCREDFILE);
2301	}
2302
2303	/* Check for recovery of NIS+ */
2304	stat_ret = stat(NIS_COLDSTART_BACK, &buf);
2305	if (mode_verbose)
2306		CLIENT_FPRINTF(stderr,
2307			gettext("recover: stat(%s)=%d\n"),
2308			NIS_COLDSTART_BACK, stat_ret);
2309	if (stat_ret == 0) {
2310		if (saveState) {
2311			gStartNisd = START_UNINIT;
2312		}
2313		if (mode_verbose)
2314			CLIENT_FPRINTF(stderr,
2315				gettext("recover: file_move(%s, %s)\n"),
2316				NIS_COLDSTART_BACK, NIS_COLDSTART);
2317		retcode = file_move(NIS_COLDSTART_BACK, NIS_COLDSTART);
2318		if (retcode != 0)
2319			CLIENT_FPRINTF(stderr,
2320				gettext("recover: file_move(%s, %s) failed!\n"),
2321				NIS_COLDSTART_BACK, NIS_COLDSTART);
2322	}
2323
2324	/* Check for recovery of NIS(YP) if we have a domainname */
2325	if (domain) {
2326		/* "name" would have to be huge for this, but just in case */
2327		if (strlen(name) >= (BUFSIZE - strlen(LDAP_RESTORE_DIR)))
2328			return (CLIENT_ERR_FAIL);
2329		if (strlen(name) >= (BUFSIZE - strlen(YP_BIND_DIR)))
2330			return (CLIENT_ERR_FAIL);
2331
2332		(void) strlcpy(yp_dir_back, LDAP_RESTORE_DIR "/", BUFSIZE);
2333		(void) strlcat(yp_dir_back, name, BUFSIZE);
2334		stat_ret = stat(yp_dir_back, &buf);
2335		if (mode_verbose)
2336			CLIENT_FPRINTF(stderr,
2337				gettext("recover: stat(%s)=%d\n"),
2338				yp_dir_back, stat_ret);
2339		if (stat_ret == 0) {
2340			(void) strlcpy(yp_dir, YP_BIND_DIR "/", BUFSIZE);
2341			(void) strlcat(yp_dir, name, BUFSIZE);
2342			retcode = file_move(yp_dir_back, yp_dir);
2343			if (mode_verbose)
2344				CLIENT_FPRINTF(stderr,
2345					gettext("recover: file_move(%s, "
2346						"%s)=%d\n"),
2347					yp_dir_back, yp_dir, retcode);
2348			if (retcode != 0) {
2349				CLIENT_FPRINTF(stderr,
2350					gettext("recover: file_move(%s, "
2351						"%s) failed!\n"),
2352					yp_dir_back, yp_dir);
2353			} else {
2354				if (saveState)
2355					gStartYp = START_UNINIT;
2356			}
2357		}
2358	}
2359
2360	/* restore machine configuration */
2361	stat_ret = stat(NSSWITCH_BACK, &buf);
2362	if (mode_verbose)
2363		CLIENT_FPRINTF(stderr,
2364			gettext("recover: stat(%s)=%d\n"),
2365			NSSWITCH_BACK, stat_ret);
2366	if (stat_ret == 0) {
2367		retcode = file_move(NSSWITCH_BACK, NSSWITCH_CONF);
2368		if (mode_verbose)
2369			CLIENT_FPRINTF(stderr,
2370				gettext("recover: file_move(%s, %s)=%d\n"),
2371				NSSWITCH_BACK, NSSWITCH_CONF, retcode);
2372		if (retcode != 0)
2373			CLIENT_FPRINTF(stderr,
2374				gettext("recover: file_move(%s, %s) failed\n"),
2375				NSSWITCH_BACK, NSSWITCH_CONF);
2376	}
2377
2378	stat_ret = stat(DOMAINNAME_BACK, &buf);
2379	if (mode_verbose)
2380		CLIENT_FPRINTF(stderr,
2381			gettext("recover: stat(%s)=%d\n"),
2382			DOMAINNAME_BACK, stat_ret);
2383	if (stat_ret == 0) {
2384		retcode = file_move(DOMAINNAME_BACK, DOMAINNAME);
2385		if (mode_verbose)
2386			CLIENT_FPRINTF(stderr,
2387				gettext("recover: file_move(%s, %s)=%d\n"),
2388				DOMAINNAME_BACK, DOMAINNAME, retcode);
2389		if (retcode != 0)
2390			CLIENT_FPRINTF(stderr,
2391				gettext("recover: file_move(%s, %s) failed\n"),
2392				DOMAINNAME_BACK, DOMAINNAME);
2393	}
2394
2395	retcode = rmdir(LDAP_RESTORE_DIR);
2396	if (retcode != 0) {
2397		CLIENT_FPRINTF(stderr,
2398			gettext("Error removing \"%s\" directory.\n"),
2399			LDAP_RESTORE_DIR);
2400	}
2401
2402	return (CLIENT_SUCCESS);
2403}
2404
2405/*
2406 * try to save the current state of this machine.
2407 * this just overwrites any old saved configration files.
2408 *
2409 * This function should only be called after network services have been stopped.
2410 *
2411 * Returns 0 on successful save
2412 * Otherwise returns -1
2413 */
2414static int
2415file_backup(void)
2416{
2417	struct stat buf;
2418	int domain_stat, conf_stat, ldap_stat;
2419	int nis_stat, yp_stat, restore_stat;
2420	int retcode, namelen, ret;
2421	char yp_dir[BUFSIZ], yp_dir_back[BUFSIZ];
2422	char name[BUFSIZ];
2423	char *ldap_conf_file, *ldap_cred_file;
2424	char ldap_file_back[BUFSIZE], ldap_cred_back[BUFSIZE];
2425
2426	ret = CLIENT_SUCCESS;
2427	/* If running as Sysid Install become a no-op */
2428	if (sysid_install == B_TRUE)
2429		return (CLIENT_SUCCESS);
2430
2431	/* If existing backup files, clear for this run */
2432	restore_stat = stat(LDAP_RESTORE_DIR, &buf);
2433	if (restore_stat == 0) {
2434		if (mode_verbose) {
2435			CLIENT_FPUTS(
2436				gettext("Removing existing restore "
2437					"directory\n"),
2438				stderr);
2439		}
2440		(void) system("/bin/rm -fr " LDAP_RESTORE_DIR);
2441		restore_stat = stat(LDAP_RESTORE_DIR, &buf);
2442		if (restore_stat == 0) {
2443			CLIENT_FPRINTF(stderr,
2444				gettext("Unable to remove backup "
2445					"directory (%s)\n"),
2446				LDAP_RESTORE_DIR);
2447			return (CLIENT_ERR_RESTORE);
2448		}
2449	}
2450
2451	retcode = mkdir(LDAP_RESTORE_DIR, 0755);
2452	if (retcode != 0) {
2453		CLIENT_FPRINTF(stderr,
2454			gettext("file_backup: Failed to make %s backup "
2455				"directory. mkdir=%d\n"),
2456			LDAP_RESTORE_DIR, retcode);
2457		return (CLIENT_ERR_FAIL);
2458	}
2459
2460	conf_stat = stat(NSSWITCH_CONF, &buf);
2461	if (mode_verbose)
2462		CLIENT_FPRINTF(stderr,
2463			gettext("file_backup: stat(%s)=%d\n"),
2464			NSSWITCH_CONF, conf_stat);
2465	if (conf_stat == 0) {
2466		if (mode_verbose)
2467			CLIENT_FPRINTF(stderr,
2468				gettext("file_backup: (%s -> %s)\n"),
2469				NSSWITCH_CONF, NSSWITCH_BACK);
2470		retcode = file_move(NSSWITCH_CONF, NSSWITCH_BACK);
2471		if (retcode != 0) {
2472			CLIENT_FPRINTF(stderr,
2473				gettext("file_backup: file_move(%s, %s) failed "
2474					"with %d\n"),
2475				NSSWITCH_CONF, NSSWITCH_BACK, retcode);
2476			ret = CLIENT_ERR_RENAME;
2477		}
2478	} else {
2479		if (mode_verbose)
2480			CLIENT_FPRINTF(stderr,
2481				gettext("file_backup: No %s file.\n"),
2482				NSSWITCH_CONF);
2483	}
2484
2485	domain_stat = stat(DOMAINNAME, &buf);
2486	if (mode_verbose)
2487		CLIENT_FPRINTF(stderr,
2488			gettext("file_backup: stat(%s)=%d\n"),
2489			DOMAINNAME, domain_stat);
2490	if ((domain_stat == 0) && (buf.st_size > 0)) {
2491		if (mode_verbose)
2492			CLIENT_FPRINTF(stderr,
2493				gettext("file_backup: (%s -> %s)\n"),
2494				DOMAINNAME, DOMAINNAME_BACK);
2495		retcode = file_move(DOMAINNAME, DOMAINNAME_BACK);
2496		if (retcode != 0) {
2497			CLIENT_FPRINTF(stderr,
2498				gettext("file_backup: file_move(%s, %s) failed "
2499					"with %d\n"),
2500				DOMAINNAME, DOMAINNAME_BACK, retcode);
2501			ret = CLIENT_ERR_RENAME;
2502		}
2503	} else {
2504		if (mode_verbose)
2505			if (domain_stat != 0) {
2506				CLIENT_FPRINTF(stderr,
2507					gettext("file_backup: No %s file.\n"),
2508					DOMAINNAME);
2509			} else {
2510				CLIENT_FPRINTF(stderr,
2511					gettext("file_backup: Empty %s "
2512								"file.\n"),
2513					DOMAINNAME);
2514			}
2515	}
2516
2517	nis_stat = stat(NIS_COLDSTART, &buf);
2518	if (mode_verbose)
2519		CLIENT_FPRINTF(stderr,
2520			gettext("file_backup: stat(%s)=%d\n"),
2521			NIS_COLDSTART, nis_stat);
2522	if (nis_stat == 0) {
2523		if (mode_verbose)
2524			CLIENT_FPRINTF(stderr,
2525				gettext("file_backup: (%s -> %s)\n"),
2526				NIS_COLDSTART, NIS_COLDSTART_BACK);
2527		retcode = file_move(NIS_COLDSTART, NIS_COLDSTART_BACK);
2528		if (retcode != 0) {
2529			CLIENT_FPRINTF(stderr,
2530				gettext("file_backup: file_move(%s, %s) failed "
2531					"with %d\n"),
2532				NIS_COLDSTART, NIS_COLDSTART_BACK, retcode);
2533			ret = CLIENT_ERR_RENAME;
2534		}
2535	} else {
2536		if (mode_verbose)
2537			CLIENT_FPRINTF(stderr,
2538				gettext("file_backup: No %s file.\n"),
2539				NIS_COLDSTART);
2540	}
2541
2542	namelen = BUFSIZ;
2543	(void) sysinfo(SI_SRPC_DOMAIN, &(name[0]), namelen);
2544	namelen = strlen(name);
2545
2546	if (mode_verbose)
2547		CLIENT_FPRINTF(stderr,
2548			gettext("file_backup: nis domain is \"%s\"\n"),
2549			(namelen > 0) ? name : "EMPTY");
2550	/* check for domain name if not set cannot save NIS(YP) state */
2551	if (namelen > 0) {
2552		/* moving /var/yp/binding will cause ypbind to core dump */
2553		(void) strlcpy(yp_dir, YP_BIND_DIR "/", BUFSIZE);
2554		(void) strlcat(yp_dir, name, BUFSIZE);
2555		yp_stat = stat(yp_dir, &buf);
2556		if (mode_verbose)
2557			CLIENT_FPRINTF(stderr,
2558				gettext("file_backup: stat(%s)=%d\n"),
2559				yp_dir, yp_stat);
2560		if (yp_stat == 0) {
2561			(void) strlcpy(yp_dir_back, LDAP_RESTORE_DIR "/",
2562				BUFSIZE);
2563			(void) strlcat(yp_dir_back, name, BUFSIZE);
2564			if (mode_verbose)
2565				CLIENT_FPRINTF(stderr,
2566					gettext("file_backup: (%s -> %s)\n"),
2567					yp_dir, yp_dir_back);
2568			retcode = file_move(yp_dir, yp_dir_back);
2569			if (retcode != 0) {
2570				CLIENT_FPRINTF(stderr,
2571					gettext("file_backup: file_move(%s, %s)"
2572						" failed with %d\n"),
2573					yp_dir, yp_dir_back, retcode);
2574				ret = CLIENT_ERR_RENAME;
2575			}
2576		} else {
2577			if (mode_verbose)
2578				CLIENT_FPRINTF(stderr,
2579					gettext("file_backup: No %s "
2580						"directory.\n"), yp_dir);
2581		}
2582	}
2583
2584
2585	/* point to file name, not path delim (/) */
2586	ldap_conf_file = strrchr(NSCONFIGFILE, '/') + 1;
2587	ldap_cred_file = strrchr(NSCREDFILE, '/') + 1;
2588
2589	ldap_stat = stat(NSCONFIGFILE, &buf);
2590	if (mode_verbose)
2591		CLIENT_FPRINTF(stderr,
2592			gettext("file_backup: stat(%s)=%d\n"),
2593			NSCONFIGFILE, ldap_stat);
2594	if (ldap_stat == 0) {
2595		(void) strlcpy(ldap_file_back, LDAP_RESTORE_DIR "/", BUFSIZE);
2596		(void) strlcat(ldap_file_back, ldap_conf_file, BUFSIZE);
2597		if (mode_verbose)
2598			CLIENT_FPRINTF(stderr,
2599				gettext("file_backup: (%s -> %s)\n"),
2600				NSCONFIGFILE, ldap_file_back);
2601		retcode = file_move(NSCONFIGFILE, ldap_file_back);
2602		if (retcode != 0) {
2603			CLIENT_FPRINTF(stderr,
2604				gettext("file_backup: file_move(%s, %s) failed "
2605					"with %d\n"),
2606				NSCONFIGFILE, ldap_file_back, retcode);
2607			ret = CLIENT_ERR_RENAME;
2608		}
2609
2610		(void) strlcpy(ldap_cred_back, LDAP_RESTORE_DIR "/", BUFSIZE);
2611		(void) strlcat(ldap_cred_back, ldap_cred_file, BUFSIZE);
2612		if (mode_verbose)
2613			CLIENT_FPRINTF(stderr,
2614				gettext("file_backup: (%s -> %s)\n"),
2615				NSCREDFILE, ldap_cred_back);
2616		retcode = file_move(NSCREDFILE, ldap_cred_back);
2617		if (retcode != 0) {
2618			CLIENT_FPRINTF(stderr,
2619				gettext("file_backup: file_move(%s, %s) failed "
2620					"with %d\n"),
2621				NSCREDFILE, ldap_cred_back, retcode);
2622			ret = CLIENT_ERR_RENAME;
2623		}
2624	} else {
2625		if (mode_verbose)
2626			CLIENT_FPRINTF(stderr,
2627				gettext("file_backup: No %s file.\n"),
2628				NSCONFIGFILE);
2629	}
2630
2631	return (ret);
2632}
2633
2634/*
2635 * mod_backup()
2636 *
2637 * This function is used to temporily backup the LDAP client files in /var/ldap
2638 * that the "mod" operation needs to update.  If an error occurs then the
2639 * function mod_recover() can be invoke to recover the unmodified files.
2640 */
2641static int
2642mod_backup(void)
2643{
2644	int rc;
2645	int retcode = CLIENT_SUCCESS;
2646
2647	rc = system(CMD_CP " " NSCONFIGFILE " " NSCONFIGFILE ".mod");
2648	retcode += rc;
2649	if (mode_verbose)
2650		CLIENT_FPRINTF(stderr,
2651		    gettext("mod_backup: backup %s for %s\n"),
2652		    rc ? "failed" : "successful", NSCONFIGFILE);
2653
2654	rc = system(CMD_CP " " NSCREDFILE " " NSCREDFILE ".mod");
2655	retcode += rc;
2656	if (mode_verbose)
2657		CLIENT_FPRINTF(stderr,
2658		    gettext("mod_backup: backup %s for %s\n"),
2659		    rc ? "failed" : "successful", NSCREDFILE);
2660
2661	rc = system(CMD_CP " " DOMAINNAME " " DOMAINNAME ".mod");
2662	retcode += rc;
2663	if (mode_verbose)
2664		CLIENT_FPRINTF(stderr,
2665		    gettext("mod_backup: backup %s for %s\n"),
2666		    rc ? "failed" : "successful", DOMAINNAME);
2667
2668	if (retcode != CLIENT_SUCCESS)
2669		retcode = CLIENT_ERR_RENAME;
2670	return (retcode);
2671}
2672
2673/*
2674 * mod_recover()
2675 *
2676 * This function is used to recover the temporily backed up files by
2677 * the mod_backup() function if an error occurs during the "mod"
2678 * operation.
2679 */
2680static int
2681mod_recover(void)
2682{
2683	int rc;
2684	int retcode = CLIENT_SUCCESS;
2685
2686	rc = system(CMD_MV " " NSCONFIGFILE ".mod " NSCONFIGFILE);
2687	retcode += rc;
2688	if (mode_verbose)
2689		CLIENT_FPRINTF(stderr,
2690		    gettext("mod_recover: recovery %s for %s\n"),
2691		    rc ? "failed" : "successful", NSCONFIGFILE);
2692
2693	rc = system(CMD_MV " " NSCREDFILE ".mod " NSCREDFILE);
2694	retcode += rc;
2695	if (mode_verbose)
2696		CLIENT_FPRINTF(stderr,
2697		    gettext("mod_recover: recovery %s for %s\n"),
2698		    rc ? "failed" : "successful", NSCREDFILE);
2699
2700	rc = system(CMD_MV " " DOMAINNAME ".mod " DOMAINNAME);
2701	retcode += rc;
2702	if (mode_verbose)
2703		CLIENT_FPRINTF(stderr,
2704		    gettext("mod_recover: recovery %s for %s\n"),
2705		    rc ? "failed" : "successful", DOMAINNAME);
2706
2707	if (retcode != CLIENT_SUCCESS)
2708		retcode = CLIENT_ERR_RENAME;
2709	return (retcode);
2710}
2711
2712/*
2713 * mod_cleanup()
2714 *
2715 * This function removes the .mod files in /var/ldap.
2716 */
2717static void
2718mod_cleanup(void)
2719{
2720	(void) system(CMD_RM " " NSCONFIGFILE ".mod " TO_DEV_NULL);
2721	(void) system(CMD_RM " " NSCREDFILE ".mod " TO_DEV_NULL);
2722	(void) system(CMD_RM " " DOMAINNAME ".mod " TO_DEV_NULL);
2723}
2724
2725#define	MAX_DN_ARRAY 100
2726#define	LDAP_NAMINGCONTEXTS	"namingcontexts"
2727
2728static char *
2729findBaseDN(char *server)
2730{
2731	int ret;
2732	ns_ldap_entry_t *entry;
2733	ns_ldap_result_t *resultp;
2734	ns_ldap_error_t *errorp = NULL;
2735	char filter[BUFSIZ], *rootDN[MAX_DN_ARRAY], *nisBaseDN;
2736	char *attribute[] = { LDAP_NAMINGCONTEXTS, NULL };
2737	int root_cnt, found_cxt;
2738	int i, j, k, retcode;
2739
2740	if (mode_verbose)
2741		CLIENT_FPUTS(gettext("findBaseDN: begins\n"), stderr);
2742
2743	if (dname == NULL)
2744		return (NULL);
2745
2746	if (is_service(LDAP_FMRI, SCF_STATE_STRING_ONLINE)) {
2747		gStartLdap = START_RESET; /* reset flag for err cases */
2748		if (mode_verbose)
2749			CLIENT_FPUTS(gettext("findBaseDN: Stopping ldap\n"),
2750								stderr);
2751		ret = disable_service(LDAP_FMRI, B_TRUE);
2752		if (ret != 0) {
2753			CLIENT_FPRINTF(stderr, gettext("findBaseDN: Stopping "
2754					"ldap failed with (%d)\n"), ret);
2755			return (NULL);
2756		}
2757		(void) unlink(LDAP_CACHE_LOG);
2758	} else {
2759		if (mode_verbose)
2760			CLIENT_FPUTS(gettext("findBaseDN: ldap not running\n"),
2761			    stderr);
2762	}
2763
2764	if (mode_verbose)
2765		CLIENT_FPUTS(
2766			gettext("findBaseDN: calling "
2767				"__ns_ldap_default_config()\n"),
2768			stderr);
2769	__ns_ldap_default_config();
2770
2771	retcode = __ns_ldap_setParam(NS_LDAP_SERVERS_P,
2772				(void *)server, &errorp);
2773	if (retcode != NS_LDAP_SUCCESS) {
2774		goto findDN_err_exit;
2775	}
2776
2777	retcode = __ns_ldap_setParam(NS_LDAP_AUTH_P,
2778			(void *)"NS_LDAP_AUTH_NONE", &errorp);
2779	if (retcode != NS_LDAP_SUCCESS) {
2780		goto findDN_err_exit;
2781	}
2782
2783	retcode = __ns_ldap_setParam(NS_LDAP_TRANSPORT_SEC_P,
2784			(void *)"NS_LDAP_SEC_NONE", &errorp);
2785	if (retcode != NS_LDAP_SUCCESS) {
2786		goto findDN_err_exit;
2787	}
2788
2789	retcode = __ns_ldap_setParam(NS_LDAP_SEARCH_BASEDN_P,
2790			(void *)"", &errorp);
2791	if (retcode != NS_LDAP_SUCCESS) {
2792		goto findDN_err_exit;
2793	}
2794
2795	retcode = __ns_ldap_setParam(NS_LDAP_SEARCH_SCOPE_P,
2796			(void *)"NS_LDAP_SCOPE_BASE", &errorp);
2797	if (retcode != NS_LDAP_SUCCESS) {
2798		goto findDN_err_exit;
2799	}
2800
2801	(void) strcpy(&filter[0], "(objectclass=*)");
2802
2803	ret = __ns_ldap_list(NULL, filter, NULL, (const char **)attribute,
2804				NULL, 0, &resultp, &errorp, NULL, NULL);
2805	if (NULL == resultp) {
2806		if (mode_verbose)
2807			CLIENT_FPUTS(
2808				gettext("__ns_ldap_list return NULL resultp\n"),
2809				stderr);
2810
2811		goto findDN_err_exit;
2812	}
2813
2814	for (i = 0; i < MAX_DN_ARRAY; i++)
2815		rootDN[i] = NULL;
2816	root_cnt = 0;
2817	entry = resultp->entry;
2818	for (i = 0; i < resultp->entries_count; i++) {
2819	    for (j = 0; j < entry->attr_count; j++) {
2820		char *cp;
2821
2822		cp = entry->attr_pair[j]->attrname;
2823		if (0 != j) {
2824		    for (k = 0; entry->attr_pair[j]->attrvalue[k]; k++)
2825			if (0 == strcasecmp(cp, LDAP_NAMINGCONTEXTS)) {
2826			    if (NULL == rootDN[root_cnt])
2827				rootDN[root_cnt++] = strdup(entry->attr_pair[j]
2828							->attrvalue[k]);
2829				if (rootDN[root_cnt-1] == NULL) {
2830					root_cnt--;
2831					CLIENT_FPUTS(gettext("Memory "
2832						"allocation error.\n"), stderr);
2833			/*
2834			 * fall through and let processing happen on the
2835			 * rootDNs found to this point.  Most likely
2836			 * things will fall apart if we are out of memory!
2837			 */
2838					break;
2839				}
2840			}
2841		}
2842	    }
2843	    entry = entry->next;
2844	}
2845	(void) __ns_ldap_freeResult(&resultp);
2846	if (mode_verbose)
2847		CLIENT_FPRINTF(stderr,
2848			gettext("found %d namingcontexts\n"), root_cnt);
2849	if (root_cnt == 0) {
2850		CLIENT_FPUTS(gettext("Cannot find the rootDN\n"), stderr);
2851		goto findDN_err_exit;
2852	}
2853	found_cxt = -1;
2854	for (i = 0; i < root_cnt; i++) {
2855		retcode = __ns_ldap_setParam(NS_LDAP_SEARCH_BASEDN_P,
2856						(void *)rootDN[i], &errorp);
2857		if (NS_LDAP_SUCCESS != retcode) {
2858			CLIENT_FPUTS(
2859				gettext("Error setting param "
2860					"NS_LDAP_SEARCH_BASEDN_P\n"), stderr);
2861			goto findDN_err_exit;
2862		}
2863		retcode = __ns_ldap_setParam(NS_LDAP_SEARCH_SCOPE_P,
2864				(void *)"NS_LDAP_SCOPE_SUBTREE", &errorp);
2865		if (NS_LDAP_SUCCESS != retcode) {
2866			CLIENT_FPUTS(
2867				gettext("Error setting param "
2868					"NS_LDAP_SEARCH_SCOPE_P\n"),
2869				stderr);
2870			goto findDN_err_exit;
2871		}
2872		(void) snprintf(&filter[0], BUFSIZ,
2873			"(&(objectclass=nisDomainObject)(nisdomain=%s))",
2874			dname);
2875		if (mode_verbose) {
2876		    CLIENT_FPRINTF(stderr,
2877			gettext("findBaseDN: __ns_ldap_list(NULL, \"%s\"\n"),
2878			filter);
2879		    CLIENT_FPRINTF(stderr,
2880			gettext("rootDN[%d] %s\n"), i, rootDN[i]);
2881		}
2882		ret = __ns_ldap_list(NULL, filter, NULL, (const char **)NULL,
2883					NULL, 0, &resultp, &errorp, NULL, NULL);
2884		if (ret == NS_LDAP_SUCCESS) {
2885			found_cxt = i;
2886			break;
2887		} else {
2888		    if (mode_verbose)
2889			CLIENT_FPRINTF(stderr,
2890				gettext("NOTFOUND:Could not find the "
2891					"nisDomainObject for DN %s\n"),
2892				rootDN[i]);
2893		}
2894	}
2895	if (-1 == found_cxt) {
2896		if (mode_verbose)
2897			CLIENT_FPUTS(gettext("found_cxt = -1\n"), stderr);
2898		goto findDN_err_exit;
2899	}
2900	if (resultp == NULL) {
2901		CLIENT_FPUTS(gettext("resultp is NULL\n"), stderr);
2902		goto findDN_err_exit;
2903	}
2904	entry = resultp->entry;
2905	if (entry == NULL) {
2906		CLIENT_FPUTS(gettext("entry is NULL\n"), stderr);
2907		goto findDN_err_exit;
2908	}
2909
2910	nisBaseDN = strdup(entry->attr_pair[0]->attrvalue[0]);
2911
2912	(void) __ns_ldap_freeResult(&resultp);
2913
2914	if (mode_verbose)
2915		CLIENT_FPRINTF(stderr,
2916			gettext("found baseDN %s for domain %s\n"),
2917			nisBaseDN ? nisBaseDN : "NULL", dname);
2918
2919	return (nisBaseDN);
2920
2921findDN_err_exit:
2922	if (mode_verbose) {
2923		CLIENT_FPUTS(gettext("findBaseDN: Err exit\n"), stderr);
2924	}
2925	if (NULL != errorp) {
2926		CLIENT_FPRINTF(stderr, gettext("\t%s\n"), errorp->message);
2927		(void) __ns_ldap_freeError(&errorp);
2928	}
2929	return (NULL);
2930}
2931
2932static multival_t *
2933multival_new()
2934{
2935	multival_t *hold;
2936
2937	hold = calloc(1, sizeof (multival_t));
2938	if (hold == NULL) {
2939		CLIENT_FPUTS(
2940			gettext("multival_new: Memory allocation error\n"),
2941			stderr);
2942	}
2943	return (hold);	/* NULL -> error */
2944}
2945
2946static int
2947multival_add(multival_t *list, char *opt)
2948{
2949	if (opt == NULL) {
2950		CLIENT_FPUTS(
2951			gettext("Empty value passed to multival_add\n"),
2952			stderr);
2953		return (CLIENT_ERR_FAIL);
2954	}
2955
2956	if (list->count == 0) {
2957		list->optlist = (char **)malloc(sizeof (char **));
2958	} else {
2959		list->optlist = (char **)realloc(list->optlist,
2960			(list->count + 1) * sizeof (char **));
2961	}
2962
2963	if (list->optlist == NULL) {
2964		CLIENT_FPUTS(gettext("Error allocating memory\n"), stderr);
2965		return (CLIENT_ERR_MEMORY);	/* 0 is success */
2966	}
2967
2968	list->optlist[list->count] = opt;
2969	list->count++;
2970
2971	return (CLIENT_SUCCESS);
2972}
2973
2974static void
2975multival_free(multival_t *list)
2976{
2977	if (list == NULL)
2978		return;
2979
2980	if (list->optlist != NULL)
2981		free(list->optlist);
2982	free(list);
2983}
2984
2985static clientopts_t *
2986clientopts_new()
2987{
2988	clientopts_t *hold;
2989
2990	hold = calloc(1, sizeof (clientopts_t));
2991	if (NULL == hold) {
2992		CLIENT_FPUTS(gettext("Error allocating memory for "
2993				"clientopts structure\n"), stderr);
2994		return (hold);	/* NULL -> error */
2995	}
2996
2997	hold->serviceAuthenticationMethod = multival_new();
2998	if (NULL == hold->serviceAuthenticationMethod) {
2999		CLIENT_FPUTS(gettext("Error allocating memory for "
3000				"serviceAuthenticationMethod\n"), stderr);
3001		free(hold);
3002		return (NULL);	/* NULL -> error */
3003	}
3004
3005	hold->serviceCredentialLevel = multival_new();
3006	if (NULL == hold->serviceCredentialLevel) {
3007		CLIENT_FPUTS(gettext("Error allocating memory for "
3008				"serviceCredentialLevel\n"), stderr);
3009		multival_free(hold->serviceAuthenticationMethod);
3010		free(hold);
3011		return (NULL);	/* NULL -> error */
3012	}
3013
3014	hold->objectclassMap = multival_new();
3015	if (NULL == hold->objectclassMap) {
3016		CLIENT_FPUTS(gettext("Error allocating memory for "
3017				"objectclassMap\n"), stderr);
3018		multival_free(hold->serviceAuthenticationMethod);
3019		multival_free(hold->serviceCredentialLevel);
3020		free(hold);
3021		return (NULL);	/* NULL -> error */
3022	}
3023
3024	hold->attributeMap = multival_new();
3025	if (NULL == hold->attributeMap) {
3026		CLIENT_FPUTS(gettext("Error allocating memory for "
3027				"attributeMap\n"), stderr);
3028		multival_free(hold->serviceAuthenticationMethod);
3029		multival_free(hold->serviceCredentialLevel);
3030		multival_free(hold->objectclassMap);
3031		free(hold);
3032		return (NULL);	/* NULL -> error */
3033	}
3034
3035	hold->serviceSearchDescriptor = multival_new();
3036	if (NULL == hold->serviceSearchDescriptor) {
3037		CLIENT_FPUTS(gettext("Error allocating memory for "
3038				"serviceSearchDescriptor\n"), stderr);
3039		multival_free(hold->serviceAuthenticationMethod);
3040		multival_free(hold->serviceCredentialLevel);
3041		multival_free(hold->objectclassMap);
3042		multival_free(hold->attributeMap);
3043		free(hold);
3044		return (NULL);	/* NULL -> error */
3045	}
3046
3047	return (hold);
3048}
3049
3050static void
3051clientopts_free(clientopts_t *list)
3052{
3053	if (NULL == list)
3054		return;
3055
3056	multival_free(list->serviceAuthenticationMethod);
3057	multival_free(list->serviceCredentialLevel);
3058	multival_free(list->objectclassMap);
3059	multival_free(list->attributeMap);
3060	multival_free(list->serviceSearchDescriptor);
3061
3062	free(list);
3063
3064}
3065
3066static void
3067multival_list(char *opt, multival_t *list)
3068{
3069	int i;
3070
3071	if (list->count == 0)
3072		return;
3073
3074	(void) puts(opt);
3075	for (i = 0; i < list->count; i++) {
3076		(void) printf("\t\targ[%d]: %s\n", i, list->optlist[i]);
3077	}
3078}
3079
3080/* return the number of arguments specified in the command line */
3081static int
3082num_args(clientopts_t *list)
3083{
3084	int arg_count = 0;
3085
3086	arg_count += list->authenticationMethod ? 1 : 0;
3087	arg_count += list->serviceAuthenticationMethod->count;
3088	arg_count += list->defaultSearchBase ? 1 : 0;
3089	arg_count += list->credentialLevel ? 1 : 0;
3090	arg_count += list->serviceCredentialLevel->count;
3091	arg_count += list->domainName ? 1 : 0;
3092	arg_count += list->proxyDN ? 1 : 0;
3093	arg_count += list->profileTTL ? 1 : 0;
3094	arg_count += list->objectclassMap->count;
3095	arg_count += list->searchTimeLimit ? 1 : 0;
3096	arg_count += list->preferredServerList ? 1 : 0;
3097	arg_count += list->profileName ? 1 : 0;
3098	arg_count += list->followReferrals ? 1 : 0;
3099	arg_count += list->attributeMap->count;
3100	arg_count += list->defaultSearchScope ? 1 : 0;
3101	arg_count += list->serviceSearchDescriptor->count;
3102	arg_count += list->bindTimeLimit ? 1 : 0;
3103	arg_count += list->proxyPassword ? 1 : 0;
3104	arg_count += list->defaultServerList ? 1 : 0;
3105	arg_count += list->certificatePath ? 1 : 0;
3106
3107	return (arg_count);
3108}
3109
3110#define	CLIENT_PRINT(opt, str) if (str) \
3111		(void) printf("%s%s\n", (opt), (str))
3112
3113static void
3114dumpargs(clientopts_t *list)
3115{
3116	CLIENT_PRINT("\tauthenticationMethod: ", list->authenticationMethod);
3117	multival_list("\tserviceAuthenticationMethod: ",
3118		list->serviceAuthenticationMethod);
3119	CLIENT_PRINT("\tdefaultSearchBase: ", list->defaultSearchBase);
3120	CLIENT_PRINT("\tcredentialLevel: ", list->credentialLevel);
3121	multival_list("\tserviceCredentialLevel: ",
3122		list->serviceCredentialLevel);
3123	CLIENT_PRINT("\tdomainName: ", list->domainName);
3124	CLIENT_PRINT("\tproxyDN: ", list->proxyDN);
3125	CLIENT_PRINT("\tprofileTTL: ", list->profileTTL);
3126	multival_list("\tobjectclassMap: ", list->objectclassMap);
3127	CLIENT_PRINT("\tsearchTimeLimit: ", list->searchTimeLimit);
3128	CLIENT_PRINT("\tpreferredServerList: ", list->preferredServerList);
3129	CLIENT_PRINT("\tprofileName: ", list->profileName);
3130	CLIENT_PRINT("\tfollowReferrals: ", list->followReferrals);
3131	multival_list("\tattributeMap: ", list->attributeMap);
3132	CLIENT_PRINT("\tdefaultSearchScope: ", list->defaultSearchScope);
3133	multival_list("\tserviceSearchDescriptor: ",
3134		list->serviceSearchDescriptor);
3135	CLIENT_PRINT("\tbindTimeLimit: ", list->bindTimeLimit);
3136	CLIENT_PRINT("\tproxyPassword: ", list->proxyPassword);
3137	CLIENT_PRINT("\tdefaultServerList: ", list->defaultServerList);
3138	CLIENT_PRINT("\tcertificatePath: ", list->certificatePath);
3139}
3140
3141
3142/* These definitions are only used in parseParam() below. */
3143struct param {
3144	char	*name;
3145	int	index;
3146};
3147
3148static struct param paramArray[] = {
3149	{"proxyDN", NS_LDAP_BINDDN_P},
3150	{"proxyPassword", NS_LDAP_BINDPASSWD_P},
3151	{"defaultServerList", NS_LDAP_SERVERS_P},
3152	{"defaultSearchBase", NS_LDAP_SEARCH_BASEDN_P},
3153	{"authenticationMethod", NS_LDAP_AUTH_P},
3154	{"followReferrals", NS_LDAP_SEARCH_REF_P},
3155	{"profileTTL", NS_LDAP_CACHETTL_P},
3156	{"certificatePath", NS_LDAP_HOST_CERTPATH_P},
3157	{"defaultSearchScope", NS_LDAP_SEARCH_SCOPE_P},
3158	{"bindTimeLimit", NS_LDAP_BIND_TIME_P},
3159	{"searchTimeLimit", NS_LDAP_SEARCH_TIME_P},
3160	{"preferredServerList", NS_LDAP_SERVER_PREF_P},
3161	{"profileName", NS_LDAP_PROFILE_P},
3162	{"credentialLevel", NS_LDAP_CREDENTIAL_LEVEL_P},
3163	{"serviceSearchDescriptor", NS_LDAP_SERVICE_SEARCH_DESC_P},
3164	{"attributeMap", NS_LDAP_ATTRIBUTEMAP_P},
3165	{"objectclassMap", NS_LDAP_OBJECTCLASSMAP_P},
3166	{"serviceAuthenticationMethod", NS_LDAP_SERVICE_AUTH_METHOD_P},
3167	{"serviceCredentialLevel", NS_LDAP_SERVICE_CRED_LEVEL_P},
3168	{"domainName", LOCAL_DOMAIN_P},
3169	{NULL, 0}
3170};
3171
3172static int
3173parseParam(char *param, char **paramVal)
3174{
3175	char *val = NULL;
3176	int counter;
3177
3178	if (mode_verbose) {
3179		CLIENT_FPRINTF(stderr, gettext("Parsing %s\n"), param);
3180	}
3181
3182	val = strchr(param, '=');
3183	if (val == NULL) {
3184		CLIENT_FPUTS(
3185			gettext("Didn\'t find \'=\' character in string\n"),
3186			stderr);
3187		paramVal = NULL;
3188		return (CLIENT_ERR_PARSE);
3189	}
3190
3191	*val = '\0';
3192
3193	for (counter = 0; paramArray[counter].name != NULL; counter++) {
3194		if (strcasecmp(paramArray[counter].name, param) == 0) {
3195			*paramVal = val+1;
3196			*val = '=';	/* restore original param */
3197			return (paramArray[counter].index);
3198		}
3199	}
3200
3201	/* Not found */
3202	*val = '=';	/* restore original param */
3203	*paramVal = NULL;
3204	return (CLIENT_ERR_PARSE);
3205}
3206
3207/*
3208 * The following macro checks if an option has already been specified
3209 * and errs out with usage if so
3210 */
3211#define	CLIENT_OPT_CHECK(opt, optarg)	\
3212if (optarg) {			\
3213	CLIENT_FPUTS(gettext("Invalid use of option\n"), stderr);	\
3214	usage();		\
3215	clientopts_free(optlist); \
3216	return (CLIENT_ERR_FAIL);		\
3217}
3218
3219static int
3220clientSetParam(clientopts_t *optlist, int paramFlag, char *attrVal)
3221{
3222	int retcode = 0;
3223	int counter;
3224
3225
3226	switch (paramFlag) {
3227	case NS_LDAP_AUTH_P:
3228		CLIENT_OPT_CHECK(paramFlag, optlist->authenticationMethod);
3229		optlist->authenticationMethod = attrVal;
3230		break;
3231
3232	case NS_LDAP_SERVICE_AUTH_METHOD_P:	/* multiple allowed */
3233		retcode = multival_add(optlist->serviceAuthenticationMethod,
3234				attrVal);
3235		if (retcode != CLIENT_SUCCESS) {
3236			CLIENT_FPRINTF(stderr,
3237				gettext("Error processing attrVal %s\n"),
3238				attrVal?attrVal:"NULL");
3239			usage();
3240			clientopts_free(optlist);
3241			return (CLIENT_ERR_FAIL);
3242		}
3243		break;
3244
3245	case NS_LDAP_SEARCH_BASEDN_P:
3246		CLIENT_OPT_CHECK(paramFlag, optlist->defaultSearchBase);
3247		optlist->defaultSearchBase = attrVal;
3248		break;
3249
3250	case NS_LDAP_CREDENTIAL_LEVEL_P:
3251		CLIENT_OPT_CHECK(paramFlag, optlist->credentialLevel);
3252		optlist->credentialLevel = attrVal;
3253		break;
3254
3255	case NS_LDAP_SERVICE_CRED_LEVEL_P:	/* multiple allowed */
3256		retcode = multival_add(optlist->serviceCredentialLevel,
3257				attrVal);
3258		if (retcode != CLIENT_SUCCESS) {
3259			CLIENT_FPRINTF(stderr,
3260				gettext("Error processing attrVal %s\n"),
3261				attrVal?attrVal:"NULL");
3262			usage();
3263			clientopts_free(optlist);
3264			return (CLIENT_ERR_FAIL);
3265		}
3266		break;
3267
3268	case LOCAL_DOMAIN_P:
3269		CLIENT_OPT_CHECK(paramFlag, optlist->domainName);
3270		optlist->domainName = attrVal;
3271		dname = optlist->domainName;
3272		break;
3273
3274	case NS_LDAP_BINDDN_P:
3275		CLIENT_OPT_CHECK(paramFlag, optlist->proxyDN);
3276		optlist->proxyDN = attrVal;
3277		break;
3278
3279	case NS_LDAP_CACHETTL_P:
3280		CLIENT_OPT_CHECK(paramFlag, optlist->profileTTL);
3281		optlist->profileTTL = attrVal;
3282		break;
3283
3284	case NS_LDAP_OBJECTCLASSMAP_P:	/* multiple allowed */
3285		retcode = multival_add(optlist->objectclassMap, attrVal);
3286		if (retcode != CLIENT_SUCCESS) {
3287			CLIENT_FPRINTF(stderr,
3288				gettext("Error processing attrVal %s\n"),
3289				attrVal?attrVal:"NULL");
3290			usage();
3291			clientopts_free(optlist);
3292			return (CLIENT_ERR_FAIL);
3293		}
3294		break;
3295
3296	case NS_LDAP_SEARCH_TIME_P:
3297		CLIENT_OPT_CHECK(paramFlag, optlist->searchTimeLimit);
3298		optlist->searchTimeLimit = attrVal;
3299		break;
3300
3301	case NS_LDAP_SERVER_PREF_P:
3302		CLIENT_OPT_CHECK(paramFlag, optlist->preferredServerList);
3303		optlist->preferredServerList = attrVal;
3304		/* replace ',' chars with ' ' for proper syntax */
3305		for (counter = 0;
3306			counter < strlen(optlist->preferredServerList);
3307			counter++) {
3308
3309			if (optlist->preferredServerList[counter] == ',')
3310				optlist->preferredServerList[counter] = ' ';
3311		}
3312		break;
3313
3314	case NS_LDAP_PROFILE_P:
3315		CLIENT_OPT_CHECK(paramFlag, optlist->profileName);
3316		optlist->profileName = attrVal;
3317		break;
3318
3319	case NS_LDAP_SEARCH_REF_P:
3320		CLIENT_OPT_CHECK(paramFlag, optlist->followReferrals);
3321		if (0 == strcasecmp(attrVal, "followref"))
3322			optlist->followReferrals = "TRUE";
3323		else if (0 == strcasecmp(attrVal, "noref"))
3324			optlist->followReferrals = "FALSE";
3325		else
3326			optlist->followReferrals = attrVal;
3327		break;
3328
3329	case NS_LDAP_ATTRIBUTEMAP_P:	/* multiple allowed */
3330		retcode = multival_add(optlist->attributeMap, attrVal);
3331		if (retcode != CLIENT_SUCCESS) {
3332			CLIENT_FPRINTF(stderr,
3333				gettext("Error processing attrVal %s\n"),
3334				attrVal?attrVal:"NULL");
3335			usage();
3336			clientopts_free(optlist);
3337			return (CLIENT_ERR_FAIL);
3338		}
3339		break;
3340
3341	case NS_LDAP_SEARCH_SCOPE_P:
3342		CLIENT_OPT_CHECK(paramFlag, optlist->defaultSearchScope);
3343		optlist->defaultSearchScope = attrVal;
3344		break;
3345
3346	case NS_LDAP_SERVICE_SEARCH_DESC_P:	/* multiple allowed */
3347		retcode = multival_add(optlist->serviceSearchDescriptor,
3348				attrVal);
3349		if (retcode != CLIENT_SUCCESS) {
3350			CLIENT_FPRINTF(stderr,
3351				gettext("Error processing attrVal %s\n"),
3352				attrVal?attrVal:"NULL");
3353			usage();
3354			clientopts_free(optlist);
3355			return (CLIENT_ERR_FAIL);
3356		}
3357		break;
3358
3359	case NS_LDAP_BIND_TIME_P:
3360		CLIENT_OPT_CHECK(paramFlag, optlist->bindTimeLimit);
3361		optlist->bindTimeLimit = attrVal;
3362		break;
3363
3364	case NS_LDAP_BINDPASSWD_P:
3365		CLIENT_OPT_CHECK(paramFlag, optlist->proxyPassword);
3366		optlist->proxyPassword = attrVal;
3367		break;
3368
3369	case NS_LDAP_HOST_CERTPATH_P:
3370		CLIENT_OPT_CHECK(paramFlag, optlist->certificatePath);
3371		optlist->certificatePath = attrVal;
3372		break;
3373
3374	case NS_LDAP_SERVERS_P:
3375		CLIENT_OPT_CHECK(paramFlag, optlist->defaultServerList);
3376		optlist->defaultServerList = attrVal;
3377		break;
3378
3379	default:
3380		usage();
3381		return (CLIENT_ERR_FAIL);
3382		/* break;  lint doesn't like break before end of switch */
3383	}
3384
3385	return (retcode);
3386}
3387
3388/*
3389 * file_move() - Used to move a config file (backup/restore).
3390 *
3391 * This function uses a system() call with /bin/mv to handle the
3392 * case where the backup directory (/var) is on a different file
3393 * system than the config file (typically /etc).
3394 */
3395static int
3396file_move(const char *from, const char *to)
3397{
3398	int retcode;
3399	char mvCommand[] = CMD_MV;
3400	char cmd_buffer[(2 * MAXPATHLEN) + sizeof (mvCommand) + 3];
3401
3402	(void) snprintf(cmd_buffer, sizeof (cmd_buffer), "%s %s %s",
3403					mvCommand, from, to);
3404
3405	/*
3406	 * This function should only be used internally to move
3407	 * system files to/from the backup directory.  For security
3408	 * reasons (this is run as root), don't use this function
3409	 * with arguments passed into the program.
3410	 */
3411	retcode = system(cmd_buffer);
3412
3413	return (retcode);
3414}
3415
3416
3417static boolean_t
3418has_port(const char *server)
3419{
3420	const char	*s;
3421	const char	*end;
3422
3423	/*
3424	 * Don't check that address is legal - only determine
3425	 * if there is a port specified - works for both ipv4 and ipv6
3426	 */
3427
3428	while (server != NULL) {
3429		end = strchr(server, ',');
3430		if (end == NULL)
3431			s = server + strlen(server);
3432		else {
3433			s = end;
3434			end = end + 1;
3435		}
3436
3437		while (s >= server) {
3438			if (*s == ']')
3439				break;
3440			else if (*s == ':')
3441				return (B_TRUE);
3442			s--;
3443		}
3444		server = end;
3445	}
3446	return (B_FALSE);
3447}
3448
3449
3450/*
3451 * Check to see if configured to use tls and some server has a port number
3452 * configured. The goal is to help prevent users from configuring impossible
3453 * profiles
3454 */
3455
3456static boolean_t
3457is_config_ok(const clientopts_t *list, boolean_t get_config)
3458{
3459	boolean_t	has_tls = B_FALSE;
3460	boolean_t	is_ok = B_TRUE;
3461	multival_t	*m_val;
3462	int		i, j, len;
3463	const char	*begin;
3464	const char	*end;
3465	ns_auth_t	**authMethod;
3466	char		**servers;
3467	char		**sam;
3468	ns_ldap_error_t	*errorp = NULL;
3469	int		rc;
3470
3471	if (list->authenticationMethod != NULL) {
3472		begin = list->authenticationMethod;
3473		len = strlen(begin) - 3;
3474		for (i = 0; i < len; i++)
3475			if (strncasecmp(begin + i, "tls:", 4) == 0)
3476				break;
3477		has_tls = i < len;
3478	} else if (get_config) {
3479		rc = __ns_ldap_getParam(NS_LDAP_AUTH_P,
3480			(void ***)&authMethod, &errorp);
3481		if (rc == NS_LDAP_SUCCESS && authMethod != NULL) {
3482			for (i = 0; authMethod[i] != NULL && !has_tls; i++)
3483			    has_tls = authMethod[i]->type == NS_LDAP_AUTH_TLS;
3484			(void) __ns_ldap_freeParam((void ***) &authMethod);
3485		}
3486		if (errorp != NULL)
3487			(void) __ns_ldap_freeError(&errorp);
3488		errorp = NULL;
3489	}
3490
3491	m_val = list->serviceAuthenticationMethod;
3492	if (!has_tls && m_val != NULL) {
3493		for (j = 0; j < m_val->count && !has_tls; j++) {
3494			begin = m_val->optlist[j];
3495			/* skip over service tag */
3496			if (begin != NULL)
3497				begin = strchr(begin, ':');
3498			if (begin == NULL)
3499				continue;
3500			len = strlen(begin) - 3;
3501			for (i = 0; i < len; i++)
3502				if (strncasecmp(begin + i, "tls:", 4) == 0)
3503					break;
3504			has_tls = i < len;
3505		}
3506	}
3507	if (!has_tls && get_config) {
3508		rc = __ns_ldap_getParam(NS_LDAP_SERVICE_AUTH_METHOD_P,
3509			(void ***)&sam, &errorp);
3510		if (rc == NS_LDAP_SUCCESS && sam != NULL) {
3511		    for (i = 0; sam[i] != NULL && !has_tls; i++) {
3512			if (m_val != NULL) {
3513			    /* check to see if a new service is replacing */
3514			    for (j = 0; j < m_val->count; j++) {
3515				begin = m_val->optlist[j];
3516				if (begin == NULL)
3517					continue;
3518				end = strchr(begin, ':');
3519				if (end == NULL)
3520					continue;
3521				len = end - begin + 1;
3522				if (strncasecmp(sam[i], begin, len) == 0)
3523					break;
3524			    }
3525			    if (j != m_val->count)
3526				continue;
3527			}
3528			begin = sam[i];
3529			/* skip over service tag */
3530			if (begin != NULL)
3531				begin = strchr(begin, ':');
3532			if (begin != NULL) {
3533			    len = strlen(begin) - 3;
3534			    for (i = 0; i < len; i++)
3535				if (strncasecmp(begin + i, "tls:", 4) == 0)
3536					break;
3537			    has_tls = i < len;
3538			}
3539		    }
3540		    (void) __ns_ldap_freeParam((void ***) &sam);
3541		}
3542		if (errorp != NULL)
3543			(void) __ns_ldap_freeError(&errorp);
3544		errorp = NULL;
3545	}
3546
3547	if (has_tls) {
3548		/*
3549		 * Don't check that address is legal - only determine
3550		 * if there is a port specified
3551		 */
3552		if (list->defaultServerList != NULL)
3553			is_ok = !has_port(list->defaultServerList);
3554		else if (get_config && is_ok) {
3555			rc = __ns_ldap_getParam(NS_LDAP_SERVERS_P,
3556				(void ***) &servers, &errorp);
3557			if (rc == NS_LDAP_SUCCESS && servers != NULL) {
3558				for (i = 0; servers[i] != NULL && is_ok; i++)
3559					is_ok = !has_port(servers[i]);
3560				(void) __ns_ldap_freeParam((void ***) &servers);
3561			}
3562		}
3563		if (errorp != NULL)
3564			(void) __ns_ldap_freeError(&errorp);
3565		errorp = NULL;
3566
3567		if (is_ok)
3568			is_ok = !has_port(list->preferredServerList);
3569		else if (get_config && is_ok) {
3570			rc = __ns_ldap_getParam(NS_LDAP_SERVER_PREF_P,
3571				(void ***) &servers, &errorp);
3572			if (rc == NS_LDAP_SUCCESS && servers != NULL) {
3573				for (i = 0; servers[i] != NULL && is_ok; i++)
3574					is_ok = !has_port(servers[i]);
3575				(void) __ns_ldap_freeParam((void ***) &servers);
3576			}
3577			if (errorp != NULL)
3578				(void) __ns_ldap_freeError(&errorp);
3579		}
3580	}
3581
3582	return (is_ok);
3583}
3584
3585
3586/*
3587 * Manipulate the service as instructed by "dowhat"
3588 */
3589static int
3590do_service(const char *fmri, boolean_t waitflag, int dowhat,
3591		const char *state) {
3592
3593	int		status;
3594	boolean_t	is_maint;
3595	const char	*what = gettext("not set");
3596	useconds_t	max;
3597
3598	/* Check if we are in maintenance */
3599	is_maint = is_service(fmri, SCF_STATE_STRING_MAINT);
3600
3601	switch (dowhat) {
3602	case START_SERVICE:
3603		what = gettext("start");
3604		status = smf_enable_instance(fmri,
3605			(sysid_install == B_TRUE)?SMF_TEMPORARY:0);
3606		break;
3607	case STOP_SERVICE:
3608		what = gettext("stop");
3609		status = smf_disable_instance(fmri,
3610			(sysid_install == B_TRUE)?SMF_TEMPORARY:0);
3611		break;
3612	case RESTART_SERVICE:
3613		what = gettext("restart");
3614		status = smf_restart_instance(fmri);
3615		break;
3616	default:
3617		/* coding error; will not happen */
3618		assert(0);
3619	}
3620
3621	/*
3622	 * If the service was previously in maintenance then we need to
3623	 * clear it immediately.  The "dowhat" action will set the
3624	 * enabled property of the service as intended by the caller while
3625	 * clear will actually cause it to be enabled/disabled.
3626	 * We assume that the caller has called us after taking some
3627	 * recovery action. Even if it's not the case, we don't lose
3628	 * anything.
3629	 */
3630	if (status == 0 && is_maint == B_TRUE) {
3631		if (mode_verbose)
3632			CLIENT_FPRINTF(stderr,
3633				"%s: %s... %s\n",
3634				what,
3635				fmri,
3636				gettext("restoring from maintenance state"));
3637		status = smf_restore_instance(fmri);
3638	}
3639
3640	if (status == 0) {
3641		/* Check if we need to wait ? */
3642		if (waitflag == B_FALSE) {
3643			if (mode_verbose)
3644				CLIENT_FPRINTF(stderr,
3645					"%s: %s... %s\n",
3646					what,
3647					fmri,
3648					gettext("success"));
3649			return (CLIENT_SUCCESS);
3650		}
3651
3652		/* Otherwise wait for max seconds (from the manifest) */
3653		max = get_timeout_value(dowhat, fmri, DEFAULT_TIMEOUT);
3654		status = wait_till(fmri, state, max, what, !is_maint);
3655		if (status == CLIENT_SUCCESS)
3656			return (CLIENT_SUCCESS);
3657		/* For error fall through for corrective action */
3658	} else {
3659		/* Well, service failed ... */
3660		if (mode_verbose)
3661			CLIENT_FPRINTF(stderr, "%s: %s... %s: %s\n",
3662				what,
3663				fmri,
3664				gettext("failed"),
3665				scf_strerror(scf_error()));
3666		status = CLIENT_ERR_FAIL;
3667		/* For error fall through for corrective action */
3668	}
3669
3670	/*
3671	 * If service is still offline after start/restart, then transitioning
3672	 * failed and guess is restarter failed to apply the timeout as well.
3673	 * So instead of leaving it offline, let's just disable it until we have
3674	 * some other mechanism available from smf to handle such situation.
3675	 */
3676	if (dowhat != STOP_SERVICE)
3677		if (is_service(fmri, SCF_STATE_STRING_OFFLINE)) {
3678			if (mode_verbose)
3679				CLIENT_FPRINTF(stderr,
3680					"%s: %s... %s\n",
3681					what,
3682					fmri,
3683					gettext("offline to disable"));
3684			(void) disable_service(fmri, waitflag);
3685		}
3686
3687	return (status);
3688}
3689
3690
3691/*
3692 * Wait for "max" usecs for the service described by "fmri" to change
3693 * to "state". If check_maint is true then return immediately if
3694 * service goes into maintenance
3695 */
3696static int
3697wait_till(const char *fmri, const char *state, useconds_t max,
3698		const char *what, boolean_t check_maint) {
3699	char *st;
3700	useconds_t usecs = INIT_WAIT_USECS;
3701
3702	for (; max > 0; max -= usecs) {
3703		/* incremental wait */
3704		usecs *= 2;
3705		usecs = (usecs > max)?max:usecs;
3706		if (mode_verbose)
3707			CLIENT_FPRINTF(stderr,
3708				"%s: %s %u %s\n",
3709				what, gettext("sleep"), usecs,
3710				gettext("microseconds"));
3711		(void) usleep(usecs);
3712
3713		/* Check state after the wait */
3714		if ((st = smf_get_state(fmri)) != NULL) {
3715			if (strcmp(st, state) == 0) {
3716				if (mode_verbose)
3717					CLIENT_FPRINTF(stderr,
3718						"%s: %s... %s\n",
3719						what,
3720						fmri,
3721						gettext("success"));
3722				free(st);
3723				return (CLIENT_SUCCESS);
3724			}
3725
3726			/*
3727			 * If service has gone into maintenance then
3728			 * we will time out anyway, so we are better
3729			 * off returning now
3730			 */
3731			if (check_maint &&
3732				strcmp(st, SCF_STATE_STRING_MAINT) == 0) {
3733				if (mode_verbose)
3734					CLIENT_FPRINTF(stderr,
3735						"%s: %s... %s\n",
3736						what,
3737						fmri,
3738						gettext("maintenance"));
3739				free(st);
3740				return (CLIENT_ERR_MAINTENANCE);
3741			}
3742			free(st);
3743		} else {
3744			if (mode_verbose)
3745				CLIENT_FPRINTF(stderr,
3746						"%s: %s... %s: %s\n",
3747						what,
3748						fmri,
3749						gettext("failed"),
3750						scf_strerror(scf_error()));
3751			return (CLIENT_ERR_FAIL);
3752		}
3753	}
3754
3755	/* Timed out waiting */
3756	if (mode_verbose)
3757		CLIENT_FPRINTF(stderr,
3758			"%s: %s... %s\n",
3759			what,
3760			fmri,
3761			gettext("timed out"));
3762	return (CLIENT_ERR_TIMEDOUT);
3763}
3764
3765
3766static boolean_t
3767is_service(const char *fmri, const char *state) {
3768	char		*st;
3769	boolean_t	result = B_FALSE;
3770
3771	if ((st = smf_get_state(fmri)) != NULL) {
3772		if (strcmp(st, state) == 0)
3773			result = B_TRUE;
3774		free(st);
3775	}
3776	return (result);
3777}
3778
3779
3780/*
3781 *
3782 * get_timeout_val : returns the timeout value set in fmri manifest
3783 * 	inputs	: action(start/stop)
3784 *	fmri(defined fmri string)
3785 *	Returns default if error, the timeout val otherwise
3786 *
3787 */
3788
3789static useconds_t
3790get_timeout_value(int dowhat, const char *fmri, useconds_t default_val)
3791{
3792	scf_simple_prop_t	*sp = NULL;
3793	uint64_t		*cp = NULL;
3794	int			timeout = default_val/1000000;
3795	char			*action = NULL;
3796	const char		*actionstr = NULL;
3797
3798	switch (dowhat)  {
3799		case START_SERVICE:
3800		case RESTART_SERVICE:
3801				action = "start";
3802				actionstr = gettext("start");
3803				break;
3804		case STOP_SERVICE:
3805				action = "stop";
3806				actionstr = gettext("stop");
3807				break;
3808		default:
3809			assert(0);
3810	}
3811
3812
3813	sp = scf_simple_prop_get(NULL, fmri, action, SCF_PROPERTY_TIMEOUT);
3814	if (sp == NULL) {
3815		if (mode_verbose)
3816			CLIENT_FPRINTF(stderr, "%s: %s... %s: %s\n",
3817				actionstr,
3818				fmri,
3819				gettext("failed to retrieve timeout property"),
3820				scf_strerror(scf_error()));
3821		return (default_val);
3822	}
3823
3824	cp = scf_simple_prop_next_count(sp);
3825	if (cp == NULL) {
3826		if (mode_verbose)
3827			CLIENT_FPRINTF(stderr, "%s: %s... %s: %s\n",
3828				actionstr,
3829				fmri,
3830				gettext("failed to retrieve timeout value"),
3831				scf_strerror(scf_error()));
3832		scf_simple_prop_free(sp);
3833		return (default_val);
3834	}
3835
3836	if (*cp != 0)
3837		timeout = *cp;
3838	scf_simple_prop_free(sp);
3839	return (timeout * 1000000);
3840}
3841