1/* 2 * Copyright (c) 2012 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/types.h> 30#include <sys/socket.h> 31#include <sys/sockio.h> 32#include <sys/ioctl.h> 33#include <net/pktap.h> 34#include <stdio.h> 35#include <unistd.h> 36#include <err.h> 37#include <stdlib.h> 38#include <string.h> 39 40const char *ifname = NULL; 41unsigned int ifindex = 0; 42int do_get = 0; 43int num_filter_entries = 0; 44struct pktap_filter set_filter[PKTAP_MAX_FILTERS]; 45 46static const char *parameters_format = " %-24s %s\n"; 47 48static void 49usage(const char *s) 50{ 51 printf("# usage: %s -i <ifname> -g -p <filter_rule> -s <filter_rule> -h\n", s); 52 printf(" Get or set filtering rules on a pktap interface\n"); 53 printf(" Options:\n"); 54 printf(parameters_format, "-h", "display this help"); 55 printf(parameters_format, "-i <ifname>", "name pktap interface"); 56 printf(parameters_format, "-g", "get filter rules"); 57 printf(parameters_format, "-p <filter_rule> param", "add a pass rule"); 58 printf(parameters_format, "-s <filter_rule> param", "add a skip rule"); 59 printf(" Format of <filter_rule> parameter:\n"); 60 printf(parameters_format, "type <iftype>", "interfaces of given type"); 61 printf(parameters_format, "", "use 0 for any interface type"); 62 printf(parameters_format, "name <ifname>", "interface of given name"); 63} 64 65static void 66print_filter_entry(struct pktap_filter *filter) 67{ 68 printf("filter_op: %u filter_param %u ", filter->filter_op, filter->filter_param); 69 if (filter->filter_param == PKTAP_FILTER_PARAM_IF_TYPE) 70 printf("%u", filter->filter_param_if_type); 71 else if (filter->filter_param == PKTAP_FILTER_PARAM_IF_NAME) 72 printf("%s", filter->filter_param_if_name); 73} 74 75int main(int argc, char * const argv[]) 76{ 77 int ch; 78 struct ifdrv ifdr; 79 int fd = -1; 80 int i; 81 82 //printf("sizeof(struct pktap_filter) %lu\n", sizeof(struct pktap_filter)); 83 //printf("sizeof(pktap_filter) %lu\n", sizeof(set_filter)); 84 85 while ((ch = getopt(argc, argv, "ghi:p:s:")) != -1) { 86 switch (ch) { 87 case 'g': 88 do_get++; 89 break; 90 91 case 'h': 92 usage(argv[0]); 93 exit(0); 94 /* NOT REACHED */ 95 96 case 'i': 97 ifname = optarg; 98 99 ifindex = if_nametoindex(ifname); 100 if (ifindex == 0) 101 err(1, "if_nametoindex(%s) failed", ifname); 102 103 break; 104 105 case 'p': 106 case 's': { 107 /* -p (type|name) <value> */ 108 struct pktap_filter entry; 109 110 if (num_filter_entries >= PKTAP_MAX_FILTERS) 111 errx(1, "Too many filter entries, max is %u", PKTAP_MAX_FILTERS); 112 if (optind + 1 > argc) 113 errx(1, "-%c needs two arguments optind %d argc %d", ch, optind, argc); 114 if (ch == 'p') 115 entry.filter_op = PKTAP_FILTER_OP_PASS; 116 else 117 entry.filter_op = PKTAP_FILTER_OP_SKIP; 118 if (strcmp(optarg, "type") == 0) { 119 entry.filter_param = PKTAP_FILTER_PARAM_IF_TYPE; 120 entry.filter_param_if_type = (uint32_t)strtoul(argv[optind], NULL, 0); 121 } else if (strcmp(optarg, "name") == 0) { 122 entry.filter_param = PKTAP_FILTER_PARAM_IF_NAME; 123 snprintf(entry.filter_param_if_name, sizeof(entry.filter_param_if_name), "%s", argv[optind]); 124 } else 125 errx(1, "syntax error -p %s", optarg); 126 printf("Addin entry: "); 127 print_filter_entry(&entry); 128 printf("\n"); 129 set_filter[num_filter_entries] = entry; 130 131 num_filter_entries++; 132 optind++; 133 break; 134 } 135 136 case '?': 137 default: 138 err(1, "syntax error"); 139 exit(0); 140 /* NOT REACHED */ 141 } 142 } 143 if (ifname == NULL) 144 errx(1, "missing interface"); 145 146 fd = socket(PF_INET, SOCK_DGRAM, 0); 147 if (fd == -1) 148 err(1, "socket(PF_INET, SOCK_DGRAM, 0)"); 149 150 if (num_filter_entries > 0) { 151 for (i = num_filter_entries; i < PKTAP_MAX_FILTERS; i++) { 152 struct pktap_filter *filter = set_filter + i; 153 filter->filter_op = PKTAP_FILTER_OP_NONE; 154 filter->filter_param = PKTAP_FILTER_PARAM_NONE; 155 } 156 157 snprintf(ifdr.ifd_name, sizeof(ifdr.ifd_name), "%s", ifname); 158 ifdr.ifd_cmd = PKTP_CMD_FILTER_SET; 159 ifdr.ifd_len = sizeof(set_filter); 160 ifdr.ifd_data = &set_filter[0]; 161 162 if (ioctl(fd, SIOCSDRVSPEC, &ifdr) == -1) 163 err(1, "ioctl(SIOCSDRVSPEC)"); 164 165 } 166 167 if (do_get) { 168 struct pktap_filter get_filter[PKTAP_MAX_FILTERS]; 169 170 snprintf(ifdr.ifd_name, sizeof(ifdr.ifd_name), "%s", ifname); 171 ifdr.ifd_cmd = PKTP_CMD_FILTER_GET; 172 ifdr.ifd_len = sizeof(get_filter); 173 ifdr.ifd_data = &get_filter[0]; 174 175 if (ioctl(fd, SIOCGDRVSPEC, &ifdr) == -1) 176 err(1, "ioctl(SIOCGDRVSPEC)"); 177 178 for (i = 0; i < PKTAP_MAX_FILTERS; i++) { 179 struct pktap_filter *filter = get_filter + i; 180 181 printf("[%d] ", i); 182 print_filter_entry(filter); 183 printf("\n"); 184 } 185 } 186 187 return 0; 188} 189 190