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