]> git.saurik.com Git - apple/xnu.git/blob - bsd/net/content_filter.h
xnu-3789.70.16.tar.gz
[apple/xnu.git] / bsd / net / content_filter.h
1 /*
2 * Copyright (c) 2013-2014 Apple Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
11 * file.
12 *
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
20 *
21 * @APPLE_LICENSE_HEADER_END@
22 */
23
24 #ifndef __CONTENT_FILTER_H__
25 #define __CONTENT_FILTER_H__
26
27 #include <sys/param.h>
28 #include <sys/types.h>
29 #include <sys/_types/_timeval64.h>
30 #include <sys/socket.h>
31 #include <sys/syslog.h>
32 #include <netinet/in.h>
33 #include <stdint.h>
34
35 #ifdef BSD_KERNEL_PRIVATE
36 #include <sys/mbuf.h>
37 #include <sys/socketvar.h>
38 #endif /* BSD_KERNEL_PRIVATE */
39
40 __BEGIN_DECLS
41
42 #ifdef PRIVATE
43
44 /*
45 * Kernel control name for an instance of a Content Filter
46 * Use CTLIOCGINFO to find out the corresponding kernel control id
47 * to be set in the sc_id field of sockaddr_ctl for connect(2)
48 * Note: the sc_unit is ephemeral
49 */
50 #define CONTENT_FILTER_CONTROL_NAME "com.apple.content-filter"
51
52 /*
53 * CFIL_OPT_NECP_CONTROL_UNIT
54 * To set or get the NECP filter control unit for the kernel control socket
55 * The option level is SYSPROTO_CONTROL
56 */
57 #define CFIL_OPT_NECP_CONTROL_UNIT 1 /* uint32_t */
58
59 /*
60 * How many filter may be active simultaneously
61 */
62 #define CFIL_MAX_FILTER_COUNT 2
63
64 /*
65 * Types of messages
66 *
67 * Event messages flow from kernel to user space while action
68 * messages flow in the reverse direction.
69 * A message in entirely represented by a packet sent or received
70 * on a Content Filter kernel control socket.
71 */
72 #define CFM_TYPE_EVENT 1 /* message from kernel */
73 #define CFM_TYPE_ACTION 2 /* message to kernel */
74
75 /*
76 * Operations associated with events from kernel
77 */
78 #define CFM_OP_SOCKET_ATTACHED 1 /* a socket has been attached */
79 #define CFM_OP_SOCKET_CLOSED 2 /* a socket is being closed */
80 #define CFM_OP_DATA_OUT 3 /* data being sent */
81 #define CFM_OP_DATA_IN 4 /* data being received */
82 #define CFM_OP_DISCONNECT_OUT 5 /* no more outgoing data */
83 #define CFM_OP_DISCONNECT_IN 6 /* no more incoming data */
84
85 /*
86 * Operations associated with action from filter to kernel
87 */
88 #define CFM_OP_DATA_UPDATE 16 /* update pass or peek offsets */
89 #define CFM_OP_DROP 17 /* shutdown socket, no more data */
90
91 /*
92 * Opaque socket identifier
93 */
94 typedef uint64_t cfil_sock_id_t;
95
96 #define CFIL_SOCK_ID_NONE UINT64_MAX
97
98 /*
99 * struct cfil_msg_hdr
100 *
101 * Header common to all messages
102 */
103 struct cfil_msg_hdr {
104 uint32_t cfm_len; /* total length */
105 uint32_t cfm_version;
106 uint32_t cfm_type;
107 uint32_t cfm_op;
108 cfil_sock_id_t cfm_sock_id;
109 };
110
111 #define CFM_VERSION_CURRENT 1
112
113 /*
114 * struct cfil_msg_sock_attached
115 *
116 * Information about a new socket being attached to the content filter
117 *
118 * Action: No reply is expected as this does not block the creation of the
119 * TCP/IP but timely action must be taken to avoid user noticeable delays.
120 *
121 * Valid Types: CFM_TYPE_EVENT
122 *
123 * Valid Op: CFM_OP_SOCKET_ATTACHED
124 */
125 struct cfil_msg_sock_attached {
126 struct cfil_msg_hdr cfs_msghdr;
127 int cfs_sock_family; /* e.g. PF_INET */
128 int cfs_sock_type; /* e.g. SOCK_STREAM */
129 int cfs_sock_protocol; /* e.g. IPPROTO_TCP */
130 int cfs_unused; /* padding */
131 pid_t cfs_pid;
132 pid_t cfs_e_pid;
133 uuid_t cfs_uuid;
134 uuid_t cfs_e_uuid;
135 };
136
137 /*
138 * struct cfil_msg_data_event
139 *
140 * Event for the content fiter to act on a span of data
141 * A data span is described by a pair of offsets over the cumulative
142 * number of bytes sent or received on the socket.
143 *
144 * Action: The event must be acted upon but the filter may buffer
145 * data spans until it has enough content to make a decision.
146 * The action must be timely to avoid user noticeable delays.
147 *
148 * Valid Type: CFM_TYPE_EVENT
149 *
150 * Valid Ops: CFM_OP_DATA_OUT, CFM_OP_DATA_IN
151 */
152 struct cfil_msg_data_event {
153 struct cfil_msg_hdr cfd_msghdr;
154 union sockaddr_in_4_6 cfc_src;
155 union sockaddr_in_4_6 cfc_dst;
156 uint64_t cfd_start_offset;
157 uint64_t cfd_end_offset;
158 /* Actual content data immediatly follows */
159 };
160
161 /*
162 * struct cfil_msg_action
163 *
164 * Valid Type: CFM_TYPE_ACTION
165 *
166 * Valid Ops: CFM_OP_DATA_UPDATE, CFM_OP_DROP
167 *
168 * For CFM_OP_DATA_UPDATE:
169 *
170 * cfa_in_pass_offset and cfa_out_pass_offset indicates how much data is
171 * allowed to pass. A zero value does not modify the corresponding pass offset.
172 *
173 * cfa_in_peek_offset and cfa_out_peek_offset lets the filter specify how much
174 * data it needs to make a decision: the kernel will deliver data up to that
175 * offset (if less than cfa_pass_offset it is ignored). Use CFM_MAX_OFFSET
176 * if you don't value the corresponding peek offset to be updated.
177 */
178 struct cfil_msg_action {
179 struct cfil_msg_hdr cfa_msghdr;
180 uint64_t cfa_in_pass_offset;
181 uint64_t cfa_in_peek_offset;
182 uint64_t cfa_out_pass_offset;
183 uint64_t cfa_out_peek_offset;
184 };
185
186 #define CFM_MAX_OFFSET UINT64_MAX
187
188 /*
189 * Statistics retrieved via sysctl(3)
190 */
191 struct cfil_filter_stat {
192 uint32_t cfs_len;
193 uint32_t cfs_filter_id;
194 uint32_t cfs_flags;
195 uint32_t cfs_sock_count;
196 uint32_t cfs_necp_control_unit;
197 };
198
199 struct cfil_entry_stat {
200 uint32_t ces_len;
201 uint32_t ces_filter_id;
202 uint32_t ces_flags;
203 uint32_t ces_necp_control_unit;
204 struct timeval64 ces_last_event;
205 struct timeval64 ces_last_action;
206 struct cfe_buf_stat {
207 uint64_t cbs_pending_first;
208 uint64_t cbs_pending_last;
209 uint64_t cbs_ctl_first;
210 uint64_t cbs_ctl_last;
211 uint64_t cbs_pass_offset;
212 uint64_t cbs_peek_offset;
213 uint64_t cbs_peeked;
214 } ces_snd, ces_rcv;
215 };
216
217 struct cfil_sock_stat {
218 uint32_t cfs_len;
219 int cfs_sock_family;
220 int cfs_sock_type;
221 int cfs_sock_protocol;
222 cfil_sock_id_t cfs_sock_id;
223 uint64_t cfs_flags;
224 pid_t cfs_pid;
225 pid_t cfs_e_pid;
226 uuid_t cfs_uuid;
227 uuid_t cfs_e_uuid;
228 struct cfi_buf_stat {
229 uint64_t cbs_pending_first;
230 uint64_t cbs_pending_last;
231 uint64_t cbs_pass_offset;
232 uint64_t cbs_inject_q_len;
233 } cfs_snd, cfs_rcv;
234 struct cfil_entry_stat ces_entries[CFIL_MAX_FILTER_COUNT];
235 };
236
237 /*
238 * Global statistics
239 */
240 struct cfil_stats {
241 int32_t cfs_ctl_connect_ok;
242 int32_t cfs_ctl_connect_fail;
243 int32_t cfs_ctl_disconnect_ok;
244 int32_t cfs_ctl_disconnect_fail;
245 int32_t cfs_ctl_send_ok;
246 int32_t cfs_ctl_send_bad;
247 int32_t cfs_ctl_rcvd_ok;
248 int32_t cfs_ctl_rcvd_bad;
249 int32_t cfs_ctl_rcvd_flow_lift;
250 int32_t cfs_ctl_action_data_update;
251 int32_t cfs_ctl_action_drop;
252 int32_t cfs_ctl_action_bad_op;
253 int32_t cfs_ctl_action_bad_len;
254
255 int32_t cfs_sock_id_not_found;
256
257 int32_t cfs_cfi_alloc_ok;
258 int32_t cfs_cfi_alloc_fail;
259
260 int32_t cfs_sock_userspace_only;
261 int32_t cfs_sock_attach_in_vain;
262 int32_t cfs_sock_attach_already;
263 int32_t cfs_sock_attach_no_mem;
264 int32_t cfs_sock_attach_failed;
265 int32_t cfs_sock_attached;
266 int32_t cfs_sock_detached;
267
268 int32_t cfs_attach_event_ok;
269 int32_t cfs_attach_event_flow_control;
270 int32_t cfs_attach_event_fail;
271
272 int32_t cfs_closed_event_ok;
273 int32_t cfs_closed_event_flow_control;
274 int32_t cfs_closed_event_fail;
275
276 int32_t cfs_data_event_ok;
277 int32_t cfs_data_event_flow_control;
278 int32_t cfs_data_event_fail;
279
280 int32_t cfs_disconnect_in_event_ok;
281 int32_t cfs_disconnect_out_event_ok;
282 int32_t cfs_disconnect_event_flow_control;
283 int32_t cfs_disconnect_event_fail;
284
285 int32_t cfs_ctl_q_not_started;
286
287 int32_t cfs_close_wait;
288 int32_t cfs_close_wait_timeout;
289
290 int32_t cfs_flush_in_drop;
291 int32_t cfs_flush_out_drop;
292 int32_t cfs_flush_in_close;
293 int32_t cfs_flush_out_close;
294 int32_t cfs_flush_in_free;
295 int32_t cfs_flush_out_free;
296
297 int32_t cfs_inject_q_nomem;
298 int32_t cfs_inject_q_nobufs;
299 int32_t cfs_inject_q_detached;
300 int32_t cfs_inject_q_in_fail;
301 int32_t cfs_inject_q_out_fail;
302
303 int32_t cfs_inject_q_in_retry;
304 int32_t cfs_inject_q_out_retry;
305
306 int32_t cfs_data_in_control;
307 int32_t cfs_data_in_oob;
308 int32_t cfs_data_out_control;
309 int32_t cfs_data_out_oob;
310
311 int64_t cfs_ctl_q_in_enqueued __attribute__((aligned(8)));
312 int64_t cfs_ctl_q_out_enqueued __attribute__((aligned(8)));
313 int64_t cfs_ctl_q_in_peeked __attribute__((aligned(8)));
314 int64_t cfs_ctl_q_out_peeked __attribute__((aligned(8)));
315
316 int64_t cfs_pending_q_in_enqueued __attribute__((aligned(8)));
317 int64_t cfs_pending_q_out_enqueued __attribute__((aligned(8)));
318
319 int64_t cfs_inject_q_in_enqueued __attribute__((aligned(8)));
320 int64_t cfs_inject_q_out_enqueued __attribute__((aligned(8)));
321 int64_t cfs_inject_q_in_passed __attribute__((aligned(8)));
322 int64_t cfs_inject_q_out_passed __attribute__((aligned(8)));
323
324 };
325 #endif /* PRIVATE */
326
327 #ifdef BSD_KERNEL_PRIVATE
328
329 #define M_SKIPCFIL M_PROTO5
330
331 extern int cfil_log_level;
332
333 #define CFIL_LOG(level, fmt, ...) \
334 do { \
335 if (cfil_log_level >= level) \
336 printf("%s:%d " fmt "\n",\
337 __FUNCTION__, __LINE__, ##__VA_ARGS__); \
338 } while (0)
339
340
341 extern void cfil_init(void);
342
343 extern errno_t cfil_sock_attach(struct socket *so);
344 extern errno_t cfil_sock_detach(struct socket *so);
345
346 extern int cfil_sock_data_out(struct socket *so, struct sockaddr *to,
347 struct mbuf *data, struct mbuf *control,
348 uint32_t flags);
349 extern int cfil_sock_data_in(struct socket *so, struct sockaddr *from,
350 struct mbuf *data, struct mbuf *control,
351 uint32_t flags);
352
353 extern int cfil_sock_shutdown(struct socket *so, int *how);
354 extern void cfil_sock_is_closed(struct socket *so);
355 extern void cfil_sock_notify_shutdown(struct socket *so, int how);
356 extern void cfil_sock_close_wait(struct socket *so);
357
358 extern boolean_t cfil_sock_data_pending(struct sockbuf *sb);
359 extern int cfil_sock_data_space(struct sockbuf *sb);
360 extern void cfil_sock_buf_update(struct sockbuf *sb);
361
362 extern cfil_sock_id_t cfil_sock_id_from_socket(struct socket *so);
363
364 __END_DECLS
365
366 #endif /* BSD_KERNEL_PRIVATE */
367
368 #endif /* __CONTENT_FILTER_H__ */