Print this page
7127 remove -Wno-missing-braces from Makefile.uts
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/uts/common/io/sad.c
+++ new/usr/src/uts/common/io/sad.c
1 1 /*
2 2 * CDDL HEADER START
3 3 *
4 4 * The contents of this file are subject to the terms of the
5 5 * Common Development and Distribution License (the "License").
6 6 * You may not use this file except in compliance with the License.
7 7 *
8 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 9 * or http://www.opensolaris.org/os/licensing.
10 10 * See the License for the specific language governing permissions
11 11 * and limitations under the License.
12 12 *
13 13 * When distributing Covered Code, include this CDDL HEADER in each
14 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 15 * If applicable, add the following below this CDDL HEADER, with the
16 16 * fields enclosed by brackets "[]" replaced with your own identifying
17 17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 18 *
19 19 * CDDL HEADER END
20 20 */
21 21 /*
22 22 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
23 23 * Use is subject to license terms.
24 24 */
25 25
26 26
27 27 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
28 28 /* All Rights Reserved */
29 29
30 30
31 31 /*
32 32 * STREAMS Administrative Driver
33 33 *
34 34 * Currently only handles autopush and module name verification.
35 35 */
36 36
37 37 #include <sys/types.h>
38 38 #include <sys/param.h>
39 39 #include <sys/errno.h>
40 40 #include <sys/stream.h>
41 41 #include <sys/stropts.h>
42 42 #include <sys/strsubr.h>
43 43 #include <sys/strsun.h>
44 44 #include <sys/conf.h>
45 45 #include <sys/sad.h>
46 46 #include <sys/cred.h>
47 47 #include <sys/debug.h>
48 48 #include <sys/ddi.h>
49 49 #include <sys/sunddi.h>
50 50 #include <sys/stat.h>
51 51 #include <sys/cmn_err.h>
52 52 #include <sys/systm.h>
53 53 #include <sys/modctl.h>
54 54 #include <sys/sysmacros.h>
55 55 #include <sys/zone.h>
56 56 #include <sys/policy.h>
57 57
58 58 static int sadopen(queue_t *, dev_t *, int, int, cred_t *);
59 59 static int sadclose(queue_t *, int, cred_t *);
60 60 static int sadwput(queue_t *qp, mblk_t *mp);
61 61
62 62 static int sad_info(dev_info_t *, ddi_info_cmd_t, void *, void **);
63 63 static int sad_attach(dev_info_t *, ddi_attach_cmd_t);
64 64
65 65 static void apush_ioctl(), apush_iocdata();
66 66 static void vml_ioctl(), vml_iocdata();
67 67 static int valid_major(major_t);
68 68
69 69 static dev_info_t *sad_dip; /* private copy of devinfo pointer */
70 70
71 71 static struct module_info sad_minfo = {
72 72 0x7361, "sad", 0, INFPSZ, 0, 0
73 73 };
74 74
75 75 static struct qinit sad_rinit = {
76 76 NULL, NULL, sadopen, sadclose, NULL, &sad_minfo, NULL
77 77 };
78 78
79 79 static struct qinit sad_winit = {
80 80 sadwput, NULL, NULL, NULL, NULL, &sad_minfo, NULL
81 81 };
82 82
83 83 struct streamtab sadinfo = {
84 84 &sad_rinit, &sad_winit, NULL, NULL
85 85 };
86 86
87 87 DDI_DEFINE_STREAM_OPS(sad_ops, nulldev, nulldev, sad_attach,
88 88 nodev, nodev, sad_info,
89 89 D_MP | D_MTPERQ | D_MTOUTPERIM | D_MTOCEXCL, &sadinfo,
90 90 ddi_quiesce_not_supported);
91 91
92 92 /*
↓ open down ↓ |
92 lines elided |
↑ open up ↑ |
93 93 * Module linkage information for the kernel.
94 94 */
95 95
96 96 static struct modldrv modldrv = {
97 97 &mod_driverops, /* Type of module. This one is a pseudo driver */
98 98 "STREAMS Administrative Driver 'sad'",
99 99 &sad_ops, /* driver ops */
100 100 };
101 101
102 102 static struct modlinkage modlinkage = {
103 - MODREV_1, &modldrv, NULL
103 + MODREV_1, { &modldrv, NULL }
104 104 };
105 105
106 106 int
107 107 _init(void)
108 108 {
109 109 return (mod_install(&modlinkage));
110 110 }
111 111
112 112 int
113 113 _fini(void)
114 114 {
115 115 return (mod_remove(&modlinkage));
116 116 }
117 117
118 118 int
119 119 _info(struct modinfo *modinfop)
120 120 {
121 121 return (mod_info(&modlinkage, modinfop));
122 122 }
123 123
124 124 static int
125 125 sad_attach(dev_info_t *devi, ddi_attach_cmd_t cmd)
126 126 {
127 127 int instance = ddi_get_instance(devi);
128 128
129 129 if (cmd != DDI_ATTACH)
130 130 return (DDI_FAILURE);
131 131
132 132 ASSERT(instance == 0);
133 133 if (instance != 0)
134 134 return (DDI_FAILURE);
135 135
136 136 if (ddi_create_minor_node(devi, "user", S_IFCHR,
137 137 0, DDI_PSEUDO, NULL) == DDI_FAILURE) {
138 138 return (DDI_FAILURE);
139 139 }
140 140 if (ddi_create_minor_node(devi, "admin", S_IFCHR,
141 141 1, DDI_PSEUDO, NULL) == DDI_FAILURE) {
142 142 ddi_remove_minor_node(devi, NULL);
143 143 return (DDI_FAILURE);
144 144 }
145 145 sad_dip = devi;
146 146 return (DDI_SUCCESS);
147 147 }
148 148
149 149 /* ARGSUSED */
150 150 static int
151 151 sad_info(dev_info_t *dip, ddi_info_cmd_t infocmd, void *arg, void **result)
152 152 {
153 153 int error;
154 154
155 155 switch (infocmd) {
156 156 case DDI_INFO_DEVT2DEVINFO:
157 157 if (sad_dip == NULL) {
158 158 error = DDI_FAILURE;
159 159 } else {
160 160 *result = sad_dip;
161 161 error = DDI_SUCCESS;
162 162 }
163 163 break;
164 164 case DDI_INFO_DEVT2INSTANCE:
165 165 *result = (void *)0;
166 166 error = DDI_SUCCESS;
167 167 break;
168 168 default:
169 169 error = DDI_FAILURE;
170 170 }
171 171 return (error);
172 172 }
173 173
174 174
175 175 /*
176 176 * sadopen() -
177 177 * Allocate a sad device. Only one
178 178 * open at a time allowed per device.
179 179 */
180 180 /* ARGSUSED */
181 181 static int
182 182 sadopen(
183 183 queue_t *qp, /* pointer to read queue */
184 184 dev_t *devp, /* major/minor device of stream */
185 185 int flag, /* file open flags */
186 186 int sflag, /* stream open flags */
187 187 cred_t *credp) /* user credentials */
188 188 {
189 189 int i;
190 190 netstack_t *ns;
191 191 str_stack_t *ss;
192 192
193 193 if (sflag) /* no longer called from clone driver */
194 194 return (EINVAL);
195 195
196 196 /* Only privileged process can access ADMINDEV */
197 197 if (getminor(*devp) == ADMMIN) {
198 198 int err;
199 199
200 200 err = secpolicy_sadopen(credp);
201 201
202 202 if (err != 0)
203 203 return (err);
204 204 }
205 205
206 206 ns = netstack_find_by_cred(credp);
207 207 ASSERT(ns != NULL);
208 208 ss = ns->netstack_str;
209 209 ASSERT(ss != NULL);
210 210
211 211 /*
212 212 * Both USRMIN and ADMMIN are clone interfaces.
213 213 */
214 214 for (i = 0; i < ss->ss_sadcnt; i++)
215 215 if (ss->ss_saddev[i].sa_qp == NULL)
216 216 break;
217 217 if (i >= ss->ss_sadcnt) { /* no such device */
218 218 netstack_rele(ss->ss_netstack);
219 219 return (ENXIO);
220 220 }
221 221 switch (getminor(*devp)) {
222 222 case USRMIN: /* mere mortal */
223 223 ss->ss_saddev[i].sa_flags = 0;
224 224 break;
225 225
226 226 case ADMMIN: /* privileged user */
227 227 ss->ss_saddev[i].sa_flags = SADPRIV;
228 228 break;
229 229
230 230 default:
231 231 netstack_rele(ss->ss_netstack);
232 232 return (EINVAL);
233 233 }
234 234
235 235 ss->ss_saddev[i].sa_qp = qp;
236 236 ss->ss_saddev[i].sa_ss = ss;
237 237 qp->q_ptr = (caddr_t)&ss->ss_saddev[i];
238 238 WR(qp)->q_ptr = (caddr_t)&ss->ss_saddev[i];
239 239
240 240 /*
241 241 * NOTE: should the ADMMIN or USRMIN minors change
242 242 * then so should the offset of 2 below
243 243 * Both USRMIN and ADMMIN are clone interfaces and
244 244 * therefore their minor numbers (0 and 1) are reserved.
245 245 */
246 246 *devp = makedevice(getemajor(*devp), i + 2);
247 247 qprocson(qp);
248 248 return (0);
249 249 }
250 250
251 251 /*
252 252 * sadclose() -
253 253 * Clean up the data structures.
254 254 */
255 255 /* ARGSUSED */
256 256 static int
257 257 sadclose(
258 258 queue_t *qp, /* pointer to read queue */
259 259 int flag, /* file open flags */
260 260 cred_t *credp) /* user credentials */
261 261 {
262 262 struct saddev *sadp;
263 263
264 264 qprocsoff(qp);
265 265 sadp = (struct saddev *)qp->q_ptr;
266 266 sadp->sa_qp = NULL;
267 267 sadp->sa_addr = NULL;
268 268 netstack_rele(sadp->sa_ss->ss_netstack);
269 269 sadp->sa_ss = NULL;
270 270 qp->q_ptr = NULL;
271 271 WR(qp)->q_ptr = NULL;
272 272 return (0);
273 273 }
274 274
275 275 /*
276 276 * sadwput() -
277 277 * Write side put procedure.
278 278 */
279 279 static int
280 280 sadwput(
281 281 queue_t *qp, /* pointer to write queue */
282 282 mblk_t *mp) /* message pointer */
283 283 {
284 284 struct iocblk *iocp;
285 285
286 286 switch (mp->b_datap->db_type) {
287 287 case M_FLUSH:
288 288 if (*mp->b_rptr & FLUSHR) {
289 289 *mp->b_rptr &= ~FLUSHW;
290 290 qreply(qp, mp);
291 291 } else
292 292 freemsg(mp);
293 293 break;
294 294
295 295 case M_IOCTL:
296 296 iocp = (struct iocblk *)mp->b_rptr;
297 297 switch (SAD_CMD(iocp->ioc_cmd)) {
298 298 case SAD_CMD(SAD_SAP):
299 299 case SAD_CMD(SAD_GAP):
300 300 apush_ioctl(qp, mp);
301 301 break;
302 302
303 303 case SAD_VML:
304 304 vml_ioctl(qp, mp);
305 305 break;
306 306
307 307 default:
308 308 miocnak(qp, mp, 0, EINVAL);
309 309 break;
310 310 }
311 311 break;
312 312
313 313 case M_IOCDATA:
314 314 iocp = (struct iocblk *)mp->b_rptr;
315 315 switch (SAD_CMD(iocp->ioc_cmd)) {
316 316 case SAD_CMD(SAD_SAP):
317 317 case SAD_CMD(SAD_GAP):
318 318 apush_iocdata(qp, mp);
319 319 break;
320 320
321 321 case SAD_VML:
322 322 vml_iocdata(qp, mp);
323 323 break;
324 324
325 325 default:
326 326 cmn_err(CE_WARN,
327 327 "sadwput: invalid ioc_cmd in case M_IOCDATA: %d",
328 328 iocp->ioc_cmd);
329 329 freemsg(mp);
330 330 break;
331 331 }
332 332 break;
333 333
334 334 default:
335 335 freemsg(mp);
336 336 break;
337 337 } /* switch (db_type) */
338 338 return (0);
339 339 }
340 340
341 341 /*
342 342 * apush_ioctl() -
343 343 * Handle the M_IOCTL messages associated with
344 344 * the autopush feature.
345 345 */
346 346 static void
347 347 apush_ioctl(
348 348 queue_t *qp, /* pointer to write queue */
349 349 mblk_t *mp) /* message pointer */
350 350 {
351 351 struct iocblk *iocp;
352 352 struct saddev *sadp;
353 353 uint_t size;
354 354
355 355 iocp = (struct iocblk *)mp->b_rptr;
356 356 if (iocp->ioc_count != TRANSPARENT) {
357 357 miocnak(qp, mp, 0, EINVAL);
358 358 return;
359 359 }
360 360 if (SAD_VER(iocp->ioc_cmd) > AP_VERSION) {
361 361 miocnak(qp, mp, 0, EINVAL);
362 362 return;
363 363 }
364 364
365 365 sadp = (struct saddev *)qp->q_ptr;
366 366 switch (SAD_CMD(iocp->ioc_cmd)) {
367 367 case SAD_CMD(SAD_SAP):
368 368 if (!(sadp->sa_flags & SADPRIV)) {
369 369 miocnak(qp, mp, 0, EPERM);
370 370 break;
371 371 }
372 372 /* FALLTHRU */
373 373
374 374 case SAD_CMD(SAD_GAP):
375 375 sadp->sa_addr = (caddr_t)*(uintptr_t *)mp->b_cont->b_rptr;
376 376 if (SAD_VER(iocp->ioc_cmd) == 1)
377 377 size = STRAPUSH_V1_LEN;
378 378 else
379 379 size = STRAPUSH_V0_LEN;
380 380 mcopyin(mp, (void *)GETSTRUCT, size, NULL);
381 381 qreply(qp, mp);
382 382 break;
383 383
384 384 default:
385 385 ASSERT(0);
386 386 miocnak(qp, mp, 0, EINVAL);
387 387 break;
388 388 } /* switch (ioc_cmd) */
389 389 }
390 390
391 391 /*
392 392 * apush_iocdata() -
393 393 * Handle the M_IOCDATA messages associated with
394 394 * the autopush feature.
395 395 */
396 396 static void
397 397 apush_iocdata(
398 398 queue_t *qp, /* pointer to write queue */
399 399 mblk_t *mp) /* message pointer */
400 400 {
401 401 int i, ret;
402 402 struct copyresp *csp;
403 403 struct strapush *sap = NULL;
404 404 struct autopush *ap, *ap_tmp;
405 405 struct saddev *sadp;
406 406 uint_t size;
407 407 dev_t dev;
408 408 str_stack_t *ss;
409 409
410 410 sadp = (struct saddev *)qp->q_ptr;
411 411 ss = sadp->sa_ss;
412 412
413 413 csp = (struct copyresp *)mp->b_rptr;
414 414 if (csp->cp_rval) { /* if there was an error */
415 415 freemsg(mp);
416 416 return;
417 417 }
418 418 if (mp->b_cont) {
419 419 /*
420 420 * sap needed only if mp->b_cont is set. figure out the
421 421 * size of the expected sap structure and make sure
422 422 * enough data was supplied.
423 423 */
424 424 if (SAD_VER(csp->cp_cmd) == 1)
425 425 size = STRAPUSH_V1_LEN;
426 426 else
427 427 size = STRAPUSH_V0_LEN;
428 428 if (MBLKL(mp->b_cont) < size) {
429 429 miocnak(qp, mp, 0, EINVAL);
430 430 return;
431 431 }
432 432 sap = (struct strapush *)mp->b_cont->b_rptr;
433 433 dev = makedevice(sap->sap_major, sap->sap_minor);
434 434 }
435 435 switch (SAD_CMD(csp->cp_cmd)) {
436 436 case SAD_CMD(SAD_SAP):
437 437
438 438 /* currently we only support one SAD_SAP command */
439 439 if (((long)csp->cp_private) != GETSTRUCT) {
440 440 cmn_err(CE_WARN,
441 441 "apush_iocdata: cp_private bad in SAD_SAP: %p",
442 442 (void *)csp->cp_private);
443 443 miocnak(qp, mp, 0, EINVAL);
444 444 return;
445 445 }
446 446
447 447 switch (sap->sap_cmd) {
448 448 default:
449 449 miocnak(qp, mp, 0, EINVAL);
450 450 return;
451 451 case SAP_ONE:
452 452 case SAP_RANGE:
453 453 case SAP_ALL:
454 454 /* allocate and initialize a new config */
455 455 ap = sad_ap_alloc();
456 456 ap->ap_common = sap->sap_common;
457 457 if (SAD_VER(csp->cp_cmd) > 0)
458 458 ap->ap_anchor = sap->sap_anchor;
459 459 for (i = 0; i < MIN(sap->sap_npush, MAXAPUSH); i++)
460 460 (void) strncpy(ap->ap_list[i],
461 461 sap->sap_list[i], FMNAMESZ);
462 462
463 463 /* sanity check the request */
464 464 if (((ret = sad_ap_verify(ap)) != 0) ||
465 465 ((ret = valid_major(ap->ap_major)) != 0)) {
466 466 sad_ap_rele(ap, ss);
467 467 miocnak(qp, mp, 0, ret);
468 468 return;
469 469 }
470 470
471 471 /* check for overlapping configs */
472 472 mutex_enter(&ss->ss_sad_lock);
473 473 ap_tmp = sad_ap_find(&ap->ap_common, ss);
474 474 if (ap_tmp != NULL) {
475 475 /* already configured */
476 476 mutex_exit(&ss->ss_sad_lock);
477 477 sad_ap_rele(ap_tmp, ss);
478 478 sad_ap_rele(ap, ss);
479 479 miocnak(qp, mp, 0, EEXIST);
480 480 return;
481 481 }
482 482
483 483 /* add the new config to our hash */
484 484 sad_ap_insert(ap, ss);
485 485 mutex_exit(&ss->ss_sad_lock);
486 486 miocack(qp, mp, 0, 0);
487 487 return;
488 488
489 489 case SAP_CLEAR:
490 490 /* sanity check the request */
491 491 if (ret = valid_major(sap->sap_major)) {
492 492 miocnak(qp, mp, 0, ret);
493 493 return;
494 494 }
495 495
496 496 /* search for a matching config */
497 497 if ((ap = sad_ap_find_by_dev(dev, ss)) == NULL) {
498 498 /* no config found */
499 499 miocnak(qp, mp, 0, ENODEV);
500 500 return;
501 501 }
502 502
503 503 /*
504 504 * If we matched a SAP_RANGE config
505 505 * the minor passed in must match the
506 506 * beginning of the range exactly.
507 507 */
508 508 if ((ap->ap_type == SAP_RANGE) &&
509 509 (ap->ap_minor != sap->sap_minor)) {
510 510 sad_ap_rele(ap, ss);
511 511 miocnak(qp, mp, 0, ERANGE);
512 512 return;
513 513 }
514 514
515 515 /*
516 516 * If we matched a SAP_ALL config
517 517 * the minor passed in must be 0.
518 518 */
519 519 if ((ap->ap_type == SAP_ALL) &&
520 520 (sap->sap_minor != 0)) {
521 521 sad_ap_rele(ap, ss);
522 522 miocnak(qp, mp, 0, EINVAL);
523 523 return;
524 524 }
525 525
526 526 /*
527 527 * make sure someone else hasn't already
528 528 * removed this config from the hash.
529 529 */
530 530 mutex_enter(&ss->ss_sad_lock);
531 531 ap_tmp = sad_ap_find(&ap->ap_common, ss);
532 532 if (ap_tmp != ap) {
533 533 mutex_exit(&ss->ss_sad_lock);
534 534 sad_ap_rele(ap_tmp, ss);
535 535 sad_ap_rele(ap, ss);
536 536 miocnak(qp, mp, 0, ENODEV);
537 537 return;
538 538 }
539 539
540 540 /* remove the config from the hash and return */
541 541 sad_ap_remove(ap, ss);
542 542 mutex_exit(&ss->ss_sad_lock);
543 543
544 544 /*
545 545 * Release thrice, once for sad_ap_find_by_dev(),
546 546 * once for sad_ap_find(), and once to free.
547 547 */
548 548 sad_ap_rele(ap, ss);
549 549 sad_ap_rele(ap, ss);
550 550 sad_ap_rele(ap, ss);
551 551 miocack(qp, mp, 0, 0);
552 552 return;
553 553 } /* switch (sap_cmd) */
554 554 /*NOTREACHED*/
555 555
556 556 case SAD_CMD(SAD_GAP):
557 557 switch ((long)csp->cp_private) {
558 558
559 559 case GETSTRUCT:
560 560 /* sanity check the request */
561 561 if (ret = valid_major(sap->sap_major)) {
562 562 miocnak(qp, mp, 0, ret);
563 563 return;
564 564 }
565 565
566 566 /* search for a matching config */
567 567 if ((ap = sad_ap_find_by_dev(dev, ss)) == NULL) {
568 568 /* no config found */
569 569 miocnak(qp, mp, 0, ENODEV);
570 570 return;
571 571 }
572 572
573 573 /* copy out the contents of the config */
574 574 sap->sap_common = ap->ap_common;
575 575 if (SAD_VER(csp->cp_cmd) > 0)
576 576 sap->sap_anchor = ap->ap_anchor;
577 577 for (i = 0; i < ap->ap_npush; i++)
578 578 (void) strcpy(sap->sap_list[i], ap->ap_list[i]);
579 579 for (; i < MAXAPUSH; i++)
580 580 bzero(sap->sap_list[i], FMNAMESZ + 1);
581 581
582 582 /* release our hold on the config */
583 583 sad_ap_rele(ap, ss);
584 584
585 585 /* copyout the results */
586 586 if (SAD_VER(csp->cp_cmd) == 1)
587 587 size = STRAPUSH_V1_LEN;
588 588 else
589 589 size = STRAPUSH_V0_LEN;
590 590
591 591 mcopyout(mp, (void *)GETRESULT, size, sadp->sa_addr,
592 592 NULL);
593 593 qreply(qp, mp);
594 594 return;
595 595 case GETRESULT:
596 596 miocack(qp, mp, 0, 0);
597 597 return;
598 598
599 599 default:
600 600 cmn_err(CE_WARN,
601 601 "apush_iocdata: cp_private bad case SAD_GAP: %p",
602 602 (void *)csp->cp_private);
603 603 freemsg(mp);
604 604 return;
605 605 } /* switch (cp_private) */
606 606 /*NOTREACHED*/
607 607 default: /* can't happen */
608 608 ASSERT(0);
609 609 freemsg(mp);
610 610 return;
611 611 } /* switch (cp_cmd) */
612 612 }
613 613
614 614 /*
615 615 * vml_ioctl() -
616 616 * Handle the M_IOCTL message associated with a request
617 617 * to validate a module list.
618 618 */
619 619 static void
620 620 vml_ioctl(
621 621 queue_t *qp, /* pointer to write queue */
622 622 mblk_t *mp) /* message pointer */
623 623 {
624 624 struct iocblk *iocp;
625 625
626 626 iocp = (struct iocblk *)mp->b_rptr;
627 627 if (iocp->ioc_count != TRANSPARENT) {
628 628 miocnak(qp, mp, 0, EINVAL);
629 629 return;
630 630 }
631 631 ASSERT(SAD_CMD(iocp->ioc_cmd) == SAD_VML);
632 632 mcopyin(mp, (void *)GETSTRUCT,
633 633 SIZEOF_STRUCT(str_list, iocp->ioc_flag), NULL);
634 634 qreply(qp, mp);
635 635 }
636 636
637 637 /*
638 638 * vml_iocdata() -
639 639 * Handle the M_IOCDATA messages associated with
640 640 * a request to validate a module list.
641 641 */
642 642 static void
643 643 vml_iocdata(
644 644 queue_t *qp, /* pointer to write queue */
645 645 mblk_t *mp) /* message pointer */
646 646 {
647 647 long i;
648 648 int nmods;
649 649 struct copyresp *csp;
650 650 struct str_mlist *lp;
651 651 STRUCT_HANDLE(str_list, slp);
652 652 struct saddev *sadp;
653 653
654 654 csp = (struct copyresp *)mp->b_rptr;
655 655 if (csp->cp_rval) { /* if there was an error */
656 656 freemsg(mp);
657 657 return;
658 658 }
659 659
660 660 ASSERT(SAD_CMD(csp->cp_cmd) == SAD_VML);
661 661 sadp = (struct saddev *)qp->q_ptr;
662 662 switch ((long)csp->cp_private) {
663 663 case GETSTRUCT:
664 664 STRUCT_SET_HANDLE(slp, csp->cp_flag,
665 665 (struct str_list *)mp->b_cont->b_rptr);
666 666 nmods = STRUCT_FGET(slp, sl_nmods);
667 667 if (nmods <= 0) {
668 668 miocnak(qp, mp, 0, EINVAL);
669 669 break;
670 670 }
671 671 sadp->sa_addr = (caddr_t)(uintptr_t)nmods;
672 672
673 673 mcopyin(mp, (void *)GETLIST, nmods * sizeof (struct str_mlist),
674 674 STRUCT_FGETP(slp, sl_modlist));
675 675 qreply(qp, mp);
676 676 break;
677 677
678 678 case GETLIST:
679 679 lp = (struct str_mlist *)mp->b_cont->b_rptr;
680 680 for (i = 0; i < (long)sadp->sa_addr; i++, lp++) {
681 681 lp->l_name[FMNAMESZ] = '\0';
682 682 if (fmodsw_find(lp->l_name, FMODSW_LOAD) == NULL) {
683 683 miocack(qp, mp, 0, 1);
684 684 return;
685 685 }
686 686 }
687 687 miocack(qp, mp, 0, 0);
688 688 break;
689 689
690 690 default:
691 691 cmn_err(CE_WARN, "vml_iocdata: invalid cp_private value: %p",
692 692 (void *)csp->cp_private);
693 693 freemsg(mp);
694 694 break;
695 695 } /* switch (cp_private) */
696 696 }
697 697
698 698 /*
699 699 * Validate a major number and also verify if
700 700 * it is a STREAMS device.
701 701 * Return values: 0 if a valid STREAMS dev
702 702 * error code otherwise
703 703 */
704 704 static int
705 705 valid_major(major_t major)
706 706 {
707 707 int ret = 0;
708 708
709 709 if (etoimajor(major) == -1)
710 710 return (EINVAL);
711 711
712 712 /*
713 713 * attempt to load the driver 'major' and verify that
714 714 * it is a STREAMS driver.
715 715 */
716 716 if (ddi_hold_driver(major) == NULL)
717 717 return (EINVAL);
718 718
719 719 if (!STREAMSTAB(major))
720 720 ret = ENOSTR;
721 721
722 722 ddi_rele_driver(major);
723 723
724 724 return (ret);
725 725 }
↓ open down ↓ |
612 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX