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 (c) 2010, Oracle and/or its affiliates. All rights reserved.
23 */
24
25 /*
26 * Data-Link Driver
27 */
28 #include <sys/sysmacros.h>
29 #include <sys/strsubr.h>
30 #include <sys/strsun.h>
31 #include <sys/vlan.h>
32 #include <sys/dld_impl.h>
33 #include <sys/mac_client.h>
34 #include <sys/mac_client_impl.h>
35 #include <sys/mac_client_priv.h>
36
37 typedef void proto_reqfunc_t(dld_str_t *, mblk_t *);
38
39 static proto_reqfunc_t proto_info_req, proto_attach_req, proto_detach_req,
40 proto_bind_req, proto_unbind_req, proto_promiscon_req, proto_promiscoff_req,
41 proto_enabmulti_req, proto_disabmulti_req, proto_physaddr_req,
42 proto_setphysaddr_req, proto_udqos_req, proto_req, proto_capability_req,
556 dsp->ds_mode = DLD_UNITDATA;
557 dsp->ds_dlstate = DL_UNBOUND;
558
559 dls_active_clear(dsp, B_FALSE);
560 mac_perim_exit(mph);
561 dlokack(dsp->ds_wq, mp, DL_UNBIND_REQ);
562 return;
563 failed:
564 dlerrorack(q, mp, DL_UNBIND_REQ, dl_err, 0);
565 }
566
567 /*
568 * DL_PROMISCON_REQ
569 */
570 static void
571 proto_promiscon_req(dld_str_t *dsp, mblk_t *mp)
572 {
573 dl_promiscon_req_t *dlp = (dl_promiscon_req_t *)mp->b_rptr;
574 int err = 0;
575 t_uscalar_t dl_err;
576 uint32_t promisc_saved;
577 queue_t *q = dsp->ds_wq;
578 mac_perim_handle_t mph;
579
580 if (MBLKL(mp) < sizeof (dl_promiscon_req_t)) {
581 dl_err = DL_BADPRIM;
582 goto failed;
583 }
584
585 if (dsp->ds_dlstate == DL_UNATTACHED ||
586 DL_ACK_PENDING(dsp->ds_dlstate)) {
587 dl_err = DL_OUTSTATE;
588 goto failed;
589 }
590
591 promisc_saved = dsp->ds_promisc;
592 switch (dlp->dl_level) {
593 case DL_PROMISC_SAP:
594 dsp->ds_promisc |= DLS_PROMISC_SAP;
595 break;
596
597 case DL_PROMISC_MULTI:
598 dsp->ds_promisc |= DLS_PROMISC_MULTI;
599 break;
600
601 case DL_PROMISC_PHYS:
602 dsp->ds_promisc |= DLS_PROMISC_PHYS;
603 break;
604
605 default:
606 dl_err = DL_NOTSUPPORTED;
607 goto failed;
608 }
609
610 mac_perim_enter_by_mh(dsp->ds_mh, &mph);
611
612 if ((promisc_saved == 0) && (err = dls_active_set(dsp)) != 0) {
613 dsp->ds_promisc = promisc_saved;
614 dl_err = DL_SYSERR;
615 goto failed2;
616 }
617
618 /*
619 * Adjust channel promiscuity.
620 */
621 err = dls_promisc(dsp, promisc_saved);
622
623 if (err != 0) {
624 dl_err = DL_SYSERR;
625 dsp->ds_promisc = promisc_saved;
626 if (promisc_saved == 0)
627 dls_active_clear(dsp, B_FALSE);
628 goto failed2;
629 }
630
631 mac_perim_exit(mph);
632
633 dlokack(q, mp, DL_PROMISCON_REQ);
634 return;
635
636 failed2:
637 mac_perim_exit(mph);
638 failed:
639 dlerrorack(q, mp, DL_PROMISCON_REQ, dl_err, (t_uscalar_t)err);
640 }
641
642 /*
643 * DL_PROMISCOFF_REQ
644 */
645 static void
646 proto_promiscoff_req(dld_str_t *dsp, mblk_t *mp)
647 {
648 dl_promiscoff_req_t *dlp = (dl_promiscoff_req_t *)mp->b_rptr;
649 int err = 0;
650 t_uscalar_t dl_err;
651 uint32_t promisc_saved;
652 queue_t *q = dsp->ds_wq;
653 mac_perim_handle_t mph;
654
655 if (MBLKL(mp) < sizeof (dl_promiscoff_req_t)) {
656 dl_err = DL_BADPRIM;
657 goto failed;
658 }
659
660 if (dsp->ds_dlstate == DL_UNATTACHED ||
661 DL_ACK_PENDING(dsp->ds_dlstate)) {
662 dl_err = DL_OUTSTATE;
663 goto failed;
664 }
665
666 promisc_saved = dsp->ds_promisc;
667 switch (dlp->dl_level) {
668 case DL_PROMISC_SAP:
669 if (!(dsp->ds_promisc & DLS_PROMISC_SAP)) {
670 dl_err = DL_NOTENAB;
671 goto failed;
672 }
673 dsp->ds_promisc &= ~DLS_PROMISC_SAP;
674 break;
675
676 case DL_PROMISC_MULTI:
677 if (!(dsp->ds_promisc & DLS_PROMISC_MULTI)) {
678 dl_err = DL_NOTENAB;
679 goto failed;
680 }
681 dsp->ds_promisc &= ~DLS_PROMISC_MULTI;
682 break;
683
684 case DL_PROMISC_PHYS:
685 if (!(dsp->ds_promisc & DLS_PROMISC_PHYS)) {
686 dl_err = DL_NOTENAB;
687 goto failed;
688 }
689 dsp->ds_promisc &= ~DLS_PROMISC_PHYS;
690 break;
691
692 default:
693 dl_err = DL_NOTSUPPORTED;
694 goto failed;
695 }
696
697 mac_perim_enter_by_mh(dsp->ds_mh, &mph);
698 /*
699 * Adjust channel promiscuity.
700 */
701 err = dls_promisc(dsp, promisc_saved);
702
703 if (err != 0) {
704 mac_perim_exit(mph);
705 dl_err = DL_SYSERR;
706 goto failed;
707 }
708
709 if (dsp->ds_promisc == 0)
710 dls_active_clear(dsp, B_FALSE);
711
712 mac_perim_exit(mph);
713
714 dlokack(q, mp, DL_PROMISCOFF_REQ);
715 return;
716 failed:
717 dlerrorack(q, mp, DL_PROMISCOFF_REQ, dl_err, (t_uscalar_t)err);
718 }
719
720 /*
721 * DL_ENABMULTI_REQ
722 */
723 static void
724 proto_enabmulti_req(dld_str_t *dsp, mblk_t *mp)
725 {
726 dl_enabmulti_req_t *dlp = (dl_enabmulti_req_t *)mp->b_rptr;
727 int err = 0;
728 t_uscalar_t dl_err;
|
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 (c) 2010, Oracle and/or its affiliates. All rights reserved.
23 * Copyright 2011, Nexenta Systems, Inc. All rights reserved.
24 */
25
26 /*
27 * Data-Link Driver
28 */
29 #include <sys/sysmacros.h>
30 #include <sys/strsubr.h>
31 #include <sys/strsun.h>
32 #include <sys/vlan.h>
33 #include <sys/dld_impl.h>
34 #include <sys/mac_client.h>
35 #include <sys/mac_client_impl.h>
36 #include <sys/mac_client_priv.h>
37
38 typedef void proto_reqfunc_t(dld_str_t *, mblk_t *);
39
40 static proto_reqfunc_t proto_info_req, proto_attach_req, proto_detach_req,
41 proto_bind_req, proto_unbind_req, proto_promiscon_req, proto_promiscoff_req,
42 proto_enabmulti_req, proto_disabmulti_req, proto_physaddr_req,
43 proto_setphysaddr_req, proto_udqos_req, proto_req, proto_capability_req,
557 dsp->ds_mode = DLD_UNITDATA;
558 dsp->ds_dlstate = DL_UNBOUND;
559
560 dls_active_clear(dsp, B_FALSE);
561 mac_perim_exit(mph);
562 dlokack(dsp->ds_wq, mp, DL_UNBIND_REQ);
563 return;
564 failed:
565 dlerrorack(q, mp, DL_UNBIND_REQ, dl_err, 0);
566 }
567
568 /*
569 * DL_PROMISCON_REQ
570 */
571 static void
572 proto_promiscon_req(dld_str_t *dsp, mblk_t *mp)
573 {
574 dl_promiscon_req_t *dlp = (dl_promiscon_req_t *)mp->b_rptr;
575 int err = 0;
576 t_uscalar_t dl_err;
577 uint32_t new_flags, promisc_saved;
578 queue_t *q = dsp->ds_wq;
579 mac_perim_handle_t mph;
580
581 if (MBLKL(mp) < sizeof (dl_promiscon_req_t)) {
582 dl_err = DL_BADPRIM;
583 goto failed;
584 }
585
586 if (dsp->ds_dlstate == DL_UNATTACHED ||
587 DL_ACK_PENDING(dsp->ds_dlstate)) {
588 dl_err = DL_OUTSTATE;
589 goto failed;
590 }
591
592 mac_perim_enter_by_mh(dsp->ds_mh, &mph);
593
594 new_flags = promisc_saved = dsp->ds_promisc;
595 switch (dlp->dl_level) {
596 case DL_PROMISC_SAP:
597 new_flags |= DLS_PROMISC_SAP;
598 break;
599
600 case DL_PROMISC_MULTI:
601 new_flags |= DLS_PROMISC_MULTI;
602 break;
603
604 case DL_PROMISC_PHYS:
605 new_flags |= DLS_PROMISC_PHYS;
606 break;
607
608 default:
609 dl_err = DL_NOTSUPPORTED;
610 goto failed;
611 }
612
613 if ((promisc_saved == 0) && (err = dls_active_set(dsp)) != 0) {
614 ASSERT(dsp->ds_promisc == promisc_saved);
615 dl_err = DL_SYSERR;
616 goto failed2;
617 }
618
619 /*
620 * Adjust channel promiscuity.
621 */
622 err = dls_promisc(dsp, new_flags);
623
624 if (err != 0) {
625 dl_err = DL_SYSERR;
626 dsp->ds_promisc = promisc_saved;
627 if (promisc_saved == 0)
628 dls_active_clear(dsp, B_FALSE);
629 goto failed2;
630 }
631
632 mac_perim_exit(mph);
633
634 dlokack(q, mp, DL_PROMISCON_REQ);
635 return;
636
637 failed2:
638 mac_perim_exit(mph);
639 failed:
640 dlerrorack(q, mp, DL_PROMISCON_REQ, dl_err, (t_uscalar_t)err);
641 }
642
643 /*
644 * DL_PROMISCOFF_REQ
645 */
646 static void
647 proto_promiscoff_req(dld_str_t *dsp, mblk_t *mp)
648 {
649 dl_promiscoff_req_t *dlp = (dl_promiscoff_req_t *)mp->b_rptr;
650 int err = 0;
651 t_uscalar_t dl_err;
652 uint32_t new_flags;
653 queue_t *q = dsp->ds_wq;
654 mac_perim_handle_t mph;
655
656 if (MBLKL(mp) < sizeof (dl_promiscoff_req_t)) {
657 dl_err = DL_BADPRIM;
658 goto failed;
659 }
660
661 if (dsp->ds_dlstate == DL_UNATTACHED ||
662 DL_ACK_PENDING(dsp->ds_dlstate)) {
663 dl_err = DL_OUTSTATE;
664 goto failed;
665 }
666
667 mac_perim_enter_by_mh(dsp->ds_mh, &mph);
668
669 new_flags = dsp->ds_promisc;
670 switch (dlp->dl_level) {
671 case DL_PROMISC_SAP:
672 if (!(dsp->ds_promisc & DLS_PROMISC_SAP)) {
673 dl_err = DL_NOTENAB;
674 goto failed;
675 }
676 new_flags &= ~DLS_PROMISC_SAP;
677 break;
678
679 case DL_PROMISC_MULTI:
680 if (!(dsp->ds_promisc & DLS_PROMISC_MULTI)) {
681 dl_err = DL_NOTENAB;
682 goto failed;
683 }
684 new_flags &= ~DLS_PROMISC_MULTI;
685 break;
686
687 case DL_PROMISC_PHYS:
688 if (!(dsp->ds_promisc & DLS_PROMISC_PHYS)) {
689 dl_err = DL_NOTENAB;
690 goto failed;
691 }
692 new_flags &= ~DLS_PROMISC_PHYS;
693 break;
694
695 default:
696 dl_err = DL_NOTSUPPORTED;
697 goto failed;
698 }
699
700 /*
701 * Adjust channel promiscuity.
702 */
703 err = dls_promisc(dsp, new_flags);
704
705 if (err != 0) {
706 mac_perim_exit(mph);
707 dl_err = DL_SYSERR;
708 goto failed;
709 }
710
711 ASSERT(dsp->ds_promisc == new_flags);
712 if (dsp->ds_promisc == 0)
713 dls_active_clear(dsp, B_FALSE);
714
715 mac_perim_exit(mph);
716
717 dlokack(q, mp, DL_PROMISCOFF_REQ);
718 return;
719 failed:
720 dlerrorack(q, mp, DL_PROMISCOFF_REQ, dl_err, (t_uscalar_t)err);
721 }
722
723 /*
724 * DL_ENABMULTI_REQ
725 */
726 static void
727 proto_enabmulti_req(dld_str_t *dsp, mblk_t *mp)
728 {
729 dl_enabmulti_req_t *dlp = (dl_enabmulti_req_t *)mp->b_rptr;
730 int err = 0;
731 t_uscalar_t dl_err;
|