]>
Commit | Line | Data |
---|---|---|
9dc66a05 A |
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 | ||
40 | const char *ifname = NULL; | |
41 | unsigned int ifindex = 0; | |
42 | int do_get = 0; | |
43 | int num_filter_entries = 0; | |
44 | struct pktap_filter set_filter[PKTAP_MAX_FILTERS]; | |
45 | ||
46 | static const char *parameters_format = " %-24s %s\n"; | |
47 | ||
48 | static void | |
49 | usage(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 | ||
65 | static void | |
66 | print_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 | ||
75 | int 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 |