1 /*
2 * Copyright (C) 1993-2001, 2003 by Darren Reed.
3 *
4 * See the IPFILTER.LICENCE file for details on licencing.
5 *
6 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
7 * Use is subject to license terms.
8 *
9 * Copyright (c) 2014, Joyent, Inc. All rights reserved.
10 */
11
12 /*
13 * ipfilter kernel module mutexes and locking:
14 *
15 * Enabling ipfilter creates a per-netstack ipf_stack_t object that is
16 * stored in the ipf_stacks list, which is protected by ipf_stack_lock.
17 * ipf_stack_t objects are accessed in three contexts:
18 *
19 * 1) administering that filter (eg: ioctls handled with iplioctl())
20 * 2) reading log data (eg: iplread() / iplwrite())
21 * 3) filtering packets (eg: ipf_hook4_* and ipf_hook6_* pfhooks
22 * functions)
23 *
24 * Each ipf_stack_t has a RW lock, ifs_ipf_global, protecting access to the
25 * whole structure. The structure also has locks protecting the various
26 * data structures used for filtering. The following guidelines should be
27 * followed for ipf_stack_t locks:
28 *
29 * - ipf_stack_lock must be held when accessing the ipf_stacks list
99 #include "netinet/ip_frag.h"
100 #include "netinet/ip_auth.h"
101 #include "netinet/ip_state.h"
102 #include "netinet/ipf_stack.h"
103
104 extern int iplwrite __P((dev_t, struct uio *, cred_t *));
105
106 static int ipf_getinfo __P((dev_info_t *, ddi_info_cmd_t,
107 void *, void **));
108 #if SOLARIS2 < 10
109 static int ipf_identify __P((dev_info_t *));
110 #endif
111 static int ipf_attach __P((dev_info_t *, ddi_attach_cmd_t));
112 static int ipf_detach __P((dev_info_t *, ddi_detach_cmd_t));
113 static void *ipf_stack_create __P((const netid_t));
114 static void ipf_stack_destroy __P((const netid_t, void *));
115 static void ipf_stack_shutdown __P((const netid_t, void *));
116 static int ipf_property_g_update __P((dev_info_t *));
117 static char *ipf_devfiles[] = { IPL_NAME, IPNAT_NAME, IPSTATE_NAME,
118 IPAUTH_NAME, IPSYNC_NAME, IPSCAN_NAME,
119 IPLOOKUP_NAME, NULL };
120 extern void *ipf_state; /* DDI state */
121 extern vmem_t *ipf_minor; /* minor number arena */
122
123 static struct cb_ops ipf_cb_ops = {
124 iplopen,
125 iplclose,
126 nodev, /* strategy */
127 nodev, /* print */
128 nodev, /* dump */
129 iplread,
130 iplwrite, /* write */
131 iplioctl, /* ioctl */
132 nodev, /* devmap */
133 nodev, /* mmap */
134 nodev, /* segmap */
135 nochpoll, /* poll */
136 ddi_prop_op,
137 NULL,
138 D_MTSAFE,
139 #if SOLARIS2 > 4
724 (void) ipf_property_g_update(dip);
725
726 if (ddi_soft_state_init(&ipf_state, sizeof (ipf_devstate_t), 1)
727 != 0) {
728 ddi_prop_remove_all(dip);
729 return (DDI_FAILURE);
730 }
731
732 for (i = 0; ((s = ipf_devfiles[i]) != NULL); i++) {
733 s = strrchr(s, '/');
734 if (s == NULL)
735 continue;
736 s++;
737 if (ddi_create_minor_node(dip, s, S_IFCHR, i,
738 DDI_PSEUDO, 0) == DDI_FAILURE)
739 goto attach_failed;
740 }
741
742 ipf_dev_info = dip;
743
744 ipfncb = net_instance_alloc(NETINFO_VERSION);
745 if (ipfncb == NULL)
746 goto attach_failed;
747
748 ipfncb->nin_name = "ipf";
749 ipfncb->nin_create = ipf_stack_create;
750 ipfncb->nin_destroy = ipf_stack_destroy;
751 ipfncb->nin_shutdown = ipf_stack_shutdown;
752 if (net_instance_register(ipfncb) == DDI_FAILURE) {
753 net_instance_free(ipfncb);
754 goto attach_failed;
755 }
756
757 ipf_minor = vmem_create("ipf_minor", (void *)1, UINT32_MAX - 1,
758 1, NULL, NULL, NULL, 0, VM_SLEEP | VMC_IDENTIFIER);
759
760 #ifdef IPFDEBUG
761 cmn_err(CE_CONT, "IP Filter:stack_create callback_reg=%d", i);
762 #endif
763
764 return (DDI_SUCCESS);
765 /* NOTREACHED */
766 default:
767 break;
768 }
769
770 attach_failed:
771 ddi_remove_minor_node(dip, NULL);
772 ddi_prop_remove_all(dip);
773 ddi_soft_state_fini(&ipf_state);
774 return (DDI_FAILURE);
775 }
776
777
778 static int ipf_detach(dip, cmd)
779 dev_info_t *dip;
780 ddi_detach_cmd_t cmd;
781 {
782 int i;
783
784 #ifdef IPFDEBUG
785 cmn_err(CE_NOTE, "IP Filter: ipf_detach(%p,%x)", dip, cmd);
786 #endif
787 switch (cmd) {
788 case DDI_DETACH:
789 if (ipf_detach_check_all() != 0)
790 return (DDI_FAILURE);
791
792 /*
793 * Undo what we did in ipf_attach, freeing resources
794 * and removing things we installed. The system
795 * framework guarantees we are not active with this devinfo
796 * node in any other entry points at this time.
797 */
798 ddi_prop_remove_all(dip);
799 i = ddi_get_instance(dip);
800 ddi_remove_minor_node(dip, NULL);
801 if (i > 0) {
802 cmn_err(CE_CONT, "IP Filter: still attached (%d)\n", i);
803 return (DDI_FAILURE);
804 }
805
806 vmem_destroy(ipf_minor);
807 ddi_soft_state_fini(&ipf_state);
808
809 (void) net_instance_unregister(ipfncb);
810 net_instance_free(ipfncb);
811
812 return (DDI_SUCCESS);
813 /* NOTREACHED */
814 default:
815 break;
816 }
817 cmn_err(CE_NOTE, "IP Filter: failed to detach\n");
|
1 /*
2 * Copyright (C) 1993-2001, 2003 by Darren Reed.
3 *
4 * See the IPFILTER.LICENCE file for details on licencing.
5 *
6 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
7 * Use is subject to license terms.
8 *
9 * Copyright 2019 Joyent, Inc.
10 */
11
12 /*
13 * ipfilter kernel module mutexes and locking:
14 *
15 * Enabling ipfilter creates a per-netstack ipf_stack_t object that is
16 * stored in the ipf_stacks list, which is protected by ipf_stack_lock.
17 * ipf_stack_t objects are accessed in three contexts:
18 *
19 * 1) administering that filter (eg: ioctls handled with iplioctl())
20 * 2) reading log data (eg: iplread() / iplwrite())
21 * 3) filtering packets (eg: ipf_hook4_* and ipf_hook6_* pfhooks
22 * functions)
23 *
24 * Each ipf_stack_t has a RW lock, ifs_ipf_global, protecting access to the
25 * whole structure. The structure also has locks protecting the various
26 * data structures used for filtering. The following guidelines should be
27 * followed for ipf_stack_t locks:
28 *
29 * - ipf_stack_lock must be held when accessing the ipf_stacks list
99 #include "netinet/ip_frag.h"
100 #include "netinet/ip_auth.h"
101 #include "netinet/ip_state.h"
102 #include "netinet/ipf_stack.h"
103
104 extern int iplwrite __P((dev_t, struct uio *, cred_t *));
105
106 static int ipf_getinfo __P((dev_info_t *, ddi_info_cmd_t,
107 void *, void **));
108 #if SOLARIS2 < 10
109 static int ipf_identify __P((dev_info_t *));
110 #endif
111 static int ipf_attach __P((dev_info_t *, ddi_attach_cmd_t));
112 static int ipf_detach __P((dev_info_t *, ddi_detach_cmd_t));
113 static void *ipf_stack_create __P((const netid_t));
114 static void ipf_stack_destroy __P((const netid_t, void *));
115 static void ipf_stack_shutdown __P((const netid_t, void *));
116 static int ipf_property_g_update __P((dev_info_t *));
117 static char *ipf_devfiles[] = { IPL_NAME, IPNAT_NAME, IPSTATE_NAME,
118 IPAUTH_NAME, IPSYNC_NAME, IPSCAN_NAME,
119 IPLOOKUP_NAME, IPFEV_NAME, NULL };
120 extern void *ipf_state; /* DDI state */
121 extern vmem_t *ipf_minor; /* minor number arena */
122
123 static struct cb_ops ipf_cb_ops = {
124 iplopen,
125 iplclose,
126 nodev, /* strategy */
127 nodev, /* print */
128 nodev, /* dump */
129 iplread,
130 iplwrite, /* write */
131 iplioctl, /* ioctl */
132 nodev, /* devmap */
133 nodev, /* mmap */
134 nodev, /* segmap */
135 nochpoll, /* poll */
136 ddi_prop_op,
137 NULL,
138 D_MTSAFE,
139 #if SOLARIS2 > 4
724 (void) ipf_property_g_update(dip);
725
726 if (ddi_soft_state_init(&ipf_state, sizeof (ipf_devstate_t), 1)
727 != 0) {
728 ddi_prop_remove_all(dip);
729 return (DDI_FAILURE);
730 }
731
732 for (i = 0; ((s = ipf_devfiles[i]) != NULL); i++) {
733 s = strrchr(s, '/');
734 if (s == NULL)
735 continue;
736 s++;
737 if (ddi_create_minor_node(dip, s, S_IFCHR, i,
738 DDI_PSEUDO, 0) == DDI_FAILURE)
739 goto attach_failed;
740 }
741
742 ipf_dev_info = dip;
743
744 if (ipf_cfw_ring_resize(IPF_CFW_RING_ALLOCATE) != 0)
745 goto attach_failed;
746
747 ipfncb = net_instance_alloc(NETINFO_VERSION);
748 if (ipfncb == NULL)
749 goto attach_failed;
750
751 ipfncb->nin_name = "ipf";
752 ipfncb->nin_create = ipf_stack_create;
753 ipfncb->nin_destroy = ipf_stack_destroy;
754 ipfncb->nin_shutdown = ipf_stack_shutdown;
755 if (net_instance_register(ipfncb) == DDI_FAILURE) {
756 net_instance_free(ipfncb);
757 goto attach_failed;
758 }
759
760 ipf_minor = vmem_create("ipf_minor", (void *)1, UINT32_MAX - 1,
761 1, NULL, NULL, NULL, 0, VM_SLEEP | VMC_IDENTIFIER);
762
763 #ifdef IPFDEBUG
764 cmn_err(CE_CONT, "IP Filter:stack_create callback_reg=%d", i);
765 #endif
766
767 return (DDI_SUCCESS);
768 /* NOTREACHED */
769 default:
770 break;
771 }
772
773 attach_failed:
774 (void) ipf_cfw_ring_resize(IPF_CFW_RING_DESTROY);
775 ddi_remove_minor_node(dip, NULL);
776 ddi_prop_remove_all(dip);
777 ddi_soft_state_fini(&ipf_state);
778 return (DDI_FAILURE);
779 }
780
781
782 static int ipf_detach(dip, cmd)
783 dev_info_t *dip;
784 ddi_detach_cmd_t cmd;
785 {
786 int i;
787
788 #ifdef IPFDEBUG
789 cmn_err(CE_NOTE, "IP Filter: ipf_detach(%p,%x)", dip, cmd);
790 #endif
791 switch (cmd) {
792 case DDI_DETACH:
793 if (ipf_detach_check_all() != 0)
794 return (DDI_FAILURE);
795
796 /*
797 * Undo what we did in ipf_attach, freeing resources
798 * and removing things we installed. The system
799 * framework guarantees we are not active with this devinfo
800 * node in any other entry points at this time.
801 */
802 (void) ipf_cfw_ring_resize(IPF_CFW_RING_DESTROY);
803 ddi_prop_remove_all(dip);
804 i = ddi_get_instance(dip);
805 ddi_remove_minor_node(dip, NULL);
806 if (i > 0) {
807 cmn_err(CE_CONT, "IP Filter: still attached (%d)\n", i);
808 return (DDI_FAILURE);
809 }
810
811 vmem_destroy(ipf_minor);
812 ddi_soft_state_fini(&ipf_state);
813
814 (void) net_instance_unregister(ipfncb);
815 net_instance_free(ipfncb);
816
817 return (DDI_SUCCESS);
818 /* NOTREACHED */
819 default:
820 break;
821 }
822 cmn_err(CE_NOTE, "IP Filter: failed to detach\n");
|