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 (c) 2010, Oracle and/or its affiliates. All rights reserved.
23  */
24 
25 #ifndef	_SOCKFS_SOCKFILTER_H
26 #define	_SOCKFS_SOCKFILTER_H
27 
28 #include <sys/kstat.h>
29 #include <sys/list.h>
30 #include <sys/mutex.h>
31 #include <sys/socket.h>
32 #include <sys/socketvar.h>
33 #include <sys/sockfilter.h>
34 
35 #ifdef	__cplusplus
36 extern "C" {
37 #endif
38 
39 struct sonode;
40 struct sockparams;
41 
42 typedef struct sof_module	sof_module_t;
43 typedef struct sof_entry_kstat	sof_entry_kstat_t;
44 typedef struct sof_entry	sof_entry_t;
45 typedef struct sof_instance	sof_instance_t;
46 typedef struct sof_kstat	sof_kstat_t;
47 
48 #define	SOF_MAXNAMELEN		FILNAME_MAX
49 #define	SOF_MAXSOCKTUPLECNT	32
50 #define	SOF_MODPATH		SOCKMOD_PATH
51 
52 struct sof_module {
53 	char		*sofm_name;
54 	sof_ops_t	sofm_ops;
55 	uint_t		sofm_refcnt;
56 	list_node_t	sofm_node;
57 };
58 
59 struct sof_kstat {
60 	kstat_named_t	sofks_defer_closed;
61 	kstat_named_t	sofks_defer_close_backlog;
62 	kstat_named_t	sofks_defer_close_failed_backlog_too_big;
63 };
64 
65 #define	SOF_GLOBAL_STAT_BUMP(s) \
66 	atomic_inc_64(&sof_stat.sofks_##s.value.ui64)
67 
68 /*
69  * Per filter statistics.
70  */
71 struct sof_entry_kstat {
72 	kstat_named_t	sofek_nactive;		/* # of consumers */
73 	kstat_named_t	sofek_tot_active_attach;
74 	kstat_named_t	sofek_tot_passive_attach;
75 	kstat_named_t	sofek_ndeferred; 	/* # of deferred conns */
76 	kstat_named_t	sofek_attach_failures;
77 };
78 
79 /*
80  * Socket filter entry - one for each configured filter (added and
81  * removed by soconfig(8)).
82  *
83  * sofe_flags, sofe_refcnt and sofe_mod are protected by sofe_lock, and all
84  * other fields are write once.
85  */
86 struct sof_entry {
87 	char		sofe_name[SOF_MAXNAMELEN];	/* filter name */
88 	char		sofe_modname[MODMAXNAMELEN];	/* filter module */
89 	sof_hint_t	sofe_hint;			/* order hint */
90 	char		*sofe_hintarg;			/* hint argument */
91 	list_node_t	sofe_node;			/* global list node */
92 	uint_t		sofe_socktuple_cnt;		/* # of socket tuples */
93 	sof_socktuple_t	*sofe_socktuple;		/* socket tuple list */
94 
95 	sof_entry_kstat_t sofe_kstat;			/* filter stats */
96 	kstat_t		*sofe_ksp;
97 
98 	kmutex_t	sofe_lock;
99 	char		sofe_flags;			/* SOFEF_* flags */
100 	uint_t		sofe_refcnt;			/* # of instances */
101 	sof_module_t	*sofe_mod;			/* filter module */
102 };
103 
104 /* Filter entry flags */
105 #define	SOFEF_AUTO	0x1	/* automatic filter */
106 #define	SOFEF_PROG	0x2	/* programmatic filter */
107 #define	SOFEF_CONDEMED	0x4	/* removed by soconfig(8) */
108 
109 /*
110  * Socket filter instance - one for each socket using a sof_entry_t
111  */
112 struct sof_instance {
113 	sof_ops_t	*sofi_ops;	/* filter ops */
114 	void		*sofi_cookie;	/* filter cookie (from attach) */
115 	char		sofi_flags;	/* instance flags (SOFIF_*) */
116 	sof_instance_t	*sofi_prev;	/* up the stack */
117 	sof_instance_t	*sofi_next;	/* down the stack */
118 	struct sonode	*sofi_sonode;	/* socket instance is attached to */
119 	sof_entry_t	*sofi_filter;	/* filter this is an instance of */
120 };
121 
122 /* Filter instance flags */
123 #define	SOFIF_BYPASS		0x1	/* filter does not want any callbacks */
124 #define	SOFIF_DEFER		0x2	/* defer notification of socket */
125 #define	SOFIF_RCV_FLOWCTRL	0x4	/* flow control recv path */
126 #define	SOFIF_SND_FLOWCTRL	0x8	/* flow control send path */
127 
128 #define	SOF_STAT_ADD(i, s, v) \
129 	atomic_add_64(&(i)->sofi_filter->sofe_kstat.sofek_##s.value.ui64, (v))
130 
131 extern void	sof_init(void);
132 
133 extern void 	sof_entry_free(sof_entry_t *);
134 extern int	sof_entry_add(sof_entry_t *);
135 extern sof_entry_t *sof_entry_remove_by_name(const char *);
136 extern int 	sof_entry_proc_sockparams(sof_entry_t *, struct sockparams *);
137 
138 extern int	sof_sockparams_init(struct sockparams *);
139 extern void	sof_sockparams_fini(struct sockparams *);
140 
141 extern int	sof_sonode_autoattach_filters(struct sonode *, cred_t *);
142 extern int	sof_sonode_inherit_filters(struct sonode *, struct sonode *);
143 extern void	sof_sonode_closing(struct sonode *);
144 extern void	sof_sonode_cleanup(struct sonode *);
145 extern void	sof_sonode_notify_filters(struct sonode *, sof_event_t,
146     uintptr_t);
147 extern boolean_t sof_sonode_drop_deferred(struct sonode *);
148 
149 extern int 	sof_setsockopt(struct sonode *, int, const void *, socklen_t,
150     struct cred *);
151 extern int 	sof_getsockopt(struct sonode *, int, void *, socklen_t *,
152     struct cred *);
153 
154 extern int	sof_rval2errno(sof_rval_t);
155 
156 #define	SOF_INTERESTED(inst, op)			\
157 	(!((inst)->sofi_flags & SOFIF_BYPASS) &&	\
158 	(inst)->sofi_ops->sofop_##op != NULL)
159 
160 /*
161  * SOF_FILTER_OP traverses the filter stack for sonode `so' top-down,
162  * calling `op' for each filter with the supplied `args'. A non-negative
163  * return value indicates that a filter action was taken.
164  */
165 #define	__SOF_FILTER_OP(so, op, cr, ...) 		\
166 	sof_instance_t *__inst;					\
167 	sof_rval_t __rval;					\
168 								\
169 	for (__inst = (so)->so_filter_top; __inst != NULL;	\
170 	    __inst = __inst->sofi_next) {			\
171 		if (!SOF_INTERESTED(__inst, op))		\
172 			continue;				\
173 		__rval = (__inst->sofi_ops->sofop_##op)((sof_handle_t)__inst,\
174 		    __inst->sofi_cookie, __VA_ARGS__, cr);	\
175 		DTRACE_PROBE2(filter__action, (sof_instance_t), __inst,\
176 		    (sof_rval_t), __rval);			\
177 		if (__rval != SOF_RVAL_CONTINUE) 		\
178 			return (sof_rval2errno(__rval));	\
179 	}							\
180 	return (-1);
181 
182 extern mblk_t	*sof_filter_data_out_from(struct sonode *so,
183     sof_instance_t *, mblk_t *, struct nmsghdr *, cred_t *, int *);
184 extern mblk_t	*sof_filter_data_in_proc(struct sonode *so,
185     mblk_t *, mblk_t **);
186 extern int	sof_filter_bind(struct sonode *, struct sockaddr *,
187     socklen_t *, cred_t *);
188 extern int	sof_filter_listen(struct sonode *, int *, cred_t *);
189 extern int	sof_filter_connect(struct sonode *, struct sockaddr *,
190     socklen_t *, cred_t *);
191 extern int	sof_filter_accept(struct sonode *, cred_t *);
192 extern int	sof_filter_shutdown(struct sonode *, int *, cred_t *);
193 extern int 	sof_filter_getsockname(struct sonode *, struct sockaddr *,
194     socklen_t *, cred_t *);
195 extern int 	sof_filter_getpeername(struct sonode *, struct sockaddr *,
196     socklen_t *, cred_t *);
197 extern int	sof_filter_setsockopt(struct sonode *, int, int, void *,
198     socklen_t *, cred_t *);
199 extern int	sof_filter_getsockopt(struct sonode *, int, int, void *,
200     socklen_t *, cred_t *);
201 extern int	sof_filter_ioctl(struct sonode *, int, intptr_t, int,
202     int32_t *, cred_t *);
203 
204 #define	SOF_FILTER_DATA_OUT(so, mp, msg, cr, errp) \
205 	sof_filter_data_out_from(so, (so)->so_filter_top, mp, msg, cr, errp)
206 #define	SOF_FILTER_DATA_OUT_FROM(so, inst, mp, msg, cr, errp) \
207 	sof_filter_data_out_from(so, inst, mp, msg, cr, errp)
208 
209 #ifdef	__cplusplus
210 }
211 #endif
212 
213 #endif	/* _SOCKFS_SOCKFILTER_H */
214