xref: /illumos-gate/usr/src/cmd/modload/update_drv.c (revision 7c478bd9)
1*7c478bd9Sstevel@tonic-gate /*
2*7c478bd9Sstevel@tonic-gate  * CDDL HEADER START
3*7c478bd9Sstevel@tonic-gate  *
4*7c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*7c478bd9Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
6*7c478bd9Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
7*7c478bd9Sstevel@tonic-gate  * with the License.
8*7c478bd9Sstevel@tonic-gate  *
9*7c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10*7c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
11*7c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
12*7c478bd9Sstevel@tonic-gate  * and limitations under the License.
13*7c478bd9Sstevel@tonic-gate  *
14*7c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
15*7c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16*7c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
17*7c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
18*7c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
19*7c478bd9Sstevel@tonic-gate  *
20*7c478bd9Sstevel@tonic-gate  * CDDL HEADER END
21*7c478bd9Sstevel@tonic-gate  */
22*7c478bd9Sstevel@tonic-gate /*
23*7c478bd9Sstevel@tonic-gate  * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
24*7c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
25*7c478bd9Sstevel@tonic-gate  */
26*7c478bd9Sstevel@tonic-gate 
27*7c478bd9Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
28*7c478bd9Sstevel@tonic-gate 
29*7c478bd9Sstevel@tonic-gate #include <stdio.h>
30*7c478bd9Sstevel@tonic-gate #include <locale.h>
31*7c478bd9Sstevel@tonic-gate #include <stdlib.h>
32*7c478bd9Sstevel@tonic-gate #include <unistd.h>
33*7c478bd9Sstevel@tonic-gate #include <sys/types.h>
34*7c478bd9Sstevel@tonic-gate #include <string.h>
35*7c478bd9Sstevel@tonic-gate #include "addrem.h"
36*7c478bd9Sstevel@tonic-gate #include "errmsg.h"
37*7c478bd9Sstevel@tonic-gate #include "plcysubr.h"
38*7c478bd9Sstevel@tonic-gate 
39*7c478bd9Sstevel@tonic-gate /* function prototypes */
40*7c478bd9Sstevel@tonic-gate static void	usage();
41*7c478bd9Sstevel@tonic-gate static int	unload_drv(char *, int, int);
42*7c478bd9Sstevel@tonic-gate 
43*7c478bd9Sstevel@tonic-gate 
44*7c478bd9Sstevel@tonic-gate /*
45*7c478bd9Sstevel@tonic-gate  * try to modunload driver.
46*7c478bd9Sstevel@tonic-gate  * return -1 on failure and 0 on success
47*7c478bd9Sstevel@tonic-gate  */
48*7c478bd9Sstevel@tonic-gate static int
49*7c478bd9Sstevel@tonic-gate unload_drv(char *driver_name, int force_flag, int verbose_flag)
50*7c478bd9Sstevel@tonic-gate {
51*7c478bd9Sstevel@tonic-gate 	int modid;
52*7c478bd9Sstevel@tonic-gate 
53*7c478bd9Sstevel@tonic-gate 	get_modid(driver_name, &modid);
54*7c478bd9Sstevel@tonic-gate 	if (modid != -1) {
55*7c478bd9Sstevel@tonic-gate 		if (modctl(MODUNLOAD, modid) < 0) {
56*7c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr, gettext(ERR_MODUN), driver_name);
57*7c478bd9Sstevel@tonic-gate 			if (force_flag == 0) { /* no force flag */
58*7c478bd9Sstevel@tonic-gate 				if (verbose_flag) {
59*7c478bd9Sstevel@tonic-gate 					(void) fprintf(stderr,
60*7c478bd9Sstevel@tonic-gate 					    gettext(NOUPDATE), driver_name);
61*7c478bd9Sstevel@tonic-gate 				}
62*7c478bd9Sstevel@tonic-gate 				/* clean up and exit. remove lock file */
63*7c478bd9Sstevel@tonic-gate 				err_exit();
64*7c478bd9Sstevel@tonic-gate 			}
65*7c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr, gettext(FORCE_UPDATE),
66*7c478bd9Sstevel@tonic-gate 			    driver_name);
67*7c478bd9Sstevel@tonic-gate 
68*7c478bd9Sstevel@tonic-gate 			return (-1);
69*7c478bd9Sstevel@tonic-gate 		}
70*7c478bd9Sstevel@tonic-gate 	}
71*7c478bd9Sstevel@tonic-gate 
72*7c478bd9Sstevel@tonic-gate 	return (0);
73*7c478bd9Sstevel@tonic-gate }
74*7c478bd9Sstevel@tonic-gate 
75*7c478bd9Sstevel@tonic-gate 
76*7c478bd9Sstevel@tonic-gate static void
77*7c478bd9Sstevel@tonic-gate usage()
78*7c478bd9Sstevel@tonic-gate {
79*7c478bd9Sstevel@tonic-gate 	(void) fprintf(stderr, gettext(UPD_DRV_USAGE));
80*7c478bd9Sstevel@tonic-gate 	exit(1);
81*7c478bd9Sstevel@tonic-gate }
82*7c478bd9Sstevel@tonic-gate 
83*7c478bd9Sstevel@tonic-gate 
84*7c478bd9Sstevel@tonic-gate int
85*7c478bd9Sstevel@tonic-gate main(int argc, char *argv[])
86*7c478bd9Sstevel@tonic-gate {
87*7c478bd9Sstevel@tonic-gate 	int	error, opt, major;
88*7c478bd9Sstevel@tonic-gate 	int	cleanup_flag = 0;
89*7c478bd9Sstevel@tonic-gate 	int	update_conf = 1;	/* reload driver.conf by default */
90*7c478bd9Sstevel@tonic-gate 	int	verbose_flag = 0;	/* -v option */
91*7c478bd9Sstevel@tonic-gate 	int	force_flag = 0;		/* -f option */
92*7c478bd9Sstevel@tonic-gate 	int	a_flag = 0;		/* -a option */
93*7c478bd9Sstevel@tonic-gate 	int	d_flag = 0;		/* -d option */
94*7c478bd9Sstevel@tonic-gate 	int	i_flag = 0;		/* -i option */
95*7c478bd9Sstevel@tonic-gate 	int	l_flag = 0;		/* -l option */
96*7c478bd9Sstevel@tonic-gate 	int	m_flag = 0;		/* -m option */
97*7c478bd9Sstevel@tonic-gate 	char	*perms = NULL;
98*7c478bd9Sstevel@tonic-gate 	char	*aliases = 0;
99*7c478bd9Sstevel@tonic-gate 	char	*basedir = NULL;
100*7c478bd9Sstevel@tonic-gate 	char	*policy = NULL;
101*7c478bd9Sstevel@tonic-gate 	char	*priv = NULL;
102*7c478bd9Sstevel@tonic-gate 	char	*driver_name;
103*7c478bd9Sstevel@tonic-gate 	int	found;
104*7c478bd9Sstevel@tonic-gate 	major_t major_num;
105*7c478bd9Sstevel@tonic-gate 	int	rval;
106*7c478bd9Sstevel@tonic-gate 
107*7c478bd9Sstevel@tonic-gate 	(void) setlocale(LC_ALL, "");
108*7c478bd9Sstevel@tonic-gate #if	!defined(TEXT_DOMAIN)	/* Should be defined by cc -D */
109*7c478bd9Sstevel@tonic-gate #define	TEXT_DOMAIN "SYS_TEST"	/* Use this only if it weren't */
110*7c478bd9Sstevel@tonic-gate #endif
111*7c478bd9Sstevel@tonic-gate 	(void) textdomain(TEXT_DOMAIN);
112*7c478bd9Sstevel@tonic-gate 
113*7c478bd9Sstevel@tonic-gate 	/*  must be run by root */
114*7c478bd9Sstevel@tonic-gate 	if (getuid() != 0) {
115*7c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr, gettext(ERR_NOT_ROOT));
116*7c478bd9Sstevel@tonic-gate 		exit(1);
117*7c478bd9Sstevel@tonic-gate 	}
118*7c478bd9Sstevel@tonic-gate 
119*7c478bd9Sstevel@tonic-gate 	while ((opt = getopt(argc, argv, "m:i:b:p:adlfuvP:")) != EOF) {
120*7c478bd9Sstevel@tonic-gate 		switch (opt) {
121*7c478bd9Sstevel@tonic-gate 		case 'a':
122*7c478bd9Sstevel@tonic-gate 			a_flag++;
123*7c478bd9Sstevel@tonic-gate 			break;
124*7c478bd9Sstevel@tonic-gate 		case 'b':
125*7c478bd9Sstevel@tonic-gate 			update_conf = 0;	/* don't update .conf file */
126*7c478bd9Sstevel@tonic-gate 			basedir = optarg;
127*7c478bd9Sstevel@tonic-gate 			break;
128*7c478bd9Sstevel@tonic-gate 		case 'd':
129*7c478bd9Sstevel@tonic-gate 			d_flag++;
130*7c478bd9Sstevel@tonic-gate 			break;
131*7c478bd9Sstevel@tonic-gate 		case 'f':
132*7c478bd9Sstevel@tonic-gate 			force_flag++;
133*7c478bd9Sstevel@tonic-gate 			break;
134*7c478bd9Sstevel@tonic-gate 		case 'i':
135*7c478bd9Sstevel@tonic-gate 			i_flag++;
136*7c478bd9Sstevel@tonic-gate 			aliases = optarg;
137*7c478bd9Sstevel@tonic-gate 			if (check_space_within_quote(aliases) == ERROR) {
138*7c478bd9Sstevel@tonic-gate 				(void) fprintf(stderr, gettext(ERR_NO_SPACE),
139*7c478bd9Sstevel@tonic-gate 					aliases);
140*7c478bd9Sstevel@tonic-gate 				exit(1);
141*7c478bd9Sstevel@tonic-gate 			}
142*7c478bd9Sstevel@tonic-gate 			break;
143*7c478bd9Sstevel@tonic-gate 		case 'l':	/* private option */
144*7c478bd9Sstevel@tonic-gate 			l_flag++;
145*7c478bd9Sstevel@tonic-gate 			break;
146*7c478bd9Sstevel@tonic-gate 		case 'm':
147*7c478bd9Sstevel@tonic-gate 			m_flag++;
148*7c478bd9Sstevel@tonic-gate 			perms = optarg;
149*7c478bd9Sstevel@tonic-gate 			break;
150*7c478bd9Sstevel@tonic-gate 		case 'p':
151*7c478bd9Sstevel@tonic-gate 			policy = optarg;
152*7c478bd9Sstevel@tonic-gate 			break;
153*7c478bd9Sstevel@tonic-gate 		case 'v':
154*7c478bd9Sstevel@tonic-gate 			verbose_flag++;
155*7c478bd9Sstevel@tonic-gate 			break;
156*7c478bd9Sstevel@tonic-gate 		case 'P':
157*7c478bd9Sstevel@tonic-gate 			priv = optarg;
158*7c478bd9Sstevel@tonic-gate 			break;
159*7c478bd9Sstevel@tonic-gate 		case '?' :
160*7c478bd9Sstevel@tonic-gate 		default:
161*7c478bd9Sstevel@tonic-gate 			usage();
162*7c478bd9Sstevel@tonic-gate 		}
163*7c478bd9Sstevel@tonic-gate 	}
164*7c478bd9Sstevel@tonic-gate 
165*7c478bd9Sstevel@tonic-gate 	/*
166*7c478bd9Sstevel@tonic-gate 	 * check for flags and extra args
167*7c478bd9Sstevel@tonic-gate 	 */
168*7c478bd9Sstevel@tonic-gate 	if ((argv[optind] == NULL) || (optind + 1 != argc)) {
169*7c478bd9Sstevel@tonic-gate 		usage();
170*7c478bd9Sstevel@tonic-gate 	}
171*7c478bd9Sstevel@tonic-gate 
172*7c478bd9Sstevel@tonic-gate 	/*
173*7c478bd9Sstevel@tonic-gate 	 * - cannot be adding and removing at the same time
174*7c478bd9Sstevel@tonic-gate 	 * - if -a or -d is specified, it's an error if none of
175*7c478bd9Sstevel@tonic-gate 	 *   -i/-m/-p/-P is specified.
176*7c478bd9Sstevel@tonic-gate 	 */
177*7c478bd9Sstevel@tonic-gate 	if ((a_flag && d_flag) ||
178*7c478bd9Sstevel@tonic-gate 	    ((a_flag || d_flag) &&
179*7c478bd9Sstevel@tonic-gate 	    !m_flag && !i_flag && priv == NULL && policy == NULL)) {
180*7c478bd9Sstevel@tonic-gate 		usage();
181*7c478bd9Sstevel@tonic-gate 	}
182*7c478bd9Sstevel@tonic-gate 
183*7c478bd9Sstevel@tonic-gate 	/*
184*7c478bd9Sstevel@tonic-gate 	 * - with -d option or -a option either -i 'identify_name',
185*7c478bd9Sstevel@tonic-gate 	 *	-m 'permission',  -p 'policy' or -P 'priv' should be specified
186*7c478bd9Sstevel@tonic-gate 	 */
187*7c478bd9Sstevel@tonic-gate 	if (m_flag || i_flag || policy != NULL || priv != NULL) {
188*7c478bd9Sstevel@tonic-gate 		if (!(a_flag || d_flag))
189*7c478bd9Sstevel@tonic-gate 			usage();
190*7c478bd9Sstevel@tonic-gate 	}
191*7c478bd9Sstevel@tonic-gate 
192*7c478bd9Sstevel@tonic-gate 	driver_name = argv[optind];
193*7c478bd9Sstevel@tonic-gate 
194*7c478bd9Sstevel@tonic-gate 	/* set up update_drv filenames */
195*7c478bd9Sstevel@tonic-gate 	if ((build_filenames(basedir)) == ERROR) {
196*7c478bd9Sstevel@tonic-gate 		exit(1);
197*7c478bd9Sstevel@tonic-gate 	}
198*7c478bd9Sstevel@tonic-gate 
199*7c478bd9Sstevel@tonic-gate 	/* no lock is needed for listing minor perm entry */
200*7c478bd9Sstevel@tonic-gate 	if (l_flag) {
201*7c478bd9Sstevel@tonic-gate 		list_entry(minor_perm, driver_name, ":");
202*7c478bd9Sstevel@tonic-gate 
203*7c478bd9Sstevel@tonic-gate 		return (NOERR);
204*7c478bd9Sstevel@tonic-gate 	}
205*7c478bd9Sstevel@tonic-gate 
206*7c478bd9Sstevel@tonic-gate 	/* must be only running version of add_drv/update_drv/rem_drv */
207*7c478bd9Sstevel@tonic-gate 	enter_lock();
208*7c478bd9Sstevel@tonic-gate 
209*7c478bd9Sstevel@tonic-gate 	if ((check_perms_aliases(m_flag, i_flag)) == ERROR) {
210*7c478bd9Sstevel@tonic-gate 		err_exit();
211*7c478bd9Sstevel@tonic-gate 	}
212*7c478bd9Sstevel@tonic-gate 
213*7c478bd9Sstevel@tonic-gate 	/* update_drv doesn't modify /etc/name_to_major file */
214*7c478bd9Sstevel@tonic-gate 	if ((check_name_to_major(R_OK)) == ERROR)
215*7c478bd9Sstevel@tonic-gate 		err_exit();
216*7c478bd9Sstevel@tonic-gate 
217*7c478bd9Sstevel@tonic-gate 	if (priv != NULL && check_priv_entry(priv, a_flag) != 0)
218*7c478bd9Sstevel@tonic-gate 		err_exit();
219*7c478bd9Sstevel@tonic-gate 
220*7c478bd9Sstevel@tonic-gate 	if (policy != NULL && (policy = check_plcy_entry(policy, driver_name,
221*7c478bd9Sstevel@tonic-gate 	    d_flag ? B_TRUE : B_FALSE)) == NULL)
222*7c478bd9Sstevel@tonic-gate 		err_exit();
223*7c478bd9Sstevel@tonic-gate 
224*7c478bd9Sstevel@tonic-gate 	/*
225*7c478bd9Sstevel@tonic-gate 	 * ADD: -a option
226*7c478bd9Sstevel@tonic-gate 	 * i_flag: update /etc/driver_aliases
227*7c478bd9Sstevel@tonic-gate 	 * m_flag: update /etc/minor_perm
228*7c478bd9Sstevel@tonic-gate 	 * -p: update /etc/security/device_policy
229*7c478bd9Sstevel@tonic-gate 	 * -P: update /etc/security/extra_privs
230*7c478bd9Sstevel@tonic-gate 	 * if force_flag is specified continue w/ the next operation
231*7c478bd9Sstevel@tonic-gate 	 */
232*7c478bd9Sstevel@tonic-gate 	if (a_flag) {
233*7c478bd9Sstevel@tonic-gate 		if (m_flag) {
234*7c478bd9Sstevel@tonic-gate 			/* check if the permissions are valid */
235*7c478bd9Sstevel@tonic-gate 			if ((error = check_perm_opts(perms)) == ERROR) {
236*7c478bd9Sstevel@tonic-gate 				if (force_flag == 0) { /* no force flag */
237*7c478bd9Sstevel@tonic-gate 					exit_unlock();
238*7c478bd9Sstevel@tonic-gate 
239*7c478bd9Sstevel@tonic-gate 					return (error);
240*7c478bd9Sstevel@tonic-gate 				}
241*7c478bd9Sstevel@tonic-gate 			}
242*7c478bd9Sstevel@tonic-gate 
243*7c478bd9Sstevel@tonic-gate 			/*
244*7c478bd9Sstevel@tonic-gate 			 * update the file, if and only if
245*7c478bd9Sstevel@tonic-gate 			 * we didn't run into error earlier.
246*7c478bd9Sstevel@tonic-gate 			 */
247*7c478bd9Sstevel@tonic-gate 			if ((error != ERROR) &&
248*7c478bd9Sstevel@tonic-gate 			    (error = update_minor_entry(driver_name, perms))) {
249*7c478bd9Sstevel@tonic-gate 				if (force_flag == 0) { /* no force flag */
250*7c478bd9Sstevel@tonic-gate 					exit_unlock();
251*7c478bd9Sstevel@tonic-gate 
252*7c478bd9Sstevel@tonic-gate 					return (error);
253*7c478bd9Sstevel@tonic-gate 				}
254*7c478bd9Sstevel@tonic-gate 			}
255*7c478bd9Sstevel@tonic-gate 			cleanup_flag |= CLEAN_NAM_MAJ;
256*7c478bd9Sstevel@tonic-gate 
257*7c478bd9Sstevel@tonic-gate 			/*
258*7c478bd9Sstevel@tonic-gate 			 * Notify running system of minor perm change
259*7c478bd9Sstevel@tonic-gate 			 */
260*7c478bd9Sstevel@tonic-gate 			if (basedir == NULL || (strcmp(basedir, "/") == 0)) {
261*7c478bd9Sstevel@tonic-gate 				rval = devfs_add_minor_perm(driver_name,
262*7c478bd9Sstevel@tonic-gate 				    log_minorperm_error);
263*7c478bd9Sstevel@tonic-gate 				if (rval) {
264*7c478bd9Sstevel@tonic-gate 					(void) fprintf(stderr,
265*7c478bd9Sstevel@tonic-gate 					    gettext(ERR_UPDATE_PERM),
266*7c478bd9Sstevel@tonic-gate 					    driver_name);
267*7c478bd9Sstevel@tonic-gate 				}
268*7c478bd9Sstevel@tonic-gate 			}
269*7c478bd9Sstevel@tonic-gate 		}
270*7c478bd9Sstevel@tonic-gate 
271*7c478bd9Sstevel@tonic-gate 		if (priv != NULL) {
272*7c478bd9Sstevel@tonic-gate 			(void) append_to_file(driver_name, priv, extra_privs,
273*7c478bd9Sstevel@tonic-gate 					',', ":");
274*7c478bd9Sstevel@tonic-gate 			cleanup_flag |= CLEAN_DRV_PRIV;
275*7c478bd9Sstevel@tonic-gate 		}
276*7c478bd9Sstevel@tonic-gate 
277*7c478bd9Sstevel@tonic-gate 		if (policy != NULL) {
278*7c478bd9Sstevel@tonic-gate 			if ((error = update_device_policy(device_policy,
279*7c478bd9Sstevel@tonic-gate 			    policy, B_TRUE)) != 0) {
280*7c478bd9Sstevel@tonic-gate 				exit_unlock();
281*7c478bd9Sstevel@tonic-gate 				return (error);
282*7c478bd9Sstevel@tonic-gate 			}
283*7c478bd9Sstevel@tonic-gate 			cleanup_flag |= CLEAN_DEV_POLICY;
284*7c478bd9Sstevel@tonic-gate 		}
285*7c478bd9Sstevel@tonic-gate 
286*7c478bd9Sstevel@tonic-gate 		if (i_flag) {
287*7c478bd9Sstevel@tonic-gate 			/* check if the alias is unique */
288*7c478bd9Sstevel@tonic-gate 			if ((error = aliases_unique(aliases)) == ERROR) {
289*7c478bd9Sstevel@tonic-gate 				exit_unlock();
290*7c478bd9Sstevel@tonic-gate 
291*7c478bd9Sstevel@tonic-gate 				return (error);
292*7c478bd9Sstevel@tonic-gate 			}
293*7c478bd9Sstevel@tonic-gate 
294*7c478bd9Sstevel@tonic-gate 			/* update the file */
295*7c478bd9Sstevel@tonic-gate 			if ((error = update_driver_aliases(driver_name,
296*7c478bd9Sstevel@tonic-gate 			    aliases)) == ERROR) {
297*7c478bd9Sstevel@tonic-gate 				exit_unlock();
298*7c478bd9Sstevel@tonic-gate 
299*7c478bd9Sstevel@tonic-gate 				return (error);
300*7c478bd9Sstevel@tonic-gate 			}
301*7c478bd9Sstevel@tonic-gate 
302*7c478bd9Sstevel@tonic-gate 			found = get_major_no(driver_name, name_to_major);
303*7c478bd9Sstevel@tonic-gate 			if (found == ERROR) {
304*7c478bd9Sstevel@tonic-gate 				(void) fprintf(stderr, gettext(ERR_MAX_MAJOR),
305*7c478bd9Sstevel@tonic-gate 				    name_to_major);
306*7c478bd9Sstevel@tonic-gate 				err_exit();
307*7c478bd9Sstevel@tonic-gate 			}
308*7c478bd9Sstevel@tonic-gate 
309*7c478bd9Sstevel@tonic-gate 			if (found == UNIQUE) {
310*7c478bd9Sstevel@tonic-gate 				(void) fprintf(stderr,
311*7c478bd9Sstevel@tonic-gate 				    gettext(ERR_NOT_INSTALLED), driver_name);
312*7c478bd9Sstevel@tonic-gate 				err_exit();
313*7c478bd9Sstevel@tonic-gate 			}
314*7c478bd9Sstevel@tonic-gate 
315*7c478bd9Sstevel@tonic-gate 			major_num = (major_t)found;
316*7c478bd9Sstevel@tonic-gate 
317*7c478bd9Sstevel@tonic-gate 			/* paranoia - if we crash whilst configuring */
318*7c478bd9Sstevel@tonic-gate 			sync();
319*7c478bd9Sstevel@tonic-gate 
320*7c478bd9Sstevel@tonic-gate 			cleanup_flag |= CLEAN_DRV_ALIAS;
321*7c478bd9Sstevel@tonic-gate 			if (config_driver(driver_name, major_num, aliases, NULL,
322*7c478bd9Sstevel@tonic-gate 			    cleanup_flag, verbose_flag) == ERROR) {
323*7c478bd9Sstevel@tonic-gate 				err_exit();
324*7c478bd9Sstevel@tonic-gate 			}
325*7c478bd9Sstevel@tonic-gate 
326*7c478bd9Sstevel@tonic-gate 		}
327*7c478bd9Sstevel@tonic-gate 		if (update_conf && (i_flag || policy != NULL))
328*7c478bd9Sstevel@tonic-gate 			/* load the driver */
329*7c478bd9Sstevel@tonic-gate 			load_driver(driver_name, verbose_flag);
330*7c478bd9Sstevel@tonic-gate 
331*7c478bd9Sstevel@tonic-gate 		exit_unlock();
332*7c478bd9Sstevel@tonic-gate 
333*7c478bd9Sstevel@tonic-gate 		return (0);
334*7c478bd9Sstevel@tonic-gate 	}
335*7c478bd9Sstevel@tonic-gate 
336*7c478bd9Sstevel@tonic-gate 
337*7c478bd9Sstevel@tonic-gate 	/*
338*7c478bd9Sstevel@tonic-gate 	 * DELETE: -d option
339*7c478bd9Sstevel@tonic-gate 	 * i_flag: update /etc/driver_aliases
340*7c478bd9Sstevel@tonic-gate 	 * m_flag: update /etc/minor_perm
341*7c478bd9Sstevel@tonic-gate 	 * -p: update /etc/security/device_policy
342*7c478bd9Sstevel@tonic-gate 	 * -P: update /etc/security/extra_privs
343*7c478bd9Sstevel@tonic-gate 	 */
344*7c478bd9Sstevel@tonic-gate 	if (d_flag) {
345*7c478bd9Sstevel@tonic-gate 		int err = NOERR;
346*7c478bd9Sstevel@tonic-gate 
347*7c478bd9Sstevel@tonic-gate 		if (m_flag) {
348*7c478bd9Sstevel@tonic-gate 			/*
349*7c478bd9Sstevel@tonic-gate 			 * On a running system, we first need to
350*7c478bd9Sstevel@tonic-gate 			 * remove devfs's idea of the minor perms.
351*7c478bd9Sstevel@tonic-gate 			 * We don't have any ability to do this singly
352*7c478bd9Sstevel@tonic-gate 			 * at this point.
353*7c478bd9Sstevel@tonic-gate 			 */
354*7c478bd9Sstevel@tonic-gate 			if (basedir == NULL || (strcmp(basedir, "/") == 0)) {
355*7c478bd9Sstevel@tonic-gate 				rval = devfs_rm_minor_perm(driver_name,
356*7c478bd9Sstevel@tonic-gate 				    log_minorperm_error);
357*7c478bd9Sstevel@tonic-gate 				if (rval) {
358*7c478bd9Sstevel@tonic-gate 					(void) fprintf(stderr,
359*7c478bd9Sstevel@tonic-gate 					    gettext(ERR_UPDATE_PERM),
360*7c478bd9Sstevel@tonic-gate 					    driver_name);
361*7c478bd9Sstevel@tonic-gate 				}
362*7c478bd9Sstevel@tonic-gate 			}
363*7c478bd9Sstevel@tonic-gate 
364*7c478bd9Sstevel@tonic-gate 			if ((error = delete_entry(minor_perm,
365*7c478bd9Sstevel@tonic-gate 			    driver_name, ":", perms)) != NOERR) {
366*7c478bd9Sstevel@tonic-gate 				(void) fprintf(stderr, gettext(ERR_NO_ENTRY),
367*7c478bd9Sstevel@tonic-gate 				    driver_name, minor_perm);
368*7c478bd9Sstevel@tonic-gate 				err = error;
369*7c478bd9Sstevel@tonic-gate 			}
370*7c478bd9Sstevel@tonic-gate 			/*
371*7c478bd9Sstevel@tonic-gate 			 * Notify running system of new minor perm state
372*7c478bd9Sstevel@tonic-gate 			 */
373*7c478bd9Sstevel@tonic-gate 			if (basedir == NULL || (strcmp(basedir, "/") == 0)) {
374*7c478bd9Sstevel@tonic-gate 				rval = devfs_add_minor_perm(driver_name,
375*7c478bd9Sstevel@tonic-gate 				    log_minorperm_error);
376*7c478bd9Sstevel@tonic-gate 				if (rval) {
377*7c478bd9Sstevel@tonic-gate 					(void) fprintf(stderr,
378*7c478bd9Sstevel@tonic-gate 					    gettext(ERR_UPDATE_PERM),
379*7c478bd9Sstevel@tonic-gate 					    driver_name);
380*7c478bd9Sstevel@tonic-gate 				}
381*7c478bd9Sstevel@tonic-gate 			}
382*7c478bd9Sstevel@tonic-gate 		}
383*7c478bd9Sstevel@tonic-gate 
384*7c478bd9Sstevel@tonic-gate 		if (i_flag) {
385*7c478bd9Sstevel@tonic-gate 			if ((error = delete_entry(driver_aliases,
386*7c478bd9Sstevel@tonic-gate 			    driver_name, ":", aliases)) != NOERR) {
387*7c478bd9Sstevel@tonic-gate 				(void) fprintf(stderr, gettext(ERR_NO_ENTRY),
388*7c478bd9Sstevel@tonic-gate 				    driver_name, driver_aliases);
389*7c478bd9Sstevel@tonic-gate 				if (err != NOERR)
390*7c478bd9Sstevel@tonic-gate 					err = error;
391*7c478bd9Sstevel@tonic-gate 			}
392*7c478bd9Sstevel@tonic-gate 		}
393*7c478bd9Sstevel@tonic-gate 
394*7c478bd9Sstevel@tonic-gate 		if (priv != NULL) {
395*7c478bd9Sstevel@tonic-gate 			if ((error = delete_entry(extra_privs, driver_name, ":",
396*7c478bd9Sstevel@tonic-gate 			    priv)) != NOERR) {
397*7c478bd9Sstevel@tonic-gate 				(void) fprintf(stderr, gettext(ERR_NO_ENTRY),
398*7c478bd9Sstevel@tonic-gate 				    driver_name, extra_privs);
399*7c478bd9Sstevel@tonic-gate 				if (err != NOERR)
400*7c478bd9Sstevel@tonic-gate 					err = error;
401*7c478bd9Sstevel@tonic-gate 			}
402*7c478bd9Sstevel@tonic-gate 		}
403*7c478bd9Sstevel@tonic-gate 
404*7c478bd9Sstevel@tonic-gate 		if (policy != NULL) {
405*7c478bd9Sstevel@tonic-gate 			if ((error = delete_plcy_entry(device_policy,
406*7c478bd9Sstevel@tonic-gate 				policy)) != NOERR) {
407*7c478bd9Sstevel@tonic-gate 				(void) fprintf(stderr, gettext(ERR_NO_ENTRY),
408*7c478bd9Sstevel@tonic-gate 				    driver_name, device_policy);
409*7c478bd9Sstevel@tonic-gate 				if (err != NOERR)
410*7c478bd9Sstevel@tonic-gate 					err = error;
411*7c478bd9Sstevel@tonic-gate 			}
412*7c478bd9Sstevel@tonic-gate 		}
413*7c478bd9Sstevel@tonic-gate 
414*7c478bd9Sstevel@tonic-gate 		if (err == NOERR && update_conf) {
415*7c478bd9Sstevel@tonic-gate 			if (i_flag || m_flag) {
416*7c478bd9Sstevel@tonic-gate 				/* try to unload the driver */
417*7c478bd9Sstevel@tonic-gate 				(void) unload_drv(driver_name,
418*7c478bd9Sstevel@tonic-gate 				    force_flag, verbose_flag);
419*7c478bd9Sstevel@tonic-gate 			}
420*7c478bd9Sstevel@tonic-gate 			/* reload the policy */
421*7c478bd9Sstevel@tonic-gate 			if (policy != NULL)
422*7c478bd9Sstevel@tonic-gate 				load_driver(driver_name, verbose_flag);
423*7c478bd9Sstevel@tonic-gate 		}
424*7c478bd9Sstevel@tonic-gate 		exit_unlock();
425*7c478bd9Sstevel@tonic-gate 
426*7c478bd9Sstevel@tonic-gate 		return (err);
427*7c478bd9Sstevel@tonic-gate 	}
428*7c478bd9Sstevel@tonic-gate 
429*7c478bd9Sstevel@tonic-gate 	/* driver name must exist (for update_conf stuff) */
430*7c478bd9Sstevel@tonic-gate 	major = get_major_no(driver_name, name_to_major);
431*7c478bd9Sstevel@tonic-gate 	if (major == ERROR) {
432*7c478bd9Sstevel@tonic-gate 		err_exit();
433*7c478bd9Sstevel@tonic-gate 	}
434*7c478bd9Sstevel@tonic-gate 
435*7c478bd9Sstevel@tonic-gate 	/*
436*7c478bd9Sstevel@tonic-gate 	 * Update driver.conf file:
437*7c478bd9Sstevel@tonic-gate 	 *	First try to unload driver module. If it fails, there may
438*7c478bd9Sstevel@tonic-gate 	 *	be attached devices using the old driver.conf properties,
439*7c478bd9Sstevel@tonic-gate 	 *	so we cannot safely update driver.conf
440*7c478bd9Sstevel@tonic-gate 	 *
441*7c478bd9Sstevel@tonic-gate 	 *	The user may specify -f to force a driver.conf update.
442*7c478bd9Sstevel@tonic-gate 	 *	In this case, we will update driver.conf cache. All attached
443*7c478bd9Sstevel@tonic-gate 	 *	devices still reference old driver.conf properties, including
444*7c478bd9Sstevel@tonic-gate 	 *	driver global properties. Devices attached in the future will
445*7c478bd9Sstevel@tonic-gate 	 *	referent properties in the updated driver.conf file.
446*7c478bd9Sstevel@tonic-gate 	 */
447*7c478bd9Sstevel@tonic-gate 	if (update_conf) {
448*7c478bd9Sstevel@tonic-gate 		(void) unload_drv(driver_name, force_flag, verbose_flag);
449*7c478bd9Sstevel@tonic-gate 
450*7c478bd9Sstevel@tonic-gate 		if ((modctl(MODUNLOADDRVCONF, major) != 0) ||
451*7c478bd9Sstevel@tonic-gate 		    (modctl(MODLOADDRVCONF, major) != 0)) {
452*7c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr, gettext(ERR_DRVCONF),
453*7c478bd9Sstevel@tonic-gate 			    driver_name);
454*7c478bd9Sstevel@tonic-gate 			err_exit();
455*7c478bd9Sstevel@tonic-gate 		}
456*7c478bd9Sstevel@tonic-gate 
457*7c478bd9Sstevel@tonic-gate 		if (verbose_flag) {
458*7c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr, gettext(DRVCONF_UPDATED),
459*7c478bd9Sstevel@tonic-gate 			    driver_name);
460*7c478bd9Sstevel@tonic-gate 		}
461*7c478bd9Sstevel@tonic-gate 	}
462*7c478bd9Sstevel@tonic-gate 
463*7c478bd9Sstevel@tonic-gate 	/* rebuild /devices & /dev */
464*7c478bd9Sstevel@tonic-gate 	load_driver(driver_name, verbose_flag);
465*7c478bd9Sstevel@tonic-gate 
466*7c478bd9Sstevel@tonic-gate 	exit_unlock();
467*7c478bd9Sstevel@tonic-gate 
468*7c478bd9Sstevel@tonic-gate 	return (NOERR);
469*7c478bd9Sstevel@tonic-gate }
470