1/*
2 * Copyright (c) 2008-2021 Apple Inc. All rights reserved.
3 *
4 * @APPLE_OSREFERENCE_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. The rights granted to you under the License
10 * may not be used to create, or enable the creation or redistribution of,
11 * unlawful or unlicensed copies of an Apple operating system, or to
12 * circumvent, violate, or enable the circumvention or violation of, any
13 * terms of an Apple operating system software license agreement.
14 *
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
17 *
18 * The Original Code and all software distributed under the License are
19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 * Please see the License for the specific language governing rights and
24 * limitations under the License.
25 *
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27 */
28/*!
29 * @header kpi_ipfilter.h
30 * This header defines an API to attach IP filters. IP filters may be
31 * attached to intercept either IPv4 or IPv6 packets. The filters can
32 * intercept all IP packets in to and out of the host regardless of
33 * interface.
34 */
35
36#ifndef __KPI_IPFILTER__
37#define __KPI_IPFILTER__
38
39#ifndef PRIVATE
40#include <Availability.h>
41#define __NKE_API_DEPRECATED __API_DEPRECATED("Network Kernel Extension KPI is deprecated", macos(10.4, 10.15))
42#else
43#define __NKE_API_DEPRECATED
44#endif /* PRIVATE */
45
46/*
47 * ipf_pktopts
48 *
49 * Options for outgoing packets. The options need to be preserved when
50 * re-injecting a packet.
51 */
52struct ipf_pktopts {
53 u_int32_t ippo_flags;
54 ifnet_t ippo_mcast_ifnet;
55 int ippo_mcast_loop;
56 u_int8_t ippo_mcast_ttl;
57};
58#define IPPOF_MCAST_OPTS 0x1
59#ifdef PRIVATE
60#define IPPOF_BOUND_IF 0x2
61#define IPPOF_NO_IFT_CELLULAR 0x4
62#define IPPOF_SELECT_SRCIF 0x8
63#define IPPOF_BOUND_SRCADDR 0x10
64#define IPPOF_SHIFT_IFSCOPE 16
65#define IPPOF_NO_IFF_EXPENSIVE 0x20
66#define IPPOF_NO_IFF_CONSTRAINED 0x40
67#endif /* PRIVATE */
68
69typedef struct ipf_pktopts *ipf_pktopts_t;
70
71__BEGIN_DECLS
72
73/*!
74 * @typedef ipf_input_func
75 *
76 * @discussion ipf_input_func is used to filter incoming ip packets.
77 * The IP filter is called for packets from all interfaces. The
78 * filter is called between when the general IP processing is
79 * handled and when the packet is passed up to the next layer
80 * protocol such as udp or tcp. In the case of encapsulation, such
81 * as UDP in ESP (IPsec), your filter will be called once for ESP
82 * and then again for UDP. This will give your filter an
83 * opportunity to process the ESP header as well as the decrypted
84 * packet. Offset and protocol are used to determine where in the
85 * packet processing is currently occuring. If you're only
86 * interested in TCP or UDP packets, just return 0 if protocol
87 * doesn't match TCP or UDP.
88 * @param cookie The cookie specified when your filter was attached.
89 * @param data The reassembled ip packet, data will start at the ip
90 * header.
91 * @param offset An offset to the next header
92 * (udp/tcp/icmp/esp/etc...).
93 * @param protocol The protocol type (udp/tcp/icmp/etc...) of the IP packet
94 * @result Return:
95 * 0 - The caller will continue with normal processing of the
96 * packet.
97 * EJUSTRETURN - The caller will stop processing the packet,
98 * the packet will not be freed.
99 * Anything Else - The caller will free the packet and stop
100 * processing.
101 */
102typedef errno_t (*ipf_input_func)(void *cookie, mbuf_t *data, int offset,
103 u_int8_t protocol);
104
105/*!
106 * @typedef ipf_output_func
107 *
108 * @discussion ipf_output_func is used to filter outbound ip packets.
109 * The IP filter is called for packets to all interfaces. The
110 * filter is called before fragmentation and IPsec processing. If
111 * you need to change the destination IP address, call
112 * ipf_inject_output and return EJUSTRETURN.
113 * @param cookie The cookie specified when your filter was attached.
114 * @param data The ip packet, will contain an IP header followed by the
115 * rest of the IP packet.
116 * @result Return:
117 * 0 - The caller will continue with normal processing of the
118 * packet.
119 * EJUSTRETURN - The caller will stop processing the packet,
120 * the packet will not be freed.
121 * Anything Else - The caller will free the packet and stop
122 * processing.
123 */
124typedef errno_t (*ipf_output_func)(void *cookie, mbuf_t *data,
125 ipf_pktopts_t options);
126
127/*!
128 * @typedef ipf_detach_func
129 *
130 * @discussion ipf_detach_func is called to notify your filter that it
131 * has been detached.
132 * @param cookie The cookie specified when your filter was attached.
133 */
134typedef void (*ipf_detach_func)(void *cookie);
135
136/*!
137 * @typedef ipf_filter
138 * @discussion This structure is used to define an IP filter for
139 * use with the ipf_addv4 or ipf_addv6 function.
140 * @field cookie A kext defined cookie that will be passed to all
141 * filter functions.
142 * @field name A filter name used for debugging purposes.
143 * @field ipf_input The filter function to handle inbound packets.
144 * @field ipf_output The filter function to handle outbound packets.
145 * @field ipf_detach The filter function to notify of a detach.
146 */
147struct ipf_filter {
148 void *cookie;
149 const char *name;
150 ipf_input_func ipf_input;
151 ipf_output_func ipf_output;
152 ipf_detach_func ipf_detach;
153};
154
155struct opaque_ipfilter;
156typedef struct opaque_ipfilter *ipfilter_t;
157
158/*!
159 * @function ipf_addv4
160 * @discussion Attaches an IPv4 ip filter.
161 * @param filter A structure defining the filter.
162 * @param filter_ref A reference to the filter used to detach it.
163 * @result 0 on success otherwise the errno error.
164 */
165#ifdef KERNEL_PRIVATE
166extern errno_t ipf_addv4_internal(const struct ipf_filter *filter,
167 ipfilter_t *filter_ref);
168
169#define ipf_addv4(filter, filter_ref) \
170 ipf_addv4_internal((filter), (filter_ref))
171#else
172extern errno_t ipf_addv4(const struct ipf_filter *filter,
173 ipfilter_t *filter_ref)
174__NKE_API_DEPRECATED;
175#endif /* KERNEL_PRIVATE */
176
177/*!
178 * @function ipf_addv6
179 * @discussion Attaches an IPv6 ip filter.
180 * @param filter A structure defining the filter.
181 * @param filter_ref A reference to the filter used to detach it.
182 * @result 0 on success otherwise the errno error.
183 */
184#ifdef KERNEL_PRIVATE
185extern errno_t ipf_addv6_internal(const struct ipf_filter *filter,
186 ipfilter_t *filter_ref);
187
188#define ipf_addv6(filter, filter_ref) \
189 ipf_addv6_internal((filter), (filter_ref))
190#else
191extern errno_t ipf_addv6(const struct ipf_filter *filter,
192 ipfilter_t *filter_ref)
193__NKE_API_DEPRECATED;
194#endif /* KERNEL_PRIVATE */
195
196/*!
197 * @function ipf_remove
198 * @discussion Detaches an IPv4 or IPv6 filter.
199 * @param filter_ref The reference to the filter returned from ipf_addv4 or
200 * ipf_addv6.
201 * @result 0 on success otherwise the errno error.
202 */
203extern errno_t ipf_remove(ipfilter_t filter_ref)
204__NKE_API_DEPRECATED;
205
206/*!
207 * @function ipf_inject_input
208 * @discussion Inject an IP packet as though it had just been
209 * reassembled in ip_input. When re-injecting a packet intercepted
210 * by the filter's ipf_input function, an IP filter can pass its
211 * reference to avoid processing the packet twice. This also
212 * prevents ip filters installed before this filter from
213 * getting a chance to process the packet. If the filter modified
214 * the packet, it should not specify the filter ref to give other
215 * filters a chance to process the new packet.
216 *
217 * Caller is responsible for freeing mbuf chain in the event that
218 * ipf_inject_input returns an error.
219 * @param data The complete IPv4 or IPv6 packet, receive interface must
220 * be set.
221 * @param filter_ref The reference to the filter injecting the data
222 * @result 0 on success otherwise the errno error.
223 */
224extern errno_t ipf_inject_input(mbuf_t data, ipfilter_t filter_ref)
225__NKE_API_DEPRECATED;
226
227/*!
228 * @function ipf_inject_output
229 * @discussion Inject an IP packet as though it had just been sent to
230 * ip_output. When re-injecting a packet intercepted by the
231 * filter's ipf_output function, an IP filter can pass its
232 * reference to avoid processing the packet twice. This also
233 * prevents ip filters installed before this filter from getting a
234 * chance to process the packet. If the filter modified the packet,
235 * it should not specify the filter ref to give other filters a
236 * chance to process the new packet.
237 * @param data The complete IPv4 or IPv6 packet.
238 * @param filter_ref The reference to the filter injecting the data
239 * @param options Output options for the packet
240 * @result 0 on success otherwise the errno error. ipf_inject_output
241 * will always free the mbuf.
242 */
243extern errno_t ipf_inject_output(mbuf_t data, ipfilter_t filter_ref,
244 ipf_pktopts_t options)
245__NKE_API_DEPRECATED;
246__END_DECLS
247#undef __NKE_API_DEPRECATED
248#endif /* __KPI_IPFILTER__ */
249