Home | History | Annotate | Line # | Download | only in npf
npf_ruleset.c revision 1.7.6.1
      1  1.7.6.1   yamt /*	$NetBSD: npf_ruleset.c,v 1.7.6.1 2012/04/17 00:08:39 yamt Exp $	*/
      2      1.1  rmind 
      3      1.1  rmind /*-
      4  1.7.6.1   yamt  * Copyright (c) 2009-2012 The NetBSD Foundation, Inc.
      5      1.1  rmind  * All rights reserved.
      6      1.1  rmind  *
      7      1.1  rmind  * This material is based upon work partially supported by The
      8      1.1  rmind  * NetBSD Foundation under a contract with Mindaugas Rasiukevicius.
      9      1.1  rmind  *
     10      1.1  rmind  * Redistribution and use in source and binary forms, with or without
     11      1.1  rmind  * modification, are permitted provided that the following conditions
     12      1.1  rmind  * are met:
     13      1.1  rmind  * 1. Redistributions of source code must retain the above copyright
     14      1.1  rmind  *    notice, this list of conditions and the following disclaimer.
     15      1.1  rmind  * 2. Redistributions in binary form must reproduce the above copyright
     16      1.1  rmind  *    notice, this list of conditions and the following disclaimer in the
     17      1.1  rmind  *    documentation and/or other materials provided with the distribution.
     18      1.1  rmind  *
     19      1.1  rmind  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     20      1.1  rmind  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     21      1.1  rmind  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     22      1.1  rmind  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
     23      1.1  rmind  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     24      1.1  rmind  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     25      1.1  rmind  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     26      1.1  rmind  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     27      1.1  rmind  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     28      1.1  rmind  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     29      1.1  rmind  * POSSIBILITY OF SUCH DAMAGE.
     30      1.1  rmind  */
     31      1.1  rmind 
     32      1.1  rmind /*
     33      1.1  rmind  * NPF ruleset module.
     34      1.1  rmind  */
     35      1.1  rmind 
     36      1.1  rmind #include <sys/cdefs.h>
     37  1.7.6.1   yamt __KERNEL_RCSID(0, "$NetBSD: npf_ruleset.c,v 1.7.6.1 2012/04/17 00:08:39 yamt Exp $");
     38      1.1  rmind 
     39      1.1  rmind #include <sys/param.h>
     40  1.7.6.1   yamt #include <sys/types.h>
     41      1.1  rmind 
     42      1.1  rmind #include <sys/kmem.h>
     43      1.1  rmind #include <sys/queue.h>
     44      1.1  rmind #include <sys/types.h>
     45      1.1  rmind 
     46      1.3  rmind #include <net/pfil.h>
     47      1.1  rmind #include <net/if.h>
     48      1.1  rmind 
     49      1.1  rmind #include "npf_ncode.h"
     50      1.1  rmind #include "npf_impl.h"
     51      1.1  rmind 
     52      1.4  rmind /* Ruleset structre (queue and default rule). */
     53      1.4  rmind struct npf_ruleset {
     54      1.4  rmind 	TAILQ_HEAD(, npf_rule)	rs_queue;
     55      1.4  rmind 	npf_rule_t *		rs_default;
     56      1.4  rmind };
     57      1.4  rmind 
     58      1.7  rmind #define	NPF_RNAME_LEN		16
     59      1.7  rmind 
     60      1.1  rmind /* Rule structure. */
     61      1.1  rmind struct npf_rule {
     62      1.7  rmind 	/* Rule name (optional) and list entry. */
     63      1.7  rmind 	char			r_name[NPF_RNAME_LEN];
     64      1.4  rmind 	TAILQ_ENTRY(npf_rule)	r_entry;
     65      1.1  rmind 	/* Optional: sub-ruleset, NAT policy. */
     66      1.4  rmind 	npf_ruleset_t		r_subset;
     67      1.4  rmind 	npf_natpolicy_t *	r_natp;
     68      1.1  rmind 	/* Rule priority: (highest) 0, 1, 2 ... n (lowest). */
     69      1.7  rmind 	pri_t			r_priority;
     70      1.1  rmind 	/* N-code to process. */
     71      1.4  rmind 	void *			r_ncode;
     72      1.4  rmind 	size_t			r_nc_size;
     73      1.1  rmind 	/* Attributes of this rule. */
     74      1.4  rmind 	uint32_t		r_attr;
     75      1.1  rmind 	/* Interface. */
     76      1.4  rmind 	u_int			r_ifid;
     77      1.6  rmind 	/* Rule procedure data. */
     78      1.4  rmind 	npf_rproc_t *		r_rproc;
     79      1.1  rmind };
     80      1.1  rmind 
     81      1.1  rmind npf_ruleset_t *
     82      1.1  rmind npf_ruleset_create(void)
     83      1.1  rmind {
     84      1.1  rmind 	npf_ruleset_t *rlset;
     85      1.1  rmind 
     86      1.1  rmind 	rlset = kmem_zalloc(sizeof(npf_ruleset_t), KM_SLEEP);
     87      1.1  rmind 	TAILQ_INIT(&rlset->rs_queue);
     88      1.1  rmind 	return rlset;
     89      1.1  rmind }
     90      1.1  rmind 
     91      1.1  rmind void
     92      1.1  rmind npf_ruleset_destroy(npf_ruleset_t *rlset)
     93      1.1  rmind {
     94      1.1  rmind 	npf_rule_t *rl;
     95      1.1  rmind 
     96      1.1  rmind 	while ((rl = TAILQ_FIRST(&rlset->rs_queue)) != NULL) {
     97      1.1  rmind 		TAILQ_REMOVE(&rlset->rs_queue, rl, r_entry);
     98      1.1  rmind 		npf_rule_free(rl);
     99      1.1  rmind 	}
    100      1.1  rmind 	kmem_free(rlset, sizeof(npf_ruleset_t));
    101      1.1  rmind }
    102      1.1  rmind 
    103      1.1  rmind /*
    104      1.1  rmind  * npf_ruleset_insert: insert the rule into the specified ruleset.
    105      1.1  rmind  *
    106      1.1  rmind  * Note: multiple rules at the same priority are allowed.
    107      1.1  rmind  */
    108      1.1  rmind void
    109      1.1  rmind npf_ruleset_insert(npf_ruleset_t *rlset, npf_rule_t *rl)
    110      1.1  rmind {
    111      1.1  rmind 	npf_rule_t *it;
    112      1.1  rmind 
    113      1.1  rmind 	if (rl->r_attr & NPF_RULE_DEFAULT) {
    114      1.1  rmind 		rlset->rs_default = rl;
    115      1.1  rmind 		return;
    116      1.1  rmind 	}
    117      1.1  rmind 	TAILQ_FOREACH(it, &rlset->rs_queue, r_entry) {
    118      1.1  rmind 		/* Rule priority: (highest) 0, 1, 2, 4 ... n (lowest). */
    119      1.1  rmind 		if (it->r_priority > rl->r_priority)
    120      1.1  rmind 			break;
    121      1.1  rmind 	}
    122      1.1  rmind 	if (it == NULL) {
    123      1.1  rmind 		TAILQ_INSERT_TAIL(&rlset->rs_queue, rl, r_entry);
    124      1.1  rmind 	} else {
    125      1.1  rmind 		TAILQ_INSERT_BEFORE(it, rl, r_entry);
    126      1.1  rmind 	}
    127      1.1  rmind }
    128      1.1  rmind 
    129      1.1  rmind /*
    130      1.4  rmind  * npf_ruleset_matchnat: find a matching NAT policy in the ruleset.
    131      1.1  rmind  */
    132      1.4  rmind npf_rule_t *
    133      1.4  rmind npf_ruleset_matchnat(npf_ruleset_t *rlset, npf_natpolicy_t *mnp)
    134      1.1  rmind {
    135      1.4  rmind 	npf_rule_t *rl;
    136      1.1  rmind 
    137      1.4  rmind 	/* Find a matching NAT policy in the old ruleset. */
    138      1.4  rmind 	TAILQ_FOREACH(rl, &rlset->rs_queue, r_entry) {
    139      1.4  rmind 		if (npf_nat_matchpolicy(rl->r_natp, mnp))
    140      1.4  rmind 			break;
    141      1.4  rmind 	}
    142      1.4  rmind 	return rl;
    143      1.1  rmind }
    144      1.1  rmind 
    145      1.6  rmind npf_rule_t *
    146      1.6  rmind npf_ruleset_sharepm(npf_ruleset_t *rlset, npf_natpolicy_t *mnp)
    147      1.6  rmind {
    148      1.6  rmind 	npf_natpolicy_t *np;
    149      1.6  rmind 	npf_rule_t *rl;
    150      1.6  rmind 
    151      1.6  rmind 	/* Find a matching NAT policy in the old ruleset. */
    152      1.6  rmind 	TAILQ_FOREACH(rl, &rlset->rs_queue, r_entry) {
    153      1.6  rmind 		/*
    154      1.6  rmind 		 * NAT policy might not yet be set during the creation of
    155      1.6  rmind 		 * the ruleset (in such case, rule is for our policy), or
    156      1.6  rmind 		 * policies might be equal due to rule exchange on reload.
    157      1.6  rmind 		 */
    158      1.6  rmind 		np = rl->r_natp;
    159      1.6  rmind 		if (np == NULL || np == mnp)
    160      1.6  rmind 			continue;
    161      1.6  rmind 		if (npf_nat_sharepm(np, mnp))
    162      1.6  rmind 			break;
    163      1.6  rmind 	}
    164      1.6  rmind 	return rl;
    165      1.6  rmind }
    166      1.6  rmind 
    167      1.1  rmind /*
    168      1.4  rmind  * npf_ruleset_natreload: minimum reload of NAT policies by maching
    169      1.6  rmind  * two (active and new) NAT rulesets.
    170      1.4  rmind  *
    171      1.4  rmind  * => Active ruleset should be exclusively locked.
    172      1.1  rmind  */
    173      1.4  rmind void
    174      1.4  rmind npf_ruleset_natreload(npf_ruleset_t *nrlset, npf_ruleset_t *arlset)
    175      1.1  rmind {
    176      1.4  rmind 	npf_natpolicy_t *np, *anp;
    177      1.4  rmind 	npf_rule_t *rl, *arl;
    178      1.4  rmind 
    179      1.4  rmind 	KASSERT(npf_core_locked());
    180      1.1  rmind 
    181      1.4  rmind 	/* Scan a new NAT ruleset against NAT policies in old ruleset. */
    182      1.4  rmind 	TAILQ_FOREACH(rl, &nrlset->rs_queue, r_entry) {
    183      1.4  rmind 		np = rl->r_natp;
    184      1.4  rmind 		arl = npf_ruleset_matchnat(arlset, np);
    185      1.4  rmind 		if (arl == NULL) {
    186      1.4  rmind 			continue;
    187      1.4  rmind 		}
    188      1.4  rmind 		/* On match - we exchange NAT policies. */
    189      1.4  rmind 		anp = arl->r_natp;
    190      1.4  rmind 		rl->r_natp = anp;
    191      1.4  rmind 		arl->r_natp = np;
    192      1.6  rmind 		/* Update other NAT policies to share portmap. */
    193      1.6  rmind 		(void)npf_ruleset_sharepm(nrlset, anp);
    194      1.1  rmind 	}
    195      1.4  rmind }
    196      1.4  rmind 
    197      1.1  rmind /*
    198      1.6  rmind  * npf_rule_alloc: allocate a rule and copy n-code from user-space.
    199      1.4  rmind  *
    200      1.4  rmind  * => N-code should be validated by the caller.
    201      1.1  rmind  */
    202      1.4  rmind npf_rule_t *
    203      1.6  rmind npf_rule_alloc(prop_dictionary_t rldict, npf_rproc_t *rp,
    204      1.6  rmind    void *nc, size_t nc_size)
    205      1.1  rmind {
    206      1.4  rmind 	npf_rule_t *rl;
    207      1.7  rmind 	const char *rname;
    208  1.7.6.1   yamt 	int errat __unused;
    209      1.1  rmind 
    210      1.4  rmind 	/* Allocate a rule structure. */
    211  1.7.6.1   yamt 	rl = kmem_zalloc(sizeof(npf_rule_t), KM_SLEEP);
    212      1.4  rmind 	TAILQ_INIT(&rl->r_subset.rs_queue);
    213      1.4  rmind 	rl->r_natp = NULL;
    214      1.4  rmind 
    215      1.4  rmind 	/* N-code. */
    216      1.4  rmind 	KASSERT(nc == NULL || npf_ncode_validate(nc, nc_size, &errat) == 0);
    217      1.4  rmind 	rl->r_ncode = nc;
    218      1.4  rmind 	rl->r_nc_size = nc_size;
    219      1.4  rmind 
    220  1.7.6.1   yamt 	/* Name (optional) */
    221      1.7  rmind 	if (prop_dictionary_get_cstring_nocopy(rldict, "name", &rname)) {
    222      1.7  rmind 		strlcpy(rl->r_name, rname, NPF_RNAME_LEN);
    223      1.7  rmind 	} else {
    224      1.7  rmind 		rl->r_name[0] = '\0';
    225      1.7  rmind 	}
    226      1.7  rmind 
    227  1.7.6.1   yamt 	/* Attributes, priority and interface ID (optional). */
    228      1.7  rmind 	prop_dictionary_get_uint32(rldict, "attributes", &rl->r_attr);
    229      1.7  rmind 	prop_dictionary_get_int32(rldict, "priority", &rl->r_priority);
    230      1.7  rmind 	prop_dictionary_get_uint32(rldict, "interface", &rl->r_ifid);
    231      1.4  rmind 
    232      1.6  rmind 	/* Rule procedure. */
    233      1.6  rmind 	if (rp) {
    234  1.7.6.1   yamt 		npf_rproc_acquire(rp);
    235      1.4  rmind 	}
    236      1.6  rmind 	rl->r_rproc = rp;
    237      1.6  rmind 
    238      1.4  rmind 	return rl;
    239      1.1  rmind }
    240      1.1  rmind 
    241      1.1  rmind /*
    242      1.1  rmind  * npf_rule_free: free the specified rule.
    243      1.1  rmind  */
    244      1.1  rmind void
    245      1.1  rmind npf_rule_free(npf_rule_t *rl)
    246      1.1  rmind {
    247      1.4  rmind 	npf_natpolicy_t *np = rl->r_natp;
    248      1.4  rmind 	npf_rproc_t *rp = rl->r_rproc;
    249      1.1  rmind 
    250      1.4  rmind 	if (np) {
    251      1.4  rmind 		/* Free NAT policy. */
    252      1.4  rmind 		npf_nat_freepolicy(np);
    253      1.4  rmind 	}
    254      1.4  rmind 	if (rp) {
    255      1.6  rmind 		/* Release rule procedure. */
    256      1.4  rmind 		npf_rproc_release(rp);
    257      1.4  rmind 	}
    258      1.1  rmind 	if (rl->r_ncode) {
    259      1.4  rmind 		/* Free n-code. */
    260      1.1  rmind 		npf_ncode_free(rl->r_ncode, rl->r_nc_size);
    261      1.1  rmind 	}
    262      1.4  rmind 	kmem_free(rl, sizeof(npf_rule_t));
    263      1.1  rmind }
    264      1.1  rmind 
    265      1.1  rmind /*
    266      1.1  rmind  * npf_rule_subset: return sub-ruleset, if any.
    267  1.7.6.1   yamt  * npf_rule_getrproc: acquire a reference and return rule procedure, if any.
    268      1.1  rmind  * npf_rule_getnat: get NAT policy assigned to the rule.
    269      1.1  rmind  */
    270      1.1  rmind 
    271      1.1  rmind npf_ruleset_t *
    272      1.1  rmind npf_rule_subset(npf_rule_t *rl)
    273      1.1  rmind {
    274      1.1  rmind 	return &rl->r_subset;
    275      1.1  rmind }
    276      1.1  rmind 
    277  1.7.6.1   yamt npf_rproc_t *
    278  1.7.6.1   yamt npf_rule_getrproc(npf_rule_t *rl)
    279  1.7.6.1   yamt {
    280  1.7.6.1   yamt 	npf_rproc_t *rp = rl->r_rproc;
    281  1.7.6.1   yamt 
    282  1.7.6.1   yamt 	KASSERT(npf_core_locked());
    283  1.7.6.1   yamt 	if (rp) {
    284  1.7.6.1   yamt 		npf_rproc_acquire(rp);
    285  1.7.6.1   yamt 	}
    286  1.7.6.1   yamt 	return rp;
    287  1.7.6.1   yamt }
    288  1.7.6.1   yamt 
    289      1.1  rmind npf_natpolicy_t *
    290      1.1  rmind npf_rule_getnat(const npf_rule_t *rl)
    291      1.1  rmind {
    292      1.4  rmind 	return rl->r_natp;
    293      1.1  rmind }
    294      1.1  rmind 
    295      1.4  rmind /*
    296      1.4  rmind  * npf_rule_setnat: assign NAT policy to the rule and insert into the
    297      1.4  rmind  * NAT policy list in the ruleset.
    298      1.4  rmind  */
    299      1.1  rmind void
    300      1.1  rmind npf_rule_setnat(npf_rule_t *rl, npf_natpolicy_t *np)
    301      1.1  rmind {
    302      1.3  rmind 
    303      1.4  rmind 	KASSERT(rl->r_natp == NULL);
    304      1.4  rmind 	rl->r_natp = np;
    305      1.1  rmind }
    306      1.1  rmind 
    307      1.7  rmind npf_rule_t *
    308      1.7  rmind npf_ruleset_replace(const char *name, npf_ruleset_t *rlset)
    309      1.7  rmind {
    310      1.7  rmind 	npf_ruleset_t orlset;
    311      1.7  rmind 	npf_rule_t *rl;
    312      1.7  rmind 
    313      1.7  rmind 	npf_core_enter(); /* XXX */
    314      1.7  rmind 	rlset = npf_core_ruleset();
    315      1.7  rmind 	TAILQ_FOREACH(rl, &rlset->rs_queue, r_entry) {
    316      1.7  rmind 		if (rl->r_name[0] == '\0')
    317      1.7  rmind 			continue;
    318      1.7  rmind 		if (strncmp(rl->r_name, name, NPF_RNAME_LEN))
    319      1.7  rmind 			continue;
    320      1.7  rmind 		memcpy(&orlset, &rl->r_subset, sizeof(npf_ruleset_t));
    321      1.7  rmind 		break;
    322      1.7  rmind 	}
    323      1.7  rmind 	npf_core_exit();
    324      1.7  rmind 	return rl;
    325      1.7  rmind }
    326      1.1  rmind 
    327      1.1  rmind /*
    328      1.7  rmind  * npf_ruleset_inspect: inspect the packet against the given ruleset.
    329      1.1  rmind  *
    330      1.7  rmind  * Loop through the rules in the set and run n-code processor of each rule
    331      1.7  rmind  * against the packet (nbuf chain).  If sub-ruleset is found, inspect it.
    332      1.7  rmind  *
    333  1.7.6.1   yamt  * => Caller is responsible for nbuf chain protection.
    334      1.1  rmind  */
    335      1.1  rmind npf_rule_t *
    336      1.7  rmind npf_ruleset_inspect(npf_cache_t *npc, nbuf_t *nbuf, npf_ruleset_t *mainrlset,
    337      1.6  rmind     ifnet_t *ifp, const int di, const int layer)
    338      1.1  rmind {
    339      1.7  rmind 	const int di_mask = (di & PFIL_IN) ? NPF_RULE_IN : NPF_RULE_OUT;
    340      1.7  rmind 	npf_ruleset_t *rlset = mainrlset;
    341      1.1  rmind 	npf_rule_t *final_rl = NULL, *rl;
    342      1.7  rmind 	bool defed = false;
    343      1.1  rmind 
    344      1.7  rmind 	KASSERT(npf_core_locked());
    345      1.1  rmind 	KASSERT(((di & PFIL_IN) != 0) ^ ((di & PFIL_OUT) != 0));
    346      1.7  rmind again:
    347      1.1  rmind 	TAILQ_FOREACH(rl, &rlset->rs_queue, r_entry) {
    348      1.1  rmind 		KASSERT(!final_rl || rl->r_priority >= final_rl->r_priority);
    349      1.1  rmind 
    350      1.1  rmind 		/* Match the interface. */
    351      1.1  rmind 		if (rl->r_ifid && rl->r_ifid != ifp->if_index) {
    352      1.1  rmind 			continue;
    353      1.1  rmind 		}
    354      1.1  rmind 		/* Match the direction. */
    355      1.1  rmind 		if ((rl->r_attr & NPF_RULE_DIMASK) != NPF_RULE_DIMASK) {
    356      1.1  rmind 			if ((rl->r_attr & di_mask) == 0)
    357      1.1  rmind 				continue;
    358      1.1  rmind 		}
    359      1.1  rmind 		/* Process the n-code, if any. */
    360      1.1  rmind 		const void *nc = rl->r_ncode;
    361      1.1  rmind 		if (nc && npf_ncode_process(npc, nc, nbuf, layer)) {
    362      1.1  rmind 			continue;
    363      1.1  rmind 		}
    364      1.1  rmind 		/* Set the matching rule and check for "final". */
    365      1.1  rmind 		final_rl = rl;
    366      1.1  rmind 		if (rl->r_attr & NPF_RULE_FINAL) {
    367      1.2  rmind 			break;
    368      1.1  rmind 		}
    369      1.1  rmind 	}
    370      1.2  rmind 
    371      1.2  rmind 	/* If no final rule, then - default. */
    372      1.7  rmind 	if (final_rl == NULL && !defed) {
    373      1.7  rmind 		final_rl = mainrlset->rs_default;
    374      1.2  rmind 		defed = true;
    375      1.2  rmind 	}
    376      1.2  rmind 	/* Inspect the sub-ruleset, if any. */
    377      1.7  rmind 	if (final_rl && !TAILQ_EMPTY(&final_rl->r_subset.rs_queue)) {
    378      1.7  rmind 		rlset = &final_rl->r_subset;
    379      1.7  rmind 		final_rl = NULL;
    380      1.7  rmind 		goto again;
    381      1.2  rmind 	}
    382      1.7  rmind 	return final_rl;
    383      1.1  rmind }
    384      1.1  rmind 
    385      1.1  rmind /*
    386  1.7.6.1   yamt  * npf_rule_apply: apply the rule and return appropriate value.
    387      1.1  rmind  *
    388      1.1  rmind  * => Returns ENETUNREACH if "block" and 0 if "pass".
    389      1.1  rmind  * => Releases the ruleset lock.
    390      1.1  rmind  */
    391      1.1  rmind int
    392      1.4  rmind npf_rule_apply(npf_cache_t *npc, nbuf_t *nbuf, npf_rule_t *rl, int *retfl)
    393      1.1  rmind {
    394      1.4  rmind 	int error;
    395      1.1  rmind 
    396      1.4  rmind 	KASSERT(npf_core_locked());
    397      1.1  rmind 
    398      1.1  rmind 	/* If not passing - drop the packet. */
    399  1.7.6.1   yamt 	error = (rl->r_attr & NPF_RULE_PASS) ? 0 : ENETUNREACH;
    400  1.7.6.1   yamt 
    401      1.4  rmind 	*retfl = rl->r_attr;
    402      1.4  rmind 	npf_core_exit();
    403  1.7.6.1   yamt 
    404      1.4  rmind 	return error;
    405      1.1  rmind }
    406      1.1  rmind 
    407      1.1  rmind #if defined(DDB) || defined(_NPF_TESTING)
    408      1.1  rmind 
    409      1.1  rmind void
    410      1.1  rmind npf_rulenc_dump(npf_rule_t *rl)
    411      1.1  rmind {
    412      1.1  rmind 	uint32_t *op = rl->r_ncode;
    413      1.1  rmind 	size_t n = rl->r_nc_size;
    414      1.1  rmind 
    415      1.2  rmind 	while (n) {
    416      1.1  rmind 		printf("\t> |0x%02x|\n", (uint32_t)*op);
    417      1.1  rmind 		op++;
    418      1.1  rmind 		n -= sizeof(*op);
    419      1.2  rmind 	}
    420      1.1  rmind 	printf("-> %s\n", (rl->r_attr & NPF_RULE_PASS) ? "pass" : "block");
    421      1.1  rmind }
    422      1.1  rmind 
    423      1.1  rmind #endif
    424