1 /*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21 /*
22 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
24 */
25
26 #include <sys/types.h>
27 #include <sys/systm.h>
28 #include <sys/param.h>
29 #include <sys/user.h>
30 #include <sys/vm.h>
31 #include <sys/conf.h>
32 #include <sys/class.h>
33 #include <sys/vfs.h>
34 #include <sys/vnode.h>
35 #include <sys/mount.h>
36 #include <sys/systm.h>
37 #include <sys/modctl.h>
38 #include <sys/exec.h>
39 #include <sys/exechdr.h>
40 #include <sys/devops.h>
41 #include <sys/ddi.h>
42 #include <sys/sunddi.h>
43 #include <sys/cmn_err.h>
44 #include <sys/hwconf.h>
45 #include <sys/ddi_impldefs.h>
46 #include <sys/autoconf.h>
47 #include <sys/disp.h>
48 #include <sys/kmem.h>
49 #include <sys/instance.h>
50 #include <sys/modhash.h>
51 #include <sys/dacf.h>
52 #include <sys/debug.h>
53 #include <ipp/ipp.h>
54 #include <sys/strsubr.h>
55 #include <sys/kcpc.h>
56 #include <sys/brand.h>
57 #include <sys/cpc_pcbe.h>
58 #include <sys/kstat.h>
59 #include <sys/socketvar.h>
60 #include <sys/kiconv.h>
61
62 extern int moddebug;
63
64 extern struct cb_ops no_cb_ops;
65 extern struct dev_ops nodev_ops;
66 extern struct dev_ops mod_nodev_ops;
67
68 extern struct modctl *mod_getctl(struct modlinkage *);
69 extern int errsys(), nodev(), nulldev();
70
71 extern int findmodbyname(char *);
72 extern int mod_getsysnum(char *);
73
74 extern struct execsw execsw[];
75
76 /*
77 * Define dev_ops for unused devopsp entry.
78 */
79 struct dev_ops mod_nodev_ops = {
80 DEVO_REV, /* devo_rev */
81 0, /* refcnt */
82 ddi_no_info, /* info */
83 nulldev, /* identify */
84 nulldev, /* probe */
85 ddifail, /* attach */
86 nodev, /* detach */
87 nulldev, /* reset */
88 &no_cb_ops, /* character/block driver operations */
89 (struct bus_ops *)0 /* bus operations for nexus drivers */
90 };
91
92 /*
93 * Define mod_ops for each supported module type
94 */
95
96 /*
97 * Null operations; used for uninitialized and "misc" modules.
98 */
99 static int mod_null(struct modldrv *, struct modlinkage *);
100 static int mod_infonull(void *, struct modlinkage *, int *);
101
102 struct mod_ops mod_miscops = {
103 mod_null, mod_null, mod_infonull
104 };
105
106 /* CPU Modules */
107 struct mod_ops mod_cpuops = {
108 mod_null, mod_null, mod_infonull
109 };
110
111 /*
112 * Cryptographic Modules
113 */
114 struct mod_ops mod_cryptoops = {
115 mod_null, mod_null, mod_infonull
116 };
117
118 /*
119 * IP Policy Modules
120 */
121 static int mod_installipp(struct modlipp *, struct modlinkage *);
122 static int mod_removeipp(struct modlipp *, struct modlinkage *);
123 static int mod_infoipp(struct modlipp *, struct modlinkage *, int *);
124
125 struct mod_ops mod_ippops = {
126 mod_installipp, mod_removeipp, mod_infoipp
127 };
128
129 /*
130 * Device drivers
131 */
132 static int mod_infodrv(struct modldrv *, struct modlinkage *, int *);
133 static int mod_installdrv(struct modldrv *, struct modlinkage *);
134 static int mod_removedrv(struct modldrv *, struct modlinkage *);
135
136 struct mod_ops mod_driverops = {
137 mod_installdrv, mod_removedrv, mod_infodrv
138 };
139
140 /*
141 * System calls (new interface)
142 */
143 static int mod_infosys(struct modlsys *, struct modlinkage *, int *);
144 static int mod_installsys(struct modlsys *, struct modlinkage *);
145 static int mod_removesys(struct modlsys *, struct modlinkage *);
146
147 struct mod_ops mod_syscallops = {
148 mod_installsys, mod_removesys, mod_infosys
149 };
150
151 #ifdef _SYSCALL32_IMPL
152 /*
153 * 32-bit system calls in 64-bit kernel
154 */
155 static int mod_infosys32(struct modlsys *, struct modlinkage *, int *);
156 static int mod_installsys32(struct modlsys *, struct modlinkage *);
157 static int mod_removesys32(struct modlsys *, struct modlinkage *);
158
159 struct mod_ops mod_syscallops32 = {
160 mod_installsys32, mod_removesys32, mod_infosys32
161 };
162 #endif /* _SYSCALL32_IMPL */
163
164 /*
165 * Filesystems
166 */
167 static int mod_infofs(struct modlfs *, struct modlinkage *, int *);
168 static int mod_installfs(struct modlfs *, struct modlinkage *);
169 static int mod_removefs(struct modlfs *, struct modlinkage *);
170
171 struct mod_ops mod_fsops = {
172 mod_installfs, mod_removefs, mod_infofs
173 };
174
175 /*
176 * Streams modules.
177 */
178 static int mod_infostrmod(struct modlstrmod *, struct modlinkage *, int *);
179 static int mod_installstrmod(struct modlstrmod *, struct modlinkage *);
180 static int mod_removestrmod(struct modlstrmod *, struct modlinkage *);
181
182 struct mod_ops mod_strmodops = {
183 mod_installstrmod, mod_removestrmod, mod_infostrmod
184 };
185
186 /*
187 * Socket modules.
188 */
189 static int mod_infosockmod(struct modlsockmod *, struct modlinkage *, int *);
190 static int mod_installsockmod(struct modlsockmod *, struct modlinkage *);
191 static int mod_removesockmod(struct modlsockmod *, struct modlinkage *);
192
193 struct mod_ops mod_sockmodops = {
194 mod_installsockmod, mod_removesockmod, mod_infosockmod
195 };
196
197 /*
198 * Scheduling classes.
199 */
200 static int mod_infosched(struct modlsched *, struct modlinkage *, int *);
201 static int mod_installsched(struct modlsched *, struct modlinkage *);
202 static int mod_removesched(struct modlsched *, struct modlinkage *);
203
204 struct mod_ops mod_schedops = {
205 mod_installsched, mod_removesched, mod_infosched
206 };
207
208 /*
209 * Exec file type (like ELF, ...).
210 */
211 static int mod_infoexec(struct modlexec *, struct modlinkage *, int *);
212 static int mod_installexec(struct modlexec *, struct modlinkage *);
213 static int mod_removeexec(struct modlexec *, struct modlinkage *);
214
215 struct mod_ops mod_execops = {
216 mod_installexec, mod_removeexec, mod_infoexec
217 };
218
219 /*
220 * Dacf (Dynamic Autoconfiguration) modules.
221 */
222 static int mod_infodacf(struct modldacf *, struct modlinkage *, int *);
223 static int mod_installdacf(struct modldacf *, struct modlinkage *);
224 static int mod_removedacf(struct modldacf *, struct modlinkage *);
225
226 struct mod_ops mod_dacfops = {
227 mod_installdacf, mod_removedacf, mod_infodacf
228 };
229
230 /*
231 * PCBE (Performance Counter BackEnd) modules.
232 */
233 static int mod_installpcbe(struct modlpcbe *, struct modlinkage *);
234 static int mod_removepcbe(struct modlpcbe *, struct modlinkage *);
235
236 struct mod_ops mod_pcbeops = {
237 mod_installpcbe, mod_removepcbe, mod_infonull
238 };
239
240 /*
241 * Brand modules.
242 */
243 static int mod_installbrand(struct modlbrand *, struct modlinkage *);
244 static int mod_removebrand(struct modlbrand *, struct modlinkage *);
245
246 struct mod_ops mod_brandops = {
247 mod_installbrand, mod_removebrand, mod_infonull
248 };
249
250 /*
251 * kiconv modules.
252 */
253 static int mod_installkiconv(struct modlkiconv *, struct modlinkage *);
254 static int mod_removekiconv(struct modlkiconv *, struct modlinkage *);
255
256 struct mod_ops mod_kiconvops = {
257 mod_installkiconv, mod_removekiconv, mod_infonull
258 };
259
260 static struct sysent *mod_getsysent(struct modlinkage *, struct sysent *);
261
262 static char uninstall_err[] = "Cannot uninstall %s; not installed";
263
264 /*
265 * Debugging support
266 */
267 #define DRV_DBG MODDEBUG_LOADMSG2
268
269 /*PRINTFLIKE2*/
270 static void mod_dprintf(int flag, const char *format, ...) __KPRINTFLIKE(2);
271
272 static void
mod_dprintf(int flag,const char * format,...)273 mod_dprintf(int flag, const char *format, ...)
274 {
275 va_list alist;
276
277 if ((moddebug & flag) != 0) {
278 va_start(alist, format);
279 (void) vprintf(format, alist);
280 va_end(alist);
281 }
282 }
283
284 /*
285 * Install a module.
286 * (This routine is in the Solaris SPARC DDI/DKI)
287 */
288 int
mod_install(struct modlinkage * modlp)289 mod_install(struct modlinkage *modlp)
290 {
291 int retval = -1; /* No linkage structures */
292 struct modlmisc **linkpp;
293 struct modlmisc **linkpp1;
294
295 if (modlp->ml_rev != MODREV_1) {
296 printf("mod_install: modlinkage structure is not MODREV_1\n");
297 return (EINVAL);
298 }
299 linkpp = (struct modlmisc **)&modlp->ml_linkage[0];
300
301 while (*linkpp != NULL) {
302 if ((retval = MODL_INSTALL(*linkpp, modlp)) != 0) {
303 linkpp1 = (struct modlmisc **)&modlp->ml_linkage[0];
304
305 while (linkpp1 != linkpp) {
306 MODL_REMOVE(*linkpp1, modlp); /* clean up */
307 linkpp1++;
308 }
309 break;
310 }
311 linkpp++;
312 }
313 return (retval);
314 }
315
316 static char *reins_err =
317 "Could not reinstall %s\nReboot to correct the problem";
318
319 /*
320 * Remove a module. This is called by the module wrapper routine.
321 * (This routine is in the Solaris SPARC DDI/DKI)
322 */
323 int
mod_remove(struct modlinkage * modlp)324 mod_remove(struct modlinkage *modlp)
325 {
326 int retval = 0;
327 struct modlmisc **linkpp, *last_linkp;
328
329 linkpp = (struct modlmisc **)&modlp->ml_linkage[0];
330
331 while (*linkpp != NULL) {
332 if ((retval = MODL_REMOVE(*linkpp, modlp)) != 0) {
333 last_linkp = *linkpp;
334 linkpp = (struct modlmisc **)&modlp->ml_linkage[0];
335 while (*linkpp != last_linkp) {
336 if (MODL_INSTALL(*linkpp, modlp) != 0) {
337 cmn_err(CE_WARN, reins_err,
338 (*linkpp)->misc_linkinfo);
339 break;
340 }
341 linkpp++;
342 }
343 break;
344 }
345 linkpp++;
346 }
347 return (retval);
348 }
349
350 /*
351 * Get module status.
352 * (This routine is in the Solaris SPARC DDI/DKI)
353 */
354 int
mod_info(struct modlinkage * modlp,struct modinfo * modinfop)355 mod_info(struct modlinkage *modlp, struct modinfo *modinfop)
356 {
357 int i;
358 int retval = 0;
359 struct modspecific_info *msip;
360 struct modlmisc **linkpp;
361
362 modinfop->mi_rev = modlp->ml_rev;
363
364 linkpp = (struct modlmisc **)modlp->ml_linkage;
365 msip = &modinfop->mi_msinfo[0];
366
367 for (i = 0; i < MODMAXLINK; i++) {
368 if (*linkpp == NULL) {
369 msip->msi_linkinfo[0] = '\0';
370 } else {
371 (void) strncpy(msip->msi_linkinfo,
372 (*linkpp)->misc_linkinfo, MODMAXLINKINFOLEN);
373 retval = MODL_INFO(*linkpp, modlp, &msip->msi_p0);
374 if (retval != 0)
375 break;
376 linkpp++;
377 }
378 msip++;
379 }
380
381 if (modinfop->mi_info == MI_INFO_LINKAGE) {
382 /*
383 * Slight kludge used to extract the address of the
384 * modlinkage structure from the module (just after
385 * loading a module for the very first time)
386 */
387 modinfop->mi_base = (void *)modlp;
388 }
389
390 if (retval == 0)
391 return (1);
392 return (0);
393 }
394
395 /*
396 * Get module name.
397 */
398 const char *
mod_modname(struct modlinkage * modlp)399 mod_modname(struct modlinkage *modlp)
400 {
401 struct modctl *mcp;
402
403 if ((mcp = mod_getctl(modlp)) == NULL)
404 return (NULL);
405
406 return (mcp->mod_modname);
407 }
408
409 /*
410 * Null operation; return 0.
411 */
412 /*ARGSUSED*/
413 static int
mod_null(struct modldrv * modl,struct modlinkage * modlp)414 mod_null(struct modldrv *modl, struct modlinkage *modlp)
415 {
416 return (0);
417 }
418
419 /*
420 * Status for User modules.
421 */
422 /*ARGSUSED*/
423 static int
mod_infonull(void * modl,struct modlinkage * modlp,int * p0)424 mod_infonull(void *modl, struct modlinkage *modlp, int *p0)
425 {
426 *p0 = -1; /* for modinfo display */
427 return (0);
428 }
429
430 /*
431 * Driver status info
432 */
433 /*ARGSUSED*/
434 static int
mod_infodrv(struct modldrv * modl,struct modlinkage * modlp,int * p0)435 mod_infodrv(struct modldrv *modl, struct modlinkage *modlp, int *p0)
436 {
437 struct modctl *mcp;
438 char *mod_name;
439
440 if ((mcp = mod_getctl(modlp)) == NULL) {
441 *p0 = -1;
442 return (0); /* driver is not yet installed */
443 }
444
445 mod_name = mcp->mod_modname;
446
447 *p0 = ddi_name_to_major(mod_name);
448 return (0);
449 }
450
451 /*
452 * Manage dacf (device autoconfiguration) modules
453 */
454
455 /*ARGSUSED*/
456 static int
mod_infodacf(struct modldacf * modl,struct modlinkage * modlp,int * p0)457 mod_infodacf(struct modldacf *modl, struct modlinkage *modlp, int *p0)
458 {
459 if (mod_getctl(modlp) == NULL) {
460 *p0 = -1;
461 return (0); /* module is not yet installed */
462 }
463
464 *p0 = 0;
465 return (0);
466 }
467
468 static int
mod_installdacf(struct modldacf * modl,struct modlinkage * modlp)469 mod_installdacf(struct modldacf *modl, struct modlinkage *modlp)
470 {
471 struct modctl *mcp;
472
473 if ((mcp = mod_getctl(modlp)) == NULL)
474 return (EINVAL);
475 return (dacf_module_register(mcp->mod_modname, modl->dacf_dacfsw));
476 }
477
478 /*ARGSUSED*/
479 static int
mod_removedacf(struct modldacf * modl,struct modlinkage * modlp)480 mod_removedacf(struct modldacf *modl, struct modlinkage *modlp)
481 {
482 struct modctl *mcp;
483
484 if ((mcp = mod_getctl(modlp)) == NULL)
485 return (EINVAL);
486 return (dacf_module_unregister(mcp->mod_modname));
487 }
488
489 /*
490 * Manage PCBE (Performance Counter BackEnd) modules.
491 */
492 /*ARGSUSED*/
493 static int
mod_installpcbe(struct modlpcbe * modl,struct modlinkage * modlp)494 mod_installpcbe(struct modlpcbe *modl, struct modlinkage *modlp)
495 {
496 if (modl->pcbe_ops->pcbe_ver != PCBE_VER_1) {
497 cmn_err(CE_WARN, "pcbe '%s' version mismatch",
498 modl->pcbe_linkinfo);
499 return (EINVAL);
500 }
501
502 kcpc_register_pcbe(modl->pcbe_ops);
503 return (0);
504 }
505
506 /*
507 * PCBEs may not be unloaded. It would make CPC locking too complex, and since
508 * PCBEs are loaded once and used for life, there is no harm done in leaving
509 * them in the system.
510 */
511 /*ARGSUSED*/
512 static int
mod_removepcbe(struct modlpcbe * modl,struct modlinkage * modlp)513 mod_removepcbe(struct modlpcbe *modl, struct modlinkage *modlp)
514 {
515 return (EBUSY);
516 }
517
518 /*
519 * Manage BrandZ modules.
520 */
521 /*ARGSUSED*/
522 static int
mod_installbrand(struct modlbrand * modl,struct modlinkage * modlp)523 mod_installbrand(struct modlbrand *modl, struct modlinkage *modlp)
524 {
525 return (brand_register(modl->brand_branddef));
526 }
527
528 /*ARGSUSED*/
529 static int
mod_removebrand(struct modlbrand * modl,struct modlinkage * modlp)530 mod_removebrand(struct modlbrand *modl, struct modlinkage *modlp)
531 {
532 return (brand_unregister(modl->brand_branddef));
533 }
534
535 /*
536 * Install a new driver
537 */
538 static int
mod_installdrv(struct modldrv * modl,struct modlinkage * modlp)539 mod_installdrv(struct modldrv *modl, struct modlinkage *modlp)
540 {
541 struct modctl *mcp;
542 struct dev_ops *ops;
543 char *modname;
544 major_t major;
545 struct dev_ops *dp;
546 struct devnames *dnp;
547 struct streamtab *str;
548 cdevsw_impl_t *cdp;
549 uint_t sqtype;
550 uint_t qflag;
551 uint_t flag;
552 int err = 0;
553
554 /* sanity check module */
555 if ((mcp = mod_getctl(modlp)) == NULL) {
556 cmn_err(CE_WARN, "mod_install: bad module linkage data");
557 err = ENXIO;
558 goto done;
559 }
560 modname = mcp->mod_modname;
561
562 /* Sanity check modname */
563 if ((major = ddi_name_to_major(modname)) == DDI_MAJOR_T_NONE) {
564 #ifdef DEBUG
565 cmn_err(CE_WARN,
566 "mod_installdrv: no major number for %s", modname);
567 #endif
568 err = ENXIO;
569 goto done;
570 }
571
572 /* Verify MP safety flag */
573 ops = modl->drv_dev_ops;
574 if (ops->devo_bus_ops == NULL && ops->devo_cb_ops != NULL &&
575 !(ops->devo_cb_ops->cb_flag & D_MP)) {
576 cmn_err(CE_WARN,
577 "mod_installdrv: MT-unsafe driver '%s' rejected", modname);
578 err = ENXIO;
579 goto done;
580 }
581
582
583 /* Is bus_map_fault signature correct (version 8 and higher)? */
584 if (ops->devo_bus_ops != NULL &&
585 ops->devo_bus_ops->bus_map_fault != NULL &&
586 ops->devo_bus_ops->bus_map_fault != i_ddi_map_fault &&
587 ops->devo_bus_ops->busops_rev < BUSO_REV_8) {
588
589 cmn_err(CE_WARN,
590 "mod_installdrv: busops' revision of '%s' is too low"
591 " (must be at least 8)", modname);
592 err = ENXIO;
593 goto done;
594 }
595
596
597 /* Make sure the driver is uninstalled */
598 dnp = &devnamesp[major];
599 LOCK_DEV_OPS(&dnp->dn_lock);
600 dp = devopsp[major];
601
602 if (dnp->dn_flags & (DN_DRIVER_REMOVED|DN_DRIVER_INACTIVE)) {
603 #ifdef DEBUG
604 cmn_err(CE_CONT,
605 "mod_installdrv: driver %s not installed", modname);
606 #endif
607 err = ENXIO;
608 goto unlock;
609 }
610
611 if (dp != &nodev_ops && dp != &mod_nodev_ops) {
612 cmn_err(CE_WARN,
613 "mod_installdrv: driver already installed %s", modname);
614 err = EALREADY;
615 goto unlock;
616 }
617
618 devopsp[major] = ops; /* setup devopsp */
619
620 if ((str = STREAMSTAB(major)) != NULL) { /* streams driver */
621 flag = CBFLAG(major);
622 if ((err = devflg_to_qflag(str, flag, &qflag, &sqtype)) != 0)
623 goto unlock;
624 cdp = &devimpl[major];
625 ASSERT(cdp->d_str == NULL);
626 cdp->d_str = str;
627 cdp->d_qflag = qflag | QISDRV;
628 cdp->d_sqtype = sqtype;
629 }
630
631 if (ops->devo_bus_ops == NULL)
632 dnp->dn_flags |= DN_LEAF_DRIVER;
633
634 unlock:
635 UNLOCK_DEV_OPS(&dnp->dn_lock);
636 done:
637 return (err);
638 }
639
640 static int
mod_removedrv(struct modldrv * modl,struct modlinkage * modlp)641 mod_removedrv(struct modldrv *modl, struct modlinkage *modlp)
642 {
643 struct modctl *mcp;
644 struct dev_ops *ops;
645 struct devnames *dnp;
646 struct dev_ops *dp;
647 major_t major;
648 char *modname;
649 extern kthread_id_t mod_aul_thread;
650 struct streamtab *str;
651 cdevsw_impl_t *cdp;
652 int err = 0;
653
654 /* Don't auto unload modules on if moddebug flag is set */
655 if ((moddebug & MODDEBUG_NOAUL_DRV) && (mod_aul_thread == curthread)) {
656 err = EBUSY;
657 goto done;
658 }
659
660 /* Verify modname has a driver major */
661 mcp = mod_getctl(modlp);
662 ASSERT(mcp != NULL);
663 modname = mcp->mod_modname;
664
665 if ((major = ddi_name_to_major(modname)) == -1) {
666 cmn_err(CE_WARN, uninstall_err, modname);
667 err = EINVAL;
668 goto done;
669 }
670
671 ops = modl->drv_dev_ops;
672 dnp = &(devnamesp[major]);
673 LOCK_DEV_OPS(&(dnp->dn_lock));
674
675 dp = devopsp[major];
676
677 if (dp != ops) {
678 cmn_err(CE_NOTE, "mod_removedrv: mismatched driver for %s",
679 modname);
680 err = EBUSY;
681 goto unlock;
682 }
683
684 /*
685 * A driver is not unloadable if its dev_ops are held
686 */
687 if (!DRV_UNLOADABLE(dp)) {
688 mod_dprintf(DRV_DBG, "Cannot unload device driver <%s>,"
689 " refcnt %d\n", modname, dp->devo_refcnt);
690 err = EBUSY;
691 goto unlock;
692 }
693
694 /*
695 * OK to unload.
696 */
697 if ((str = STREAMSTAB(major)) != NULL) { /* streams driver */
698 cdp = &devimpl[major];
699 ASSERT(cdp->d_str == str);
700 cdp->d_str = NULL;
701
702 /* check for reference to per-dev syncq */
703 if (cdp->d_dmp != NULL) {
704 rele_dm(cdp->d_dmp);
705 cdp->d_dmp = NULL;
706 }
707 }
708
709 devopsp[major] = &mod_nodev_ops;
710 dnp->dn_flags &= ~(DN_DRIVER_HELD|DN_NO_AUTODETACH);
711
712 unlock:
713 UNLOCK_DEV_OPS(&(dnp->dn_lock));
714 done:
715 return (err);
716 }
717
718 /*
719 * System call subroutines
720 */
721
722 /*
723 * Compute system call number for given sysent and sysent table
724 */
725 static int
mod_infosysnum(struct modlinkage * modlp,struct sysent table[])726 mod_infosysnum(struct modlinkage *modlp, struct sysent table[])
727 {
728 struct sysent *sysp;
729
730 if ((sysp = mod_getsysent(modlp, table)) == NULL)
731 return (-1);
732 return ((int)(sysp - table));
733 }
734
735 /*
736 * Put a loadable system call entry into a sysent table.
737 */
738 static int
mod_installsys_sysent(struct modlsys * modl,struct modlinkage * modlp,struct sysent table[])739 mod_installsys_sysent(
740 struct modlsys *modl,
741 struct modlinkage *modlp,
742 struct sysent table[])
743 {
744 struct sysent *sysp;
745 struct sysent *mp;
746
747 #ifdef DEBUG
748 /*
749 * Before we even play with the sysent table, sanity check the
750 * incoming flags to make sure the entry is valid
751 */
752 switch (modl->sys_sysent->sy_flags & SE_RVAL_MASK) {
753 case SE_32RVAL1:
754 /* only r_val1 returned */
755 case SE_32RVAL1 | SE_32RVAL2:
756 /* r_val1 and r_val2 returned */
757 case SE_64RVAL:
758 /* 64-bit rval returned */
759 break;
760 default:
761 cmn_err(CE_WARN, "loadable syscall: %p: bad rval flags %x",
762 (void *)modl, modl->sys_sysent->sy_flags);
763 return (ENOSYS);
764 }
765 #endif
766 if ((sysp = mod_getsysent(modlp, table)) == NULL)
767 return (ENOSPC);
768
769 /*
770 * We should only block here until the reader in syscall gives
771 * up the lock. Multiple writers are prevented in the mod layer.
772 */
773 rw_enter(sysp->sy_lock, RW_WRITER);
774 mp = modl->sys_sysent;
775 sysp->sy_narg = mp->sy_narg;
776 sysp->sy_call = mp->sy_call;
777
778 /*
779 * clear the old call method flag, and get the new one from the module.
780 */
781 sysp->sy_flags &= ~SE_ARGC;
782 sysp->sy_flags |= SE_LOADED |
783 (mp->sy_flags & (SE_ARGC | SE_NOUNLOAD | SE_RVAL_MASK));
784
785 /*
786 * If the syscall doesn't need or want unloading, it can avoid
787 * the locking overhead on each entry. Convert the sysent to a
788 * normal non-loadable entry in that case.
789 */
790 if (mp->sy_flags & SE_NOUNLOAD) {
791 if (mp->sy_flags & SE_ARGC) {
792 sysp->sy_callc = (int64_t (*)())mp->sy_call;
793 } else {
794 sysp->sy_callc = syscall_ap;
795 }
796 sysp->sy_flags &= ~SE_LOADABLE;
797 }
798 rw_exit(sysp->sy_lock);
799 return (0);
800 }
801
802 /*
803 * Remove a loadable system call entry from a sysent table.
804 */
805 static int
mod_removesys_sysent(struct modlsys * modl,struct modlinkage * modlp,struct sysent table[])806 mod_removesys_sysent(
807 struct modlsys *modl,
808 struct modlinkage *modlp,
809 struct sysent table[])
810 {
811 struct sysent *sysp;
812
813 if ((sysp = mod_getsysent(modlp, table)) == NULL ||
814 (sysp->sy_flags & (SE_LOADABLE | SE_NOUNLOAD)) == 0 ||
815 sysp->sy_call != modl->sys_sysent->sy_call) {
816
817 struct modctl *mcp = mod_getctl(modlp);
818 char *modname = mcp->mod_modname;
819
820 cmn_err(CE_WARN, uninstall_err, modname);
821 return (EINVAL);
822 }
823
824 /* If we can't get the write lock, we can't unlink from the system */
825
826 if (!(moddebug & MODDEBUG_NOAUL_SYS) &&
827 rw_tryenter(sysp->sy_lock, RW_WRITER)) {
828 /*
829 * Check the flags to be sure the syscall is still
830 * (un)loadable.
831 * If SE_NOUNLOAD is set, SE_LOADABLE will not be.
832 */
833 if ((sysp->sy_flags & (SE_LOADED | SE_LOADABLE)) ==
834 (SE_LOADED | SE_LOADABLE)) {
835 sysp->sy_flags &= ~SE_LOADED;
836 sysp->sy_callc = loadable_syscall;
837 sysp->sy_call = (int (*)())nosys;
838 rw_exit(sysp->sy_lock);
839 return (0);
840 }
841 rw_exit(sysp->sy_lock);
842 }
843 return (EBUSY);
844 }
845
846 /*
847 * System call status info
848 */
849 /*ARGSUSED*/
850 static int
mod_infosys(struct modlsys * modl,struct modlinkage * modlp,int * p0)851 mod_infosys(struct modlsys *modl, struct modlinkage *modlp, int *p0)
852 {
853 *p0 = mod_infosysnum(modlp, sysent);
854 return (0);
855 }
856
857 /*
858 * Link a system call into the system by setting the proper sysent entry.
859 * Called from the module's _init routine.
860 */
861 static int
mod_installsys(struct modlsys * modl,struct modlinkage * modlp)862 mod_installsys(struct modlsys *modl, struct modlinkage *modlp)
863 {
864 return (mod_installsys_sysent(modl, modlp, sysent));
865 }
866
867 /*
868 * Unlink a system call from the system.
869 * Called from a modules _fini routine.
870 */
871 static int
mod_removesys(struct modlsys * modl,struct modlinkage * modlp)872 mod_removesys(struct modlsys *modl, struct modlinkage *modlp)
873 {
874 return (mod_removesys_sysent(modl, modlp, sysent));
875 }
876
877 #ifdef _SYSCALL32_IMPL
878
879 /*
880 * 32-bit system call status info
881 */
882 /*ARGSUSED*/
883 static int
mod_infosys32(struct modlsys * modl,struct modlinkage * modlp,int * p0)884 mod_infosys32(struct modlsys *modl, struct modlinkage *modlp, int *p0)
885 {
886 *p0 = mod_infosysnum(modlp, sysent32);
887 return (0);
888 }
889
890 /*
891 * Link the 32-bit syscall into the system by setting the proper sysent entry.
892 * Also called from the module's _init routine.
893 */
894 static int
mod_installsys32(struct modlsys * modl,struct modlinkage * modlp)895 mod_installsys32(struct modlsys *modl, struct modlinkage *modlp)
896 {
897 return (mod_installsys_sysent(modl, modlp, sysent32));
898 }
899
900 /*
901 * Unlink the 32-bit flavor of a system call from the system.
902 * Also called from a module's _fini routine.
903 */
904 static int
mod_removesys32(struct modlsys * modl,struct modlinkage * modlp)905 mod_removesys32(struct modlsys *modl, struct modlinkage *modlp)
906 {
907 return (mod_removesys_sysent(modl, modlp, sysent32));
908 }
909
910 #endif /* _SYSCALL32_IMPL */
911
912 /*
913 * Filesystem status info
914 */
915 /*ARGSUSED*/
916 static int
mod_infofs(struct modlfs * modl,struct modlinkage * modlp,int * p0)917 mod_infofs(struct modlfs *modl, struct modlinkage *modlp, int *p0)
918 {
919 struct vfssw *vswp;
920
921 RLOCK_VFSSW();
922 if ((vswp = vfs_getvfsswbyname(modl->fs_vfsdef->name)) == NULL)
923 *p0 = -1;
924 else {
925 *p0 = vswp - vfssw;
926 vfs_unrefvfssw(vswp);
927 }
928 RUNLOCK_VFSSW();
929 return (0);
930 }
931
932 /*
933 * Install a filesystem.
934 */
935 /*ARGSUSED1*/
936 static int
mod_installfs(struct modlfs * modl,struct modlinkage * modlp)937 mod_installfs(struct modlfs *modl, struct modlinkage *modlp)
938 {
939 struct vfssw *vswp;
940 struct modctl *mcp;
941 char *fsname;
942 char ksname[KSTAT_STRLEN + 1];
943 int fstype; /* index into vfssw[] and vsanchor_fstype[] */
944 int allocated;
945 int err;
946 int vsw_stats_enabled;
947 /* Not for public consumption so these aren't in a header file */
948 extern int vopstats_enabled;
949 extern vopstats_t **vopstats_fstype;
950 extern kstat_t *new_vskstat(char *, vopstats_t *);
951 extern void initialize_vopstats(vopstats_t *);
952
953 if (modl->fs_vfsdef->def_version == VFSDEF_VERSION) {
954 /* Version matched */
955 fsname = modl->fs_vfsdef->name;
956 } else {
957 if ((modl->fs_vfsdef->def_version > 0) &&
958 (modl->fs_vfsdef->def_version < VFSDEF_VERSION)) {
959 /* Older VFSDEF_VERSION */
960 fsname = modl->fs_vfsdef->name;
961 } else if ((mcp = mod_getctl(modlp)) != NULL) {
962 /* Pre-VFSDEF_VERSION */
963 fsname = mcp->mod_modname;
964 } else {
965 /* If all else fails... */
966 fsname = "<unknown file system type>";
967 }
968
969 cmn_err(CE_WARN, "file system '%s' version mismatch", fsname);
970 return (ENXIO);
971 }
972
973 allocated = 0;
974
975 WLOCK_VFSSW();
976 if ((vswp = vfs_getvfsswbyname(fsname)) == NULL) {
977 if ((vswp = allocate_vfssw(fsname)) == NULL) {
978 WUNLOCK_VFSSW();
979 /*
980 * See 1095689. If this message appears, then
981 * we either need to make the vfssw table bigger
982 * statically, or make it grow dynamically.
983 */
984 cmn_err(CE_WARN, "no room for '%s' in vfssw!", fsname);
985 return (ENXIO);
986 }
987 allocated = 1;
988 }
989 ASSERT(vswp != NULL);
990
991 fstype = vswp - vfssw; /* Pointer arithmetic to get the fstype */
992
993 /* Turn on everything by default *except* VSW_STATS */
994 vswp->vsw_flag = modl->fs_vfsdef->flags & ~(VSW_STATS);
995
996 if (modl->fs_vfsdef->flags & VSW_HASPROTO) {
997 vfs_mergeopttbl(&vfs_mntopts, modl->fs_vfsdef->optproto,
998 &vswp->vsw_optproto);
999 } else {
1000 vfs_copyopttbl(&vfs_mntopts, &vswp->vsw_optproto);
1001 }
1002
1003 if (modl->fs_vfsdef->flags & VSW_CANRWRO) {
1004 /*
1005 * This obviously implies VSW_CANREMOUNT.
1006 */
1007 vswp->vsw_flag |= VSW_CANREMOUNT;
1008 }
1009
1010 /*
1011 * If stats are enabled system wide and for this fstype, then
1012 * set the VSW_STATS flag in the proper vfssw[] table entry.
1013 */
1014 if (vopstats_enabled && modl->fs_vfsdef->flags & VSW_STATS) {
1015 vswp->vsw_flag |= VSW_STATS;
1016 }
1017
1018 if (modl->fs_vfsdef->init == NULL)
1019 err = EFAULT;
1020 else
1021 err = (*(modl->fs_vfsdef->init))(fstype, fsname);
1022
1023 if (err != 0) {
1024 if (allocated) {
1025 kmem_free(vswp->vsw_name, strlen(vswp->vsw_name)+1);
1026 vswp->vsw_name = "";
1027 }
1028 vswp->vsw_flag = 0;
1029 vswp->vsw_init = NULL;
1030 }
1031
1032 /* We don't want to hold the vfssw[] write lock over a kmem_alloc() */
1033 vsw_stats_enabled = vswp->vsw_flag & VSW_STATS;
1034
1035 vfs_unrefvfssw(vswp);
1036 WUNLOCK_VFSSW();
1037
1038 /* If everything is on, set up the per-fstype vopstats */
1039 if (vsw_stats_enabled && vopstats_enabled &&
1040 vopstats_fstype && vopstats_fstype[fstype] == NULL) {
1041 (void) strlcpy(ksname, VOPSTATS_STR, sizeof (ksname));
1042 (void) strlcat(ksname, vfssw[fstype].vsw_name, sizeof (ksname));
1043 vopstats_fstype[fstype] =
1044 kmem_alloc(sizeof (vopstats_t), KM_SLEEP);
1045 initialize_vopstats(vopstats_fstype[fstype]);
1046 (void) new_vskstat(ksname, vopstats_fstype[fstype]);
1047 }
1048 return (err);
1049 }
1050
1051 /*
1052 * Remove a filesystem
1053 */
1054 static int
mod_removefs(struct modlfs * modl,struct modlinkage * modlp)1055 mod_removefs(struct modlfs *modl, struct modlinkage *modlp)
1056 {
1057 struct vfssw *vswp;
1058 struct modctl *mcp;
1059 char *modname;
1060
1061 if (moddebug & MODDEBUG_NOAUL_FS)
1062 return (EBUSY);
1063
1064 WLOCK_VFSSW();
1065 if ((vswp = vfs_getvfsswbyname(modl->fs_vfsdef->name)) == NULL) {
1066 mcp = mod_getctl(modlp);
1067 ASSERT(mcp != NULL);
1068 modname = mcp->mod_modname;
1069 WUNLOCK_VFSSW();
1070 cmn_err(CE_WARN, uninstall_err, modname);
1071 return (EINVAL);
1072 }
1073 if (vswp->vsw_count != 1) {
1074 vfs_unrefvfssw(vswp);
1075 WUNLOCK_VFSSW();
1076 return (EBUSY);
1077 }
1078
1079 /*
1080 * A mounted filesystem could still have vsw_count = 0
1081 * so we must check whether anyone is actually using our ops
1082 */
1083 if (vfs_opsinuse(&vswp->vsw_vfsops)) {
1084 vfs_unrefvfssw(vswp);
1085 WUNLOCK_VFSSW();
1086 return (EBUSY);
1087 }
1088
1089 vfs_freeopttbl(&vswp->vsw_optproto);
1090 vswp->vsw_optproto.mo_count = 0;
1091
1092 vswp->vsw_flag = 0;
1093 vswp->vsw_init = NULL;
1094 vfs_unrefvfssw(vswp);
1095 WUNLOCK_VFSSW();
1096 return (0);
1097 }
1098
1099 /*
1100 * Get status of a streams module.
1101 */
1102 /*ARGSUSED*/
1103 static int
mod_infostrmod(struct modlstrmod * modl,struct modlinkage * modlp,int * p0)1104 mod_infostrmod(struct modlstrmod *modl, struct modlinkage *modlp, int *p0)
1105 {
1106 *p0 = -1; /* no useful info */
1107 return (0);
1108 }
1109
1110
1111 /*
1112 * Install a streams module.
1113 */
1114 /*ARGSUSED*/
1115 static int
mod_installstrmod(struct modlstrmod * modl,struct modlinkage * modlp)1116 mod_installstrmod(struct modlstrmod *modl, struct modlinkage *modlp)
1117 {
1118 struct fmodsw *fp = modl->strmod_fmodsw;
1119
1120 if (!(fp->f_flag & D_MP)) {
1121 cmn_err(CE_WARN, "mod_install: MT-unsafe strmod '%s' rejected",
1122 fp->f_name);
1123 return (ENXIO);
1124 }
1125
1126 return (fmodsw_register(fp->f_name, fp->f_str, fp->f_flag));
1127 }
1128
1129 /*
1130 * Remove a streams module.
1131 */
1132 /*ARGSUSED*/
1133 static int
mod_removestrmod(struct modlstrmod * modl,struct modlinkage * modlp)1134 mod_removestrmod(struct modlstrmod *modl, struct modlinkage *modlp)
1135 {
1136 if (moddebug & MODDEBUG_NOAUL_STR)
1137 return (EBUSY);
1138
1139 return (fmodsw_unregister(modl->strmod_fmodsw->f_name));
1140 }
1141
1142 /*
1143 * Get status of a socket module.
1144 */
1145 /*ARGSUSED*/
1146 static int
mod_infosockmod(struct modlsockmod * modl,struct modlinkage * modlp,int * p0)1147 mod_infosockmod(struct modlsockmod *modl, struct modlinkage *modlp, int *p0)
1148 {
1149 *p0 = -1; /* no useful info */
1150 return (0);
1151 }
1152
1153 /*
1154 * Install a socket module.
1155 */
1156 /*ARGSUSED*/
1157 static int
mod_installsockmod(struct modlsockmod * modl,struct modlinkage * modlp)1158 mod_installsockmod(struct modlsockmod *modl, struct modlinkage *modlp)
1159 {
1160 struct modctl *mcp;
1161 char *mod_name;
1162
1163 mcp = mod_getctl(modlp);
1164 ASSERT(mcp != NULL);
1165 mod_name = mcp->mod_modname;
1166 if (strcmp(mod_name, modl->sockmod_reg_info->smod_name) != 0) {
1167 #ifdef DEBUG
1168 cmn_err(CE_CONT, "mod_installsockmod: different names"
1169 " %s != %s \n", mod_name,
1170 modl->sockmod_reg_info->smod_name);
1171 #endif
1172 return (EINVAL);
1173 }
1174
1175 /*
1176 * Register module.
1177 */
1178 return (smod_register(modl->sockmod_reg_info));
1179 }
1180
1181 /*
1182 * Remove a socket module.
1183 */
1184 /*ARGSUSED*/
1185 static int
mod_removesockmod(struct modlsockmod * modl,struct modlinkage * modlp)1186 mod_removesockmod(struct modlsockmod *modl, struct modlinkage *modlp)
1187 {
1188 /*
1189 * unregister from the global socket creation table
1190 * check the refcnt in the lookup table
1191 */
1192 return (smod_unregister(modl->sockmod_reg_info->smod_name));
1193 }
1194
1195 /*
1196 * Get status of a scheduling class module.
1197 */
1198 /*ARGSUSED1*/
1199 static int
mod_infosched(struct modlsched * modl,struct modlinkage * modlp,int * p0)1200 mod_infosched(struct modlsched *modl, struct modlinkage *modlp, int *p0)
1201 {
1202 int status;
1203 auto id_t cid;
1204
1205 status = getcidbyname(modl->sched_class->cl_name, &cid);
1206
1207 if (status != 0)
1208 *p0 = -1;
1209 else
1210 *p0 = cid;
1211
1212 return (0);
1213 }
1214
1215 /*
1216 * Install a scheduling class module.
1217 */
1218 /*ARGSUSED1*/
1219 static int
mod_installsched(struct modlsched * modl,struct modlinkage * modlp)1220 mod_installsched(struct modlsched *modl, struct modlinkage *modlp)
1221 {
1222 sclass_t *clp;
1223 int status;
1224 id_t cid;
1225
1226 /*
1227 * See if module is already installed.
1228 */
1229 mutex_enter(&class_lock);
1230 status = alloc_cid(modl->sched_class->cl_name, &cid);
1231 mutex_exit(&class_lock);
1232 ASSERT(status == 0);
1233 clp = &sclass[cid];
1234 rw_enter(clp->cl_lock, RW_WRITER);
1235 if (SCHED_INSTALLED(clp)) {
1236 printf("scheduling class %s is already installed\n",
1237 modl->sched_class->cl_name);
1238 rw_exit(clp->cl_lock);
1239 return (EBUSY); /* it's already there */
1240 }
1241
1242 clp->cl_init = modl->sched_class->cl_init;
1243 clp->cl_funcs = modl->sched_class->cl_funcs;
1244 modl->sched_class = clp;
1245 disp_add(clp);
1246 loaded_classes++; /* for priocntl system call */
1247 rw_exit(clp->cl_lock);
1248 return (0);
1249 }
1250
1251 /*
1252 * Remove a scheduling class module.
1253 *
1254 * we only null out the init func and the class functions because
1255 * once a class has been loaded it has that slot in the class
1256 * array until the next reboot. We don't decrement loaded_classes
1257 * because this keeps count of the number of classes that have
1258 * been loaded for this session. It will have to be this way until
1259 * we implement the class array as a linked list and do true
1260 * dynamic allocation.
1261 */
1262 static int
mod_removesched(struct modlsched * modl,struct modlinkage * modlp)1263 mod_removesched(struct modlsched *modl, struct modlinkage *modlp)
1264 {
1265 int status;
1266 sclass_t *clp;
1267 struct modctl *mcp;
1268 char *modname;
1269 id_t cid;
1270
1271 status = getcidbyname(modl->sched_class->cl_name, &cid);
1272 if (status != 0) {
1273 mcp = mod_getctl(modlp);
1274 ASSERT(mcp != NULL);
1275 modname = mcp->mod_modname;
1276 cmn_err(CE_WARN, uninstall_err, modname);
1277 return (EINVAL);
1278 }
1279 clp = &sclass[cid];
1280 if (moddebug & MODDEBUG_NOAUL_SCHED ||
1281 !rw_tryenter(clp->cl_lock, RW_WRITER))
1282 return (EBUSY);
1283
1284 clp->cl_init = NULL;
1285 clp->cl_funcs = NULL;
1286 rw_exit(clp->cl_lock);
1287 return (0);
1288 }
1289
1290 /*
1291 * Get status of an exec module.
1292 */
1293 /*ARGSUSED1*/
1294 static int
mod_infoexec(struct modlexec * modl,struct modlinkage * modlp,int * p0)1295 mod_infoexec(struct modlexec *modl, struct modlinkage *modlp, int *p0)
1296 {
1297 struct execsw *eswp;
1298
1299 if ((eswp = findexecsw(modl->exec_execsw->exec_magic)) == NULL)
1300 *p0 = -1;
1301 else
1302 *p0 = eswp - execsw;
1303
1304 return (0);
1305 }
1306
1307 /*
1308 * Install an exec module.
1309 */
1310 static int
mod_installexec(struct modlexec * modl,struct modlinkage * modlp)1311 mod_installexec(struct modlexec *modl, struct modlinkage *modlp)
1312 {
1313 struct execsw *eswp;
1314 struct modctl *mcp;
1315 char *modname;
1316 char *magic;
1317 size_t magic_size;
1318
1319 /*
1320 * See if execsw entry is already allocated. Can't use findexectype()
1321 * because we may get a recursive call to here.
1322 */
1323
1324 if ((eswp = findexecsw(modl->exec_execsw->exec_magic)) == NULL) {
1325 mcp = mod_getctl(modlp);
1326 ASSERT(mcp != NULL);
1327 modname = mcp->mod_modname;
1328 magic = modl->exec_execsw->exec_magic;
1329 magic_size = modl->exec_execsw->exec_maglen;
1330 if ((eswp = allocate_execsw(modname, magic, magic_size)) ==
1331 NULL) {
1332 printf("no unused entries in 'execsw'\n");
1333 return (ENOSPC);
1334 }
1335 }
1336 if (eswp->exec_func != NULL) {
1337 printf("exec type %x is already installed\n",
1338 *eswp->exec_magic);
1339 return (EBUSY); /* it's already there! */
1340 }
1341
1342 rw_enter(eswp->exec_lock, RW_WRITER);
1343 eswp->exec_func = modl->exec_execsw->exec_func;
1344 eswp->exec_core = modl->exec_execsw->exec_core;
1345 rw_exit(eswp->exec_lock);
1346
1347 return (0);
1348 }
1349
1350 /*
1351 * Remove an exec module.
1352 */
1353 static int
mod_removeexec(struct modlexec * modl,struct modlinkage * modlp)1354 mod_removeexec(struct modlexec *modl, struct modlinkage *modlp)
1355 {
1356 struct execsw *eswp;
1357 struct modctl *mcp;
1358 char *modname;
1359
1360 eswp = findexecsw(modl->exec_execsw->exec_magic);
1361 if (eswp == NULL) {
1362 mcp = mod_getctl(modlp);
1363 ASSERT(mcp != NULL);
1364 modname = mcp->mod_modname;
1365 cmn_err(CE_WARN, uninstall_err, modname);
1366 return (EINVAL);
1367 }
1368 if (moddebug & MODDEBUG_NOAUL_EXEC ||
1369 !rw_tryenter(eswp->exec_lock, RW_WRITER))
1370 return (EBUSY);
1371 eswp->exec_func = NULL;
1372 eswp->exec_core = NULL;
1373 rw_exit(eswp->exec_lock);
1374 return (0);
1375 }
1376
1377 /*
1378 * Find a free sysent entry or check if the specified one is free.
1379 */
1380 static struct sysent *
mod_getsysent(struct modlinkage * modlp,struct sysent * se)1381 mod_getsysent(struct modlinkage *modlp, struct sysent *se)
1382 {
1383 int sysnum;
1384 struct modctl *mcp;
1385 char *mod_name;
1386
1387 if ((mcp = mod_getctl(modlp)) == NULL) {
1388 /*
1389 * This happens when we're looking up the module
1390 * pointer as part of a stub installation. So
1391 * there's no need to whine at this point.
1392 */
1393 return (NULL);
1394 }
1395
1396 mod_name = mcp->mod_modname;
1397
1398 if ((sysnum = mod_getsysnum(mod_name)) == -1) {
1399 cmn_err(CE_WARN, "system call missing from bind file");
1400 return (NULL);
1401 }
1402
1403 if (sysnum > 0 && sysnum < NSYSCALL &&
1404 (se[sysnum].sy_flags & (SE_LOADABLE | SE_NOUNLOAD)))
1405 return (se + sysnum);
1406
1407 cmn_err(CE_WARN, "system call entry %d is already in use", sysnum);
1408 return (NULL);
1409 }
1410
1411 /*
1412 * IP Policy Modules.
1413 */
1414 /*ARGSUSED*/
1415 static int
mod_infoipp(struct modlipp * modl,struct modlinkage * modlp,int * p0)1416 mod_infoipp(struct modlipp *modl, struct modlinkage *modlp, int *p0)
1417 {
1418 struct modctl *mcp = mod_getctl(modlp);
1419 ipp_mod_id_t mid;
1420
1421 if (mcp == NULL) {
1422 *p0 = -1;
1423 return (0); /* module is not yet installed */
1424 }
1425
1426 mid = ipp_mod_lookup(mcp->mod_modname);
1427
1428 *p0 = mid;
1429 return (0);
1430 }
1431
1432 static int
mod_installipp(struct modlipp * modl,struct modlinkage * modlp)1433 mod_installipp(struct modlipp *modl, struct modlinkage *modlp)
1434 {
1435 struct modctl *mcp = mod_getctl(modlp);
1436
1437 ASSERT(mcp != NULL);
1438 return (ipp_mod_register(mcp->mod_modname, modl->ipp_ops));
1439 }
1440
1441 /*ARGSUSED*/
1442 static int
mod_removeipp(struct modlipp * modl,struct modlinkage * modlp)1443 mod_removeipp(struct modlipp *modl, struct modlinkage *modlp)
1444 {
1445 struct modctl *mcp = mod_getctl(modlp);
1446 extern kthread_id_t mod_aul_thread;
1447 ipp_mod_id_t mid;
1448
1449 ASSERT(mcp != NULL);
1450
1451 if ((moddebug & MODDEBUG_NOAUL_IPP) && (mod_aul_thread == curthread))
1452 return (EBUSY);
1453
1454 mid = ipp_mod_lookup(mcp->mod_modname);
1455 ASSERT(mid != IPP_MOD_INVAL);
1456
1457 return (ipp_mod_unregister(mid));
1458 }
1459
1460 /*
1461 * Manage kiconv modules.
1462 */
1463 /*ARGSUSED*/
1464 static int
mod_installkiconv(struct modlkiconv * modl,struct modlinkage * modlp)1465 mod_installkiconv(struct modlkiconv *modl, struct modlinkage *modlp)
1466 {
1467 return (kiconv_register_module(modl->kiconv_moddef));
1468 }
1469
1470 /*ARGSUSED*/
1471 static int
mod_removekiconv(struct modlkiconv * modl,struct modlinkage * modlp)1472 mod_removekiconv(struct modlkiconv *modl, struct modlinkage *modlp)
1473 {
1474 return (kiconv_unregister_module(modl->kiconv_moddef));
1475 }
1476