1/* 2 * Copyright (c) 2013-2014 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#include <sys/errno.h> 30#include <sys/sysctl.h> 31#include <net/content_filter.h> 32#include <stdio.h> 33#include <stdlib.h> 34#include <err.h> 35#include <unistd.h> 36#include <string.h> 37 38void 39print_filter_list() 40{ 41 size_t total_len, curr_len; 42 void *buffer = NULL; 43 void *ptr; 44 uint32_t line = 0; 45 46 if (sysctlbyname("net.cfil.filter_list", NULL, &total_len, NULL, 0) == -1) 47 err(1, "sysctlbyname(net.cfil.filter_list)"); 48 49 buffer = malloc(total_len); 50 if (buffer == NULL) 51 err(1, "malloc()"); 52 if (sysctlbyname("net.cfil.filter_list", buffer, &total_len, NULL, 0) == -1) 53 err(1, "sysctlbyname(net.cfil.filter_list)"); 54 55 ptr = buffer; 56 curr_len = 0; 57 do { 58 struct cfil_filter_stat *filter_stat; 59 60 filter_stat = (struct cfil_filter_stat *)ptr; 61 62 if (curr_len + filter_stat->cfs_len > total_len || 63 filter_stat->cfs_len < sizeof(struct cfil_filter_stat)) 64 break; 65 66 if (line % 16 == 0) 67 printf("%10s %10s %10s %10s\n", 68 "filter", "flags", "count", "necpunit"); 69 70 printf("%10u 0x%08x %10u %10u\n", 71 filter_stat->cfs_filter_id, 72 filter_stat->cfs_flags, 73 filter_stat->cfs_sock_count, 74 filter_stat->cfs_necp_control_unit); 75 76 ptr += filter_stat->cfs_len; 77 curr_len += filter_stat->cfs_len; 78 } while (1); 79 80 free(buffer); 81} 82 83void 84sprint_offset(char *str, size_t len, const char *fmt, uint64_t offset) 85{ 86 if (offset == CFM_MAX_OFFSET) 87 snprintf(str, len, "%s", "MAX"); 88 else 89 snprintf(str, len, fmt, offset); 90} 91 92void 93print_socket_list() 94{ 95 size_t total_len, curr_len; 96 void *buffer = NULL; 97 void *ptr; 98 int i; 99 100 if (sysctlbyname("net.cfil.sock_list", NULL, &total_len, NULL, 0) == -1) 101 err(1, "sysctlbyname(net.cfil.sock_list)"); 102 103 buffer = malloc(total_len); 104 if (buffer == NULL) 105 err(1, "malloc()"); 106 if (sysctlbyname("net.cfil.sock_list", buffer, &total_len, NULL, 0) == -1) 107 err(1, "sysctlbyname(net.cfil.sock_list)"); 108 109 ptr = buffer; 110 curr_len = 0; 111 do { 112 struct cfil_sock_stat *sock_stat; 113 char opass[32]; 114 char ipass[32]; 115 116 sock_stat = (struct cfil_sock_stat *)ptr; 117 118 if (curr_len + sock_stat->cfs_len > total_len || 119 sock_stat->cfs_len < sizeof(struct cfil_sock_stat)) 120 break; 121 122 sprint_offset(opass, 32, "%8llu", sock_stat->cfs_snd.cbs_pass_offset); 123 sprint_offset(ipass, 32, "%8llu", sock_stat->cfs_rcv.cbs_pass_offset); 124 125 printf("%18s %10s " 126 "%8s %8s %8s %8s %8s %8s %8s " 127 "%8s %8s %8s %8s %8s %8s %8s " 128 "%8s %8s\n", 129 "sockid", "flags", 130 "ofirst", "olast", "oqlen", " ", "opass", " ", " ", 131 "ifirst", "ilast", "iqlen", " ", "ipass", " ", " ", 132 "pid", "epid"); 133 134 printf("0x%016llx 0x%08llx " 135 "%8llu %8llu %8llu %8s %8s %8s %8s " 136 "%8llu %8llu %8llu %8s %8s %8s %8s " 137 "%8u %8u\n", 138 139 sock_stat->cfs_sock_id, 140 sock_stat->cfs_flags, 141 142 sock_stat->cfs_snd.cbs_pending_first, 143 sock_stat->cfs_snd.cbs_pending_last, 144 sock_stat->cfs_snd.cbs_inject_q_len, 145 " ", 146 opass, 147 " ", 148 " ", 149 150 sock_stat->cfs_rcv.cbs_pending_first, 151 sock_stat->cfs_rcv.cbs_pending_last, 152 sock_stat->cfs_rcv.cbs_inject_q_len, 153 " ", 154 ipass, 155 " ", 156 " ", 157 sock_stat->cfs_pid, 158 sock_stat->cfs_e_pid); 159 160 printf("%7s %10s %10s " 161 "%8s %8s %8s %8s %8s %8s %8s " 162 "%8s %8s %8s %8s %8s %8s %8s\n", 163 " ", 164 "filter", "flags", 165 "octlfrst", "octllast", "opndfrst", "opndlast", "opass", "opked", "opeek", 166 "ictlfrst", "ictllast", "ipndfrst", "ipndlast", "ipass", "ipked", "ipeek"); 167 for (i = 0; i < CFIL_MAX_FILTER_COUNT; i++) { 168 struct cfil_entry_stat *estat; 169 char spass[32]; 170 char speek[32]; 171 char spked[32]; 172 char rpass[32]; 173 char rpeek[32]; 174 char rpked[32]; 175 176 estat = &sock_stat->ces_entries[i]; 177 178 sprint_offset(spass, 32, "%8llu", estat->ces_snd.cbs_pass_offset); 179 sprint_offset(speek, 32, "%8llu", estat->ces_snd.cbs_peek_offset); 180 sprint_offset(spked, 32, "%8llu", estat->ces_snd.cbs_peeked); 181 182 sprint_offset(rpass, 32, "%8llu", estat->ces_rcv.cbs_pass_offset); 183 sprint_offset(rpeek, 32, "%8llu", estat->ces_rcv.cbs_peek_offset); 184 sprint_offset(rpked, 32, "%8llu", estat->ces_rcv.cbs_peeked); 185 186 printf("%7s %10u 0x%08x " 187 "%8llu %8llu %8llu %8llu %8s %8s %8s " 188 "%8llu %8llu %8llu %8llu %8s %8s %8s\n", 189 190 " ", 191 estat->ces_filter_id, 192 estat->ces_flags, 193 194 estat->ces_snd.cbs_ctl_first, 195 estat->ces_snd.cbs_ctl_last, 196 estat->ces_snd.cbs_pending_first, 197 estat->ces_snd.cbs_pending_last, 198 spass, 199 spked, 200 speek, 201 202 estat->ces_rcv.cbs_ctl_first, 203 estat->ces_rcv.cbs_ctl_last, 204 estat->ces_rcv.cbs_pending_first, 205 estat->ces_rcv.cbs_pending_last, 206 rpass, 207 rpked, 208 rpeek); 209 } 210 211 212 ptr += sock_stat->cfs_len; 213 curr_len += sock_stat->cfs_len; 214 } while (1); 215 216 free(buffer); 217} 218 219 220#define PR32(x) printf(#x " %u\n", stats-> x) 221#define PR64(x) printf(#x " %llu\n", stats-> x) 222void 223print_cfil_stats() 224{ 225 size_t len, alloc_len; 226 void *buffer = NULL; 227 struct cfil_stats *stats; 228 229 if (sysctlbyname("net.cfil.stats", NULL, &len, NULL, 0) == -1) 230 err(1, "sysctlbyname(net.cfil.stats)"); 231 232 if (len < sizeof(struct cfil_stats)) 233 alloc_len = sizeof(struct cfil_stats); 234 else 235 alloc_len = len; 236 237 buffer = malloc(alloc_len); 238 if (buffer == NULL) 239 err(1, "malloc()"); 240 if (sysctlbyname("net.cfil.stats", buffer, &len, NULL, 0) == -1) 241 err(1, "sysctlbyname(net.cfil.stats)"); 242 stats = (struct cfil_stats *)buffer; 243 244 PR32(cfs_ctl_connect_ok); 245 PR32(cfs_ctl_connect_fail); 246 PR32(cfs_ctl_connect_ok); 247 PR32(cfs_ctl_connect_fail); 248 PR32(cfs_ctl_disconnect_ok); 249 PR32(cfs_ctl_disconnect_fail); 250 PR32(cfs_ctl_send_ok); 251 PR32(cfs_ctl_send_bad); 252 PR32(cfs_ctl_rcvd_ok); 253 PR32(cfs_ctl_rcvd_bad); 254 PR32(cfs_ctl_rcvd_flow_lift); 255 PR32(cfs_ctl_action_data_update); 256 PR32(cfs_ctl_action_drop); 257 PR32(cfs_ctl_action_bad_op); 258 PR32(cfs_ctl_action_bad_len); 259 260 PR32(cfs_sock_id_not_found); 261 262 PR32(cfs_cfi_alloc_ok); 263 PR32(cfs_cfi_alloc_fail); 264 265 PR32(cfs_sock_userspace_only); 266 PR32(cfs_sock_attach_in_vain); 267 PR32(cfs_sock_attach_already); 268 PR32(cfs_sock_attach_no_mem); 269 PR32(cfs_sock_attach_failed); 270 PR32(cfs_sock_attached); 271 PR32(cfs_sock_detached); 272 273 PR32(cfs_attach_event_ok); 274 PR32(cfs_attach_event_flow_control); 275 PR32(cfs_attach_event_fail); 276 277 PR32(cfs_closed_event_ok); 278 PR32(cfs_closed_event_flow_control); 279 PR32(cfs_closed_event_fail); 280 281 PR32(cfs_data_event_ok); 282 PR32(cfs_data_event_flow_control); 283 PR32(cfs_data_event_fail); 284 285 PR32(cfs_disconnect_in_event_ok); 286 PR32(cfs_disconnect_out_event_ok); 287 PR32(cfs_disconnect_event_flow_control); 288 PR32(cfs_disconnect_event_fail); 289 290 PR32(cfs_ctl_q_not_started); 291 292 PR32(cfs_close_wait); 293 PR32(cfs_close_wait_timeout); 294 295 PR32(cfs_flush_in_drop); 296 PR32(cfs_flush_out_drop); 297 PR32(cfs_flush_in_close); 298 PR32(cfs_flush_out_close); 299 PR32(cfs_flush_in_free); 300 PR32(cfs_flush_out_free); 301 302 PR32(cfs_inject_q_nomem); 303 PR32(cfs_inject_q_nobufs); 304 PR32(cfs_inject_q_detached); 305 PR32(cfs_inject_q_in_fail); 306 PR32(cfs_inject_q_out_fail); 307 308 PR32(cfs_inject_q_in_retry); 309 PR32(cfs_inject_q_out_retry); 310 311 PR32(cfs_data_in_control); 312 PR32(cfs_data_in_oob); 313 PR32(cfs_data_out_control); 314 PR32(cfs_data_out_oob); 315 316 PR64(cfs_ctl_q_in_enqueued); 317 PR64(cfs_ctl_q_out_enqueued); 318 PR64(cfs_ctl_q_in_peeked); 319 PR64(cfs_ctl_q_out_peeked); 320 321 PR64(cfs_pending_q_in_enqueued); 322 PR64(cfs_pending_q_out_enqueued); 323 324 PR64(cfs_inject_q_in_enqueued); 325 PR64(cfs_inject_q_out_enqueued); 326 PR64(cfs_inject_q_in_passed); 327 PR64(cfs_inject_q_out_passed); 328} 329