#ifndef __CONTENT_FILTER_H__
#define __CONTENT_FILTER_H__
#include <sys/param.h>
#include <sys/types.h>
#include <sys/_types/_timeval64.h>
#include <sys/socket.h>
#include <sys/syslog.h>
#include <netinet/in.h>
#include <stdint.h>
#ifdef BSD_KERNEL_PRIVATE
#include <sys/mbuf.h>
#include <sys/socketvar.h>
#endif
__BEGIN_DECLS
#ifdef PRIVATE
#define CONTENT_FILTER_CONTROL_NAME "com.apple.content-filter"
#define CFIL_OPT_NECP_CONTROL_UNIT 1
#define CFIL_MAX_FILTER_COUNT 2
#define CFM_TYPE_EVENT 1
#define CFM_TYPE_ACTION 2
#define CFM_OP_SOCKET_ATTACHED 1
#define CFM_OP_SOCKET_CLOSED 2
#define CFM_OP_DATA_OUT 3
#define CFM_OP_DATA_IN 4
#define CFM_OP_DISCONNECT_OUT 5
#define CFM_OP_DISCONNECT_IN 6
#define CFM_OP_DATA_UPDATE 16
#define CFM_OP_DROP 17
typedef uint64_t cfil_sock_id_t;
#define CFIL_SOCK_ID_NONE UINT64_MAX
struct cfil_msg_hdr {
uint32_t cfm_len;
uint32_t cfm_version;
uint32_t cfm_type;
uint32_t cfm_op;
cfil_sock_id_t cfm_sock_id;
};
#define CFM_VERSION_CURRENT 1
struct cfil_msg_sock_attached {
struct cfil_msg_hdr cfs_msghdr;
int cfs_sock_family;
int cfs_sock_type;
int cfs_sock_protocol;
int cfs_unused;
pid_t cfs_pid;
pid_t cfs_e_pid;
uuid_t cfs_uuid;
uuid_t cfs_e_uuid;
};
struct cfil_msg_data_event {
struct cfil_msg_hdr cfd_msghdr;
union sockaddr_in_4_6 cfc_src;
union sockaddr_in_4_6 cfc_dst;
uint64_t cfd_start_offset;
uint64_t cfd_end_offset;
};
struct cfil_msg_action {
struct cfil_msg_hdr cfa_msghdr;
uint64_t cfa_in_pass_offset;
uint64_t cfa_in_peek_offset;
uint64_t cfa_out_pass_offset;
uint64_t cfa_out_peek_offset;
};
#define CFM_MAX_OFFSET UINT64_MAX
struct cfil_filter_stat {
uint32_t cfs_len;
uint32_t cfs_filter_id;
uint32_t cfs_flags;
uint32_t cfs_sock_count;
uint32_t cfs_necp_control_unit;
};
struct cfil_entry_stat {
uint32_t ces_len;
uint32_t ces_filter_id;
uint32_t ces_flags;
uint32_t ces_necp_control_unit;
struct timeval64 ces_last_event;
struct timeval64 ces_last_action;
struct cfe_buf_stat {
uint64_t cbs_pending_first;
uint64_t cbs_pending_last;
uint64_t cbs_ctl_first;
uint64_t cbs_ctl_last;
uint64_t cbs_pass_offset;
uint64_t cbs_peek_offset;
uint64_t cbs_peeked;
} ces_snd, ces_rcv;
};
struct cfil_sock_stat {
uint32_t cfs_len;
int cfs_sock_family;
int cfs_sock_type;
int cfs_sock_protocol;
cfil_sock_id_t cfs_sock_id;
uint64_t cfs_flags;
pid_t cfs_pid;
pid_t cfs_e_pid;
uuid_t cfs_uuid;
uuid_t cfs_e_uuid;
struct cfi_buf_stat {
uint64_t cbs_pending_first;
uint64_t cbs_pending_last;
uint64_t cbs_pass_offset;
uint64_t cbs_inject_q_len;
} cfs_snd, cfs_rcv;
struct cfil_entry_stat ces_entries[CFIL_MAX_FILTER_COUNT];
};
struct cfil_stats {
int32_t cfs_ctl_connect_ok;
int32_t cfs_ctl_connect_fail;
int32_t cfs_ctl_disconnect_ok;
int32_t cfs_ctl_disconnect_fail;
int32_t cfs_ctl_send_ok;
int32_t cfs_ctl_send_bad;
int32_t cfs_ctl_rcvd_ok;
int32_t cfs_ctl_rcvd_bad;
int32_t cfs_ctl_rcvd_flow_lift;
int32_t cfs_ctl_action_data_update;
int32_t cfs_ctl_action_drop;
int32_t cfs_ctl_action_bad_op;
int32_t cfs_ctl_action_bad_len;
int32_t cfs_sock_id_not_found;
int32_t cfs_cfi_alloc_ok;
int32_t cfs_cfi_alloc_fail;
int32_t cfs_sock_userspace_only;
int32_t cfs_sock_attach_in_vain;
int32_t cfs_sock_attach_already;
int32_t cfs_sock_attach_no_mem;
int32_t cfs_sock_attach_failed;
int32_t cfs_sock_attached;
int32_t cfs_sock_detached;
int32_t cfs_attach_event_ok;
int32_t cfs_attach_event_flow_control;
int32_t cfs_attach_event_fail;
int32_t cfs_closed_event_ok;
int32_t cfs_closed_event_flow_control;
int32_t cfs_closed_event_fail;
int32_t cfs_data_event_ok;
int32_t cfs_data_event_flow_control;
int32_t cfs_data_event_fail;
int32_t cfs_disconnect_in_event_ok;
int32_t cfs_disconnect_out_event_ok;
int32_t cfs_disconnect_event_flow_control;
int32_t cfs_disconnect_event_fail;
int32_t cfs_ctl_q_not_started;
int32_t cfs_close_wait;
int32_t cfs_close_wait_timeout;
int32_t cfs_flush_in_drop;
int32_t cfs_flush_out_drop;
int32_t cfs_flush_in_close;
int32_t cfs_flush_out_close;
int32_t cfs_flush_in_free;
int32_t cfs_flush_out_free;
int32_t cfs_inject_q_nomem;
int32_t cfs_inject_q_nobufs;
int32_t cfs_inject_q_detached;
int32_t cfs_inject_q_in_fail;
int32_t cfs_inject_q_out_fail;
int32_t cfs_inject_q_in_retry;
int32_t cfs_inject_q_out_retry;
int32_t cfs_data_in_control;
int32_t cfs_data_in_oob;
int32_t cfs_data_out_control;
int32_t cfs_data_out_oob;
int64_t cfs_ctl_q_in_enqueued __attribute__((aligned(8)));
int64_t cfs_ctl_q_out_enqueued __attribute__((aligned(8)));
int64_t cfs_ctl_q_in_peeked __attribute__((aligned(8)));
int64_t cfs_ctl_q_out_peeked __attribute__((aligned(8)));
int64_t cfs_pending_q_in_enqueued __attribute__((aligned(8)));
int64_t cfs_pending_q_out_enqueued __attribute__((aligned(8)));
int64_t cfs_inject_q_in_enqueued __attribute__((aligned(8)));
int64_t cfs_inject_q_out_enqueued __attribute__((aligned(8)));
int64_t cfs_inject_q_in_passed __attribute__((aligned(8)));
int64_t cfs_inject_q_out_passed __attribute__((aligned(8)));
};
#endif
#ifdef BSD_KERNEL_PRIVATE
#define M_SKIPCFIL M_PROTO5
extern int cfil_log_level;
#define CFIL_LOG(level, fmt, ...) \
do { \
if (cfil_log_level >= level) \
printf("%s:%d " fmt "\n",\
__FUNCTION__, __LINE__, ##__VA_ARGS__); \
} while (0)
extern void cfil_init(void);
extern errno_t cfil_sock_attach(struct socket *so);
extern errno_t cfil_sock_detach(struct socket *so);
extern int cfil_sock_data_out(struct socket *so, struct sockaddr *to,
struct mbuf *data, struct mbuf *control,
uint32_t flags);
extern int cfil_sock_data_in(struct socket *so, struct sockaddr *from,
struct mbuf *data, struct mbuf *control,
uint32_t flags);
extern int cfil_sock_shutdown(struct socket *so, int *how);
extern void cfil_sock_is_closed(struct socket *so);
extern void cfil_sock_notify_shutdown(struct socket *so, int how);
extern void cfil_sock_close_wait(struct socket *so);
extern boolean_t cfil_sock_data_pending(struct sockbuf *sb);
extern int cfil_sock_data_space(struct sockbuf *sb);
extern void cfil_sock_buf_update(struct sockbuf *sb);
extern cfil_sock_id_t cfil_sock_id_from_socket(struct socket *so);
__END_DECLS
#endif
#endif