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