1 /*
2 Copyright (c) 2013-2016, The Linux Foundation. All rights reserved.
3 
4 Redistribution and use in source and binary forms, with or without
5 modification, are permitted provided that the following conditions are
6 met:
7 		* Redistributions of source code must retain the above copyright
8 			notice, this list of conditions and the following disclaimer.
9 		* Redistributions in binary form must reproduce the above
10 			copyright notice, this list of conditions and the following
11 			disclaimer in the documentation and/or other materials provided
12 			with the distribution.
13 		* Neither the name of The Linux Foundation nor the names of its
14 			contributors may be used to endorse or promote products derived
15 			from this software without specific prior written permission.
16 
17 THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
18 WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
19 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
20 ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
21 BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23 SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
24 BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
25 WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
26 OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
27 IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 */
29 /*!
30 	@file
31 	IPACM_Filtering.cpp
32 
33 	@brief
34 	This file implements the IPACM filtering functionality.
35 
36 	@Author
37 	Skylar Chang
38 
39 */
40 #include <unistd.h>
41 #include <sys/ioctl.h>
42 #include <fcntl.h>
43 #include <stdio.h>
44 #include <stdlib.h>
45 
46 #include "IPACM_Filtering.h"
47 #include <IPACM_Log.h>
48 #include "IPACM_Defs.h"
49 
50 
51 const char *IPACM_Filtering::DEVICE_NAME = "/dev/ipa";
52 
IPACM_Filtering()53 IPACM_Filtering::IPACM_Filtering()
54 {
55 	fd = open(DEVICE_NAME, O_RDWR);
56 	if (fd < 0)
57 	{
58 		IPACMERR("Failed opening %s.\n", DEVICE_NAME);
59 	}
60 }
61 
~IPACM_Filtering()62 IPACM_Filtering::~IPACM_Filtering()
63 {
64 	close(fd);
65 }
66 
DeviceNodeIsOpened()67 bool IPACM_Filtering::DeviceNodeIsOpened()
68 {
69 	return fd;
70 }
71 
AddFilteringRule(struct ipa_ioc_add_flt_rule const * ruleTable)72 bool IPACM_Filtering::AddFilteringRule(struct ipa_ioc_add_flt_rule const *ruleTable)
73 {
74 	int retval = 0;
75 
76 	IPACMDBG("Printing filter add attributes\n");
77 	IPACMDBG("ip type: %d\n", ruleTable->ip);
78 	IPACMDBG("Number of rules: %d\n", ruleTable->num_rules);
79 	IPACMDBG("End point: %d and global value: %d\n", ruleTable->ep, ruleTable->global);
80 	IPACMDBG("commit value: %d\n", ruleTable->commit);
81 	for (int cnt=0; cnt<ruleTable->num_rules; cnt++)
82 	{
83 		IPACMDBG("Filter rule:%d attrib mask: 0x%x\n", cnt,
84 				ruleTable->rules[cnt].rule.attrib.attrib_mask);
85 	}
86 
87 	retval = ioctl(fd, IPA_IOC_ADD_FLT_RULE, ruleTable);
88 	if (retval != 0)
89 	{
90 		IPACMERR("Failed adding Filtering rule %p\n", ruleTable);
91 		PERROR("unable to add filter rule:");
92 
93 		for (int cnt = 0; cnt < ruleTable->num_rules; cnt++)
94 		{
95 			if (ruleTable->rules[cnt].status != 0)
96 			{
97 				IPACMERR("Adding Filter rule:%d failed with status:%d\n",
98 								 cnt, ruleTable->rules[cnt].status);
99 			}
100 		}
101 		return false;
102 	}
103 
104 	for (int cnt = 0; cnt<ruleTable->num_rules; cnt++)
105 	{
106 		if(ruleTable->rules[cnt].status != 0)
107 		{
108 			IPACMERR("Adding Filter rule:%d failed with status:%d\n",
109 							 cnt, ruleTable->rules[cnt].status);
110 		}
111 	}
112 
113 	IPACMDBG("Added Filtering rule %p\n", ruleTable);
114 	return true;
115 }
116 
AddFilteringRuleAfter(struct ipa_ioc_add_flt_rule_after const * ruleTable)117 bool IPACM_Filtering::AddFilteringRuleAfter(struct ipa_ioc_add_flt_rule_after const *ruleTable)
118 {
119 #ifdef FEATURE_IPA_V3
120 	int retval = 0;
121 
122 	IPACMDBG("Printing filter add attributes\n");
123 	IPACMDBG("ip type: %d\n", ruleTable->ip);
124 	IPACMDBG("Number of rules: %d\n", ruleTable->num_rules);
125 	IPACMDBG("End point: %d\n", ruleTable->ep);
126 	IPACMDBG("commit value: %d\n", ruleTable->commit);
127 
128 	retval = ioctl(fd, IPA_IOC_ADD_FLT_RULE_AFTER, ruleTable);
129 
130 	for (int cnt = 0; cnt<ruleTable->num_rules; cnt++)
131 	{
132 		if(ruleTable->rules[cnt].status != 0)
133 		{
134 			IPACMERR("Adding Filter rule:%d failed with status:%d\n",
135 							 cnt, ruleTable->rules[cnt].status);
136 		}
137 	}
138 
139 	if (retval != 0)
140 	{
141 		IPACMERR("Failed adding Filtering rule %p\n", ruleTable);
142 		return false;
143 	}
144 	IPACMDBG("Added Filtering rule %p\n", ruleTable);
145 #endif
146 	return true;
147 }
148 
DeleteFilteringRule(struct ipa_ioc_del_flt_rule * ruleTable)149 bool IPACM_Filtering::DeleteFilteringRule(struct ipa_ioc_del_flt_rule *ruleTable)
150 {
151 	int retval = 0;
152 
153 	retval = ioctl(fd, IPA_IOC_DEL_FLT_RULE, ruleTable);
154 	if (retval != 0)
155 	{
156 		IPACMERR("Failed deleting Filtering rule %p\n", ruleTable);
157 		return false;
158 	}
159 
160 	IPACMDBG("Deleted Filtering rule %p\n", ruleTable);
161 	return true;
162 }
163 
Commit(enum ipa_ip_type ip)164 bool IPACM_Filtering::Commit(enum ipa_ip_type ip)
165 {
166 	int retval = 0;
167 
168 	retval = ioctl(fd, IPA_IOC_COMMIT_FLT, ip);
169 	if (retval != 0)
170 	{
171 		IPACMERR("failed committing Filtering rules.\n");
172 		return false;
173 	}
174 
175 	IPACMDBG("Committed Filtering rules to IPA HW.\n");
176 	return true;
177 }
178 
Reset(enum ipa_ip_type ip)179 bool IPACM_Filtering::Reset(enum ipa_ip_type ip)
180 {
181 	int retval = 0;
182 
183 	retval = ioctl(fd, IPA_IOC_RESET_FLT, ip);
184 	retval |= ioctl(fd, IPA_IOC_COMMIT_FLT, ip);
185 	if (retval)
186 	{
187 		IPACMERR("failed resetting Filtering block.\n");
188 		return false;
189 	}
190 
191 	IPACMDBG("Reset command issued to IPA Filtering block.\n");
192 	return true;
193 }
194 
DeleteFilteringHdls(uint32_t * flt_rule_hdls,ipa_ip_type ip,uint8_t num_rules)195 bool IPACM_Filtering::DeleteFilteringHdls
196 (
197 	 uint32_t *flt_rule_hdls,
198 	 ipa_ip_type ip,
199 	 uint8_t num_rules
200 )
201 {
202 	struct ipa_ioc_del_flt_rule *flt_rule;
203 	bool res = true;
204 	int len = 0, cnt = 0;
205         const uint8_t UNIT_RULES = 1;
206 
207 	len = (sizeof(struct ipa_ioc_del_flt_rule)) + (UNIT_RULES * sizeof(struct ipa_flt_rule_del));
208 	flt_rule = (struct ipa_ioc_del_flt_rule *)malloc(len);
209 	if (flt_rule == NULL)
210 	{
211 		IPACMERR("unable to allocate memory for del filter rule\n");
212 		return false;
213 	}
214 
215 	for (cnt = 0; cnt < num_rules; cnt++)
216 	{
217 	    memset(flt_rule, 0, len);
218 	    flt_rule->commit = 1;
219 	    flt_rule->num_hdls = UNIT_RULES;
220 	    flt_rule->ip = ip;
221 
222 	    if (flt_rule_hdls[cnt] == 0)
223 	    {
224 		   IPACMERR("invalid filter handle passed, ignoring it: %d\n", cnt)
225 	    }
226             else
227 	    {
228 
229 		   flt_rule->hdl[0].status = -1;
230 		   flt_rule->hdl[0].hdl = flt_rule_hdls[cnt];
231 		   IPACMDBG("Deleting filter hdl:(0x%x) with ip type: %d\n", flt_rule_hdls[cnt], ip);
232 
233 	           if (DeleteFilteringRule(flt_rule) == false)
234 	           {
235 		        PERROR("Filter rule deletion failed!\n");
236 		        res = false;
237 		        goto fail;
238 	           }
239 		   else
240 	           {
241 
242 		        if (flt_rule->hdl[0].status != 0)
243 		        {
244 			     IPACMERR("Filter rule hdl 0x%x deletion failed with error:%d\n",
245 		        					 flt_rule->hdl[0].hdl, flt_rule->hdl[0].status);
246 			     res = false;
247 			     goto fail;
248 		        }
249 		   }
250 	    }
251 	}
252 
253 fail:
254 	free(flt_rule);
255 
256 	return res;
257 }
258 
AddWanDLFilteringRule(struct ipa_ioc_add_flt_rule const * rule_table_v4,struct ipa_ioc_add_flt_rule const * rule_table_v6,uint8_t mux_id)259 bool IPACM_Filtering::AddWanDLFilteringRule(struct ipa_ioc_add_flt_rule const *rule_table_v4, struct ipa_ioc_add_flt_rule const * rule_table_v6, uint8_t mux_id)
260 {
261 	int ret = 0, cnt, num_rules = 0, pos = 0;
262 	ipa_install_fltr_rule_req_msg_v01 qmi_rule_msg;
263 #ifdef FEATURE_IPA_V3
264 	ipa_install_fltr_rule_req_ex_msg_v01 qmi_rule_ex_msg;
265 #endif
266 
267 	memset(&qmi_rule_msg, 0, sizeof(qmi_rule_msg));
268 	int fd_wwan_ioctl = open(WWAN_QMI_IOCTL_DEVICE_NAME, O_RDWR);
269 	if(fd_wwan_ioctl < 0)
270 	{
271 		IPACMERR("Failed to open %s.\n",WWAN_QMI_IOCTL_DEVICE_NAME);
272 		return false;
273 	}
274 
275 	if(rule_table_v4 != NULL)
276 	{
277 		num_rules += rule_table_v4->num_rules;
278 		IPACMDBG_H("Get %d WAN DL IPv4 filtering rules.\n", rule_table_v4->num_rules);
279 	}
280 	if(rule_table_v6 != NULL)
281 	{
282 		num_rules += rule_table_v6->num_rules;
283 		IPACMDBG_H("Get %d WAN DL IPv6 filtering rules.\n", rule_table_v6->num_rules);
284 	}
285 
286 	/* if it is not IPA v3, use old QMI format */
287 #ifndef FEATURE_IPA_V3
288 	if(num_rules > QMI_IPA_MAX_FILTERS_V01)
289 	{
290 		IPACMERR("The number of filtering rules exceed limit.\n");
291 		close(fd_wwan_ioctl);
292 		return false;
293 	}
294 	else
295 	{
296 		if (num_rules > 0)
297 		{
298 			qmi_rule_msg.filter_spec_list_valid = true;
299 		}
300 		else
301 		{
302 			qmi_rule_msg.filter_spec_list_valid = false;
303 		}
304 
305 		qmi_rule_msg.filter_spec_list_len = num_rules;
306 		qmi_rule_msg.source_pipe_index_valid = 0;
307 
308 		IPACMDBG_H("Get %d WAN DL filtering rules in total.\n", num_rules);
309 
310 		if(rule_table_v4 != NULL)
311 		{
312 			for(cnt = rule_table_v4->num_rules - 1; cnt >= 0; cnt--)
313 			{
314 				if (pos < QMI_IPA_MAX_FILTERS_V01)
315 				{
316 					qmi_rule_msg.filter_spec_list[pos].filter_spec_identifier = pos;
317 					qmi_rule_msg.filter_spec_list[pos].ip_type = QMI_IPA_IP_TYPE_V4_V01;
318 					qmi_rule_msg.filter_spec_list[pos].filter_action = GetQmiFilterAction(rule_table_v4->rules[cnt].rule.action);
319 					qmi_rule_msg.filter_spec_list[pos].is_routing_table_index_valid = 1;
320 					qmi_rule_msg.filter_spec_list[pos].route_table_index = rule_table_v4->rules[cnt].rule.rt_tbl_idx;
321 					qmi_rule_msg.filter_spec_list[pos].is_mux_id_valid = 1;
322 					qmi_rule_msg.filter_spec_list[pos].mux_id = mux_id;
323 					memcpy(&qmi_rule_msg.filter_spec_list[pos].filter_rule,
324 						&rule_table_v4->rules[cnt].rule.eq_attrib,
325 						sizeof(struct ipa_filter_rule_type_v01));
326 					pos++;
327 				}
328 				else
329 				{
330 					IPACMERR(" QMI only support max %d rules, current (%d)\n ",QMI_IPA_MAX_FILTERS_V01, pos);
331 				}
332 			}
333 		}
334 
335 		if(rule_table_v6 != NULL)
336 		{
337 			for(cnt = rule_table_v6->num_rules - 1; cnt >= 0; cnt--)
338 			{
339 				if (pos < QMI_IPA_MAX_FILTERS_V01)
340 				{
341 					qmi_rule_msg.filter_spec_list[pos].filter_spec_identifier = pos;
342 					qmi_rule_msg.filter_spec_list[pos].ip_type = QMI_IPA_IP_TYPE_V6_V01;
343 					qmi_rule_msg.filter_spec_list[pos].filter_action = GetQmiFilterAction(rule_table_v6->rules[cnt].rule.action);
344 					qmi_rule_msg.filter_spec_list[pos].is_routing_table_index_valid = 1;
345 					qmi_rule_msg.filter_spec_list[pos].route_table_index = rule_table_v6->rules[cnt].rule.rt_tbl_idx;
346 					qmi_rule_msg.filter_spec_list[pos].is_mux_id_valid = 1;
347 					qmi_rule_msg.filter_spec_list[pos].mux_id = mux_id;
348 					memcpy(&qmi_rule_msg.filter_spec_list[pos].filter_rule,
349 						&rule_table_v6->rules[cnt].rule.eq_attrib,
350 						sizeof(struct ipa_filter_rule_type_v01));
351 					pos++;
352 				}
353 				else
354 				{
355 					IPACMERR(" QMI only support max %d rules, current (%d)\n ",QMI_IPA_MAX_FILTERS_V01, pos);
356 				}
357 			}
358 		}
359 
360 		ret = ioctl(fd_wwan_ioctl, WAN_IOC_ADD_FLT_RULE, &qmi_rule_msg);
361 		if (ret != 0)
362 		{
363 			IPACMERR("Failed adding Filtering rule %p with ret %d\n ", &qmi_rule_msg, ret);
364 			close(fd_wwan_ioctl);
365 			return false;
366 		}
367 	}
368 	/* if it is IPA v3, use new QMI format */
369 #else
370 	if(num_rules > QMI_IPA_MAX_FILTERS_EX_V01)
371 	{
372 		IPACMERR("The number of filtering rules exceed limit.\n");
373 		close(fd_wwan_ioctl);
374 		return false;
375 	}
376 	else
377 	{
378 		memset(&qmi_rule_ex_msg, 0, sizeof(qmi_rule_ex_msg));
379 
380 		if (num_rules > 0)
381 		{
382 			qmi_rule_ex_msg.filter_spec_ex_list_valid = true;
383 		}
384 		else
385 		{
386 			qmi_rule_ex_msg.filter_spec_ex_list_valid = false;
387 		}
388 		qmi_rule_ex_msg.filter_spec_ex_list_len = num_rules;
389 		qmi_rule_ex_msg.source_pipe_index_valid = 0;
390 
391 		IPACMDBG_H("Get %d WAN DL filtering rules in total.\n", num_rules);
392 
393 		if(rule_table_v4 != NULL)
394 		{
395 			for(cnt = rule_table_v4->num_rules - 1; cnt >= 0; cnt--)
396 			{
397 				if (pos < QMI_IPA_MAX_FILTERS_EX_V01)
398 				{
399 					qmi_rule_ex_msg.filter_spec_ex_list[pos].ip_type = QMI_IPA_IP_TYPE_V4_V01;
400 					qmi_rule_ex_msg.filter_spec_ex_list[pos].filter_action = GetQmiFilterAction(rule_table_v4->rules[cnt].rule.action);
401 					qmi_rule_ex_msg.filter_spec_ex_list[pos].is_routing_table_index_valid = 1;
402 					qmi_rule_ex_msg.filter_spec_ex_list[pos].route_table_index = rule_table_v4->rules[cnt].rule.rt_tbl_idx;
403 					qmi_rule_ex_msg.filter_spec_ex_list[pos].is_mux_id_valid = 1;
404 					qmi_rule_ex_msg.filter_spec_ex_list[pos].mux_id = mux_id;
405 					qmi_rule_ex_msg.filter_spec_ex_list[pos].rule_id = rule_table_v4->rules[cnt].rule.rule_id;
406 					qmi_rule_ex_msg.filter_spec_ex_list[pos].is_rule_hashable = rule_table_v4->rules[cnt].rule.hashable;
407 					memcpy(&qmi_rule_ex_msg.filter_spec_ex_list[pos].filter_rule,
408 						&rule_table_v4->rules[cnt].rule.eq_attrib,
409 						sizeof(struct ipa_filter_rule_type_v01));
410 
411 					pos++;
412 				}
413 				else
414 				{
415 					IPACMERR(" QMI only support max %d rules, current (%d)\n ",QMI_IPA_MAX_FILTERS_EX_V01, pos);
416 				}
417 			}
418 		}
419 
420 		if(rule_table_v6 != NULL)
421 		{
422 			for(cnt = rule_table_v6->num_rules - 1; cnt >= 0; cnt--)
423 			{
424 				if (pos < QMI_IPA_MAX_FILTERS_EX_V01)
425 				{
426 					qmi_rule_ex_msg.filter_spec_ex_list[pos].ip_type = QMI_IPA_IP_TYPE_V6_V01;
427 					qmi_rule_ex_msg.filter_spec_ex_list[pos].filter_action = GetQmiFilterAction(rule_table_v6->rules[cnt].rule.action);
428 					qmi_rule_ex_msg.filter_spec_ex_list[pos].is_routing_table_index_valid = 1;
429 					qmi_rule_ex_msg.filter_spec_ex_list[pos].route_table_index = rule_table_v6->rules[cnt].rule.rt_tbl_idx;
430 					qmi_rule_ex_msg.filter_spec_ex_list[pos].is_mux_id_valid = 1;
431 					qmi_rule_ex_msg.filter_spec_ex_list[pos].mux_id = mux_id;
432 					qmi_rule_ex_msg.filter_spec_ex_list[pos].rule_id = rule_table_v6->rules[cnt].rule.rule_id;
433 					qmi_rule_ex_msg.filter_spec_ex_list[pos].is_rule_hashable = rule_table_v6->rules[cnt].rule.hashable;
434 					memcpy(&qmi_rule_ex_msg.filter_spec_ex_list[pos].filter_rule,
435 						&rule_table_v6->rules[cnt].rule.eq_attrib,
436 						sizeof(struct ipa_filter_rule_type_v01));
437 
438 					pos++;
439 				}
440 				else
441 				{
442 					IPACMERR(" QMI only support max %d rules, current (%d)\n ",QMI_IPA_MAX_FILTERS_EX_V01, pos);
443 				}
444 			}
445 		}
446 
447 		ret = ioctl(fd_wwan_ioctl, WAN_IOC_ADD_FLT_RULE_EX, &qmi_rule_ex_msg);
448 		if (ret != 0)
449 		{
450 			IPACMERR("Failed adding Filtering rule %p with ret %d\n ", &qmi_rule_ex_msg, ret);
451 			close(fd_wwan_ioctl);
452 			return false;
453 		}
454 	}
455 #endif
456 
457 	close(fd_wwan_ioctl);
458 	return true;
459 }
460 
SendFilteringRuleIndex(struct ipa_fltr_installed_notif_req_msg_v01 * table)461 bool IPACM_Filtering::SendFilteringRuleIndex(struct ipa_fltr_installed_notif_req_msg_v01* table)
462 {
463 	int ret = 0;
464 	int fd_wwan_ioctl = open(WWAN_QMI_IOCTL_DEVICE_NAME, O_RDWR);
465 	if(fd_wwan_ioctl < 0)
466 	{
467 		IPACMERR("Failed to open %s.\n",WWAN_QMI_IOCTL_DEVICE_NAME);
468 		return false;
469 	}
470 
471 	ret = ioctl(fd_wwan_ioctl, WAN_IOC_ADD_FLT_RULE_INDEX, table);
472 	if (ret != 0)
473 	{
474 		IPACMERR("Failed adding filtering rule index %p with ret %d\n", table, ret);
475 		close(fd_wwan_ioctl);
476 		return false;
477 	}
478 
479 	IPACMDBG("Added Filtering rule index %p\n", table);
480 	close(fd_wwan_ioctl);
481 	return true;
482 }
483 
GetQmiFilterAction(ipa_flt_action action)484 ipa_filter_action_enum_v01 IPACM_Filtering::GetQmiFilterAction(ipa_flt_action action)
485 {
486 	switch(action)
487 	{
488 	case IPA_PASS_TO_ROUTING:
489 		return QMI_IPA_FILTER_ACTION_ROUTING_V01;
490 
491 	case IPA_PASS_TO_SRC_NAT:
492 		return QMI_IPA_FILTER_ACTION_SRC_NAT_V01;
493 
494 	case IPA_PASS_TO_DST_NAT:
495 		return QMI_IPA_FILTER_ACTION_DST_NAT_V01;
496 
497 	case IPA_PASS_TO_EXCEPTION:
498 		return QMI_IPA_FILTER_ACTION_EXCEPTION_V01;
499 
500 	default:
501 		return IPA_FILTER_ACTION_ENUM_MAX_ENUM_VAL_V01;
502 	}
503 }
504 
ModifyFilteringRule(struct ipa_ioc_mdfy_flt_rule * ruleTable)505 bool IPACM_Filtering::ModifyFilteringRule(struct ipa_ioc_mdfy_flt_rule* ruleTable)
506 {
507 	int i, ret = 0;
508 
509 	IPACMDBG("Printing filtering add attributes\n");
510 	IPACMDBG("IP type: %d Number of rules: %d commit value: %d\n", ruleTable->ip, ruleTable->num_rules, ruleTable->commit);
511 
512 	for (i=0; i<ruleTable->num_rules; i++)
513 	{
514 		IPACMDBG("Filter rule:%d attrib mask: 0x%x\n", i, ruleTable->rules[i].rule.attrib.attrib_mask);
515 	}
516 
517 	ret = ioctl(fd, IPA_IOC_MDFY_FLT_RULE, ruleTable);
518 	if (ret != 0)
519 	{
520 		IPACMERR("Failed modifying filtering rule %p\n", ruleTable);
521 
522 		for (i = 0; i < ruleTable->num_rules; i++)
523 		{
524 			if (ruleTable->rules[i].status != 0)
525 			{
526 				IPACMERR("Modifying filter rule %d failed\n", i);
527 			}
528 		}
529 		return false;
530 	}
531 
532 	IPACMDBG("Modified filtering rule %p\n", ruleTable);
533 	return true;
534 }
535 
536