Home | History | Annotate | Line # | Download | only in libnpf
npf.c revision 1.28.2.1
      1  1.28.2.1       tls /*	$NetBSD: npf.c,v 1.28.2.1 2014/08/10 06:52:04 tls Exp $	*/
      2       1.1     rmind 
      3       1.1     rmind /*-
      4      1.26     rmind  * Copyright (c) 2010-2014 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 #include <sys/cdefs.h>
     33  1.28.2.1       tls __KERNEL_RCSID(0, "$NetBSD: npf.c,v 1.28.2.1 2014/08/10 06:52:04 tls Exp $");
     34       1.1     rmind 
     35       1.1     rmind #include <sys/types.h>
     36       1.1     rmind #include <netinet/in_systm.h>
     37       1.1     rmind #include <netinet/in.h>
     38      1.11     rmind #include <net/if.h>
     39       1.1     rmind #include <prop/proplib.h>
     40       1.1     rmind 
     41       1.1     rmind #include <stdlib.h>
     42       1.1     rmind #include <string.h>
     43       1.7     rmind #include <assert.h>
     44       1.1     rmind #include <errno.h>
     45       1.1     rmind #include <err.h>
     46       1.1     rmind 
     47       1.1     rmind #define	_NPF_PRIVATE
     48       1.1     rmind #include "npf.h"
     49       1.1     rmind 
     50       1.1     rmind struct nl_rule {
     51       1.1     rmind 	prop_dictionary_t	nrl_dict;
     52       1.1     rmind };
     53       1.1     rmind 
     54       1.1     rmind struct nl_rproc {
     55       1.1     rmind 	prop_dictionary_t	nrp_dict;
     56       1.1     rmind };
     57       1.1     rmind 
     58       1.1     rmind struct nl_table {
     59       1.1     rmind 	prop_dictionary_t	ntl_dict;
     60       1.1     rmind };
     61       1.1     rmind 
     62      1.19  christos struct nl_alg {
     63      1.19  christos 	prop_dictionary_t	nal_dict;
     64      1.19  christos };
     65      1.19  christos 
     66      1.13     rmind struct nl_ext {
     67      1.13     rmind 	const char *		nxt_name;
     68      1.13     rmind 	prop_dictionary_t	nxt_dict;
     69      1.13     rmind };
     70      1.13     rmind 
     71      1.20     rmind struct nl_config {
     72      1.20     rmind 	/* Rules, translations, tables, procedures. */
     73      1.20     rmind 	prop_dictionary_t	ncf_dict;
     74      1.20     rmind 	prop_array_t		ncf_alg_list;
     75      1.20     rmind 	prop_array_t		ncf_rules_list;
     76      1.20     rmind 	prop_array_t		ncf_rproc_list;
     77      1.20     rmind 	prop_array_t		ncf_table_list;
     78      1.20     rmind 	prop_array_t		ncf_nat_list;
     79      1.20     rmind 
     80      1.20     rmind 	/* Iterators. */
     81      1.20     rmind 	prop_object_iterator_t	ncf_rule_iter;
     82      1.20     rmind 	unsigned		ncf_reduce[16];
     83      1.20     rmind 	unsigned		ncf_nlevel;
     84      1.20     rmind 	unsigned		ncf_counter;
     85      1.20     rmind 	nl_rule_t		ncf_cur_rule;
     86      1.20     rmind 
     87      1.20     rmind 	prop_object_iterator_t	ncf_table_iter;
     88      1.20     rmind 	nl_table_t		ncf_cur_table;
     89      1.20     rmind 
     90      1.20     rmind 	prop_object_iterator_t	ncf_rproc_iter;
     91      1.20     rmind 	nl_rproc_t		ncf_cur_rproc;
     92      1.20     rmind 
     93      1.20     rmind 	/* Error report and debug information. */
     94      1.20     rmind 	prop_dictionary_t	ncf_err;
     95      1.20     rmind 	prop_dictionary_t	ncf_debug;
     96      1.20     rmind 
     97      1.20     rmind 	/* Custom file to externalise property-list. */
     98      1.20     rmind 	const char *		ncf_plist;
     99      1.20     rmind 	bool			ncf_flush;
    100      1.20     rmind };
    101      1.20     rmind 
    102      1.16     rmind static prop_array_t	_npf_ruleset_transform(prop_array_t);
    103      1.16     rmind 
    104       1.1     rmind /*
    105       1.1     rmind  * CONFIGURATION INTERFACE.
    106       1.1     rmind  */
    107       1.1     rmind 
    108       1.1     rmind nl_config_t *
    109       1.1     rmind npf_config_create(void)
    110       1.1     rmind {
    111       1.1     rmind 	nl_config_t *ncf;
    112       1.1     rmind 
    113       1.7     rmind 	ncf = calloc(1, sizeof(*ncf));
    114       1.1     rmind 	if (ncf == NULL) {
    115       1.1     rmind 		return NULL;
    116       1.1     rmind 	}
    117      1.19  christos 	ncf->ncf_alg_list = prop_array_create();
    118       1.1     rmind 	ncf->ncf_rules_list = prop_array_create();
    119       1.1     rmind 	ncf->ncf_rproc_list = prop_array_create();
    120       1.1     rmind 	ncf->ncf_table_list = prop_array_create();
    121       1.1     rmind 	ncf->ncf_nat_list = prop_array_create();
    122       1.1     rmind 
    123       1.4     rmind 	ncf->ncf_plist = NULL;
    124       1.6     rmind 	ncf->ncf_flush = false;
    125       1.4     rmind 
    126       1.1     rmind 	return ncf;
    127       1.1     rmind }
    128       1.1     rmind 
    129       1.1     rmind int
    130       1.1     rmind npf_config_submit(nl_config_t *ncf, int fd)
    131       1.1     rmind {
    132       1.7     rmind 	const char *plist = ncf->ncf_plist;
    133       1.1     rmind 	prop_dictionary_t npf_dict;
    134      1.16     rmind 	prop_array_t rlset;
    135       1.1     rmind 	int error = 0;
    136       1.1     rmind 
    137       1.1     rmind 	npf_dict = prop_dictionary_create();
    138       1.1     rmind 	if (npf_dict == NULL) {
    139       1.1     rmind 		return ENOMEM;
    140       1.1     rmind 	}
    141      1.15     rmind 	prop_dictionary_set_uint32(npf_dict, "version", NPF_VERSION);
    142      1.16     rmind 
    143      1.16     rmind 	rlset = _npf_ruleset_transform(ncf->ncf_rules_list);
    144      1.16     rmind 	if (rlset == NULL) {
    145      1.16     rmind 		prop_object_release(npf_dict);
    146      1.16     rmind 		return ENOMEM;
    147      1.16     rmind 	}
    148      1.20     rmind 	prop_object_release(ncf->ncf_rules_list);
    149      1.20     rmind 	ncf->ncf_rules_list = rlset;
    150      1.16     rmind 
    151      1.20     rmind 	prop_dictionary_set(npf_dict, "rules", ncf->ncf_rules_list);
    152      1.19  christos 	prop_dictionary_set(npf_dict, "algs", ncf->ncf_alg_list);
    153       1.1     rmind 	prop_dictionary_set(npf_dict, "rprocs", ncf->ncf_rproc_list);
    154       1.1     rmind 	prop_dictionary_set(npf_dict, "tables", ncf->ncf_table_list);
    155       1.1     rmind 	prop_dictionary_set(npf_dict, "translation", ncf->ncf_nat_list);
    156       1.6     rmind 	prop_dictionary_set_bool(npf_dict, "flush", ncf->ncf_flush);
    157      1.15     rmind 	if (ncf->ncf_debug) {
    158      1.15     rmind 		prop_dictionary_set(npf_dict, "debug", ncf->ncf_debug);
    159      1.15     rmind 	}
    160       1.1     rmind 
    161       1.4     rmind 	if (plist) {
    162       1.4     rmind 		if (!prop_dictionary_externalize_to_file(npf_dict, plist)) {
    163       1.4     rmind 			error = errno;
    164       1.4     rmind 		}
    165       1.7     rmind 		prop_object_release(npf_dict);
    166       1.7     rmind 		return error;
    167       1.7     rmind 	}
    168      1.20     rmind 	if (fd) {
    169      1.20     rmind 		error = prop_dictionary_sendrecv_ioctl(npf_dict, fd,
    170  1.28.2.1       tls 		    IOC_NPF_LOAD, &ncf->ncf_err);
    171      1.20     rmind 		if (error) {
    172      1.20     rmind 			prop_object_release(npf_dict);
    173      1.20     rmind 			assert(ncf->ncf_err == NULL);
    174      1.20     rmind 			return error;
    175      1.20     rmind 		}
    176      1.20     rmind 		prop_dictionary_get_int32(ncf->ncf_err, "errno", &error);
    177       1.1     rmind 	}
    178       1.1     rmind 	prop_object_release(npf_dict);
    179       1.1     rmind 	return error;
    180       1.1     rmind }
    181       1.1     rmind 
    182  1.28.2.1       tls static nl_config_t *
    183  1.28.2.1       tls _npf_config_consdict(prop_dictionary_t npf_dict)
    184       1.8     rmind {
    185       1.8     rmind 	nl_config_t *ncf;
    186       1.8     rmind 
    187       1.8     rmind 	ncf = calloc(1, sizeof(*ncf));
    188       1.8     rmind 	if (ncf == NULL) {
    189       1.8     rmind 		return NULL;
    190       1.8     rmind 	}
    191       1.8     rmind 	ncf->ncf_dict = npf_dict;
    192      1.19  christos 	ncf->ncf_alg_list = prop_dictionary_get(npf_dict, "algs");
    193       1.8     rmind 	ncf->ncf_rules_list = prop_dictionary_get(npf_dict, "rules");
    194       1.8     rmind 	ncf->ncf_rproc_list = prop_dictionary_get(npf_dict, "rprocs");
    195       1.8     rmind 	ncf->ncf_table_list = prop_dictionary_get(npf_dict, "tables");
    196       1.8     rmind 	ncf->ncf_nat_list = prop_dictionary_get(npf_dict, "translation");
    197  1.28.2.1       tls 	return ncf;
    198  1.28.2.1       tls }
    199       1.8     rmind 
    200  1.28.2.1       tls nl_config_t *
    201  1.28.2.1       tls npf_config_retrieve(int fd, bool *active, bool *loaded)
    202  1.28.2.1       tls {
    203  1.28.2.1       tls 	prop_dictionary_t npf_dict;
    204  1.28.2.1       tls 	nl_config_t *ncf;
    205  1.28.2.1       tls 	int error;
    206  1.28.2.1       tls 
    207  1.28.2.1       tls 	error = prop_dictionary_recv_ioctl(fd, IOC_NPF_SAVE, &npf_dict);
    208  1.28.2.1       tls 	if (error) {
    209  1.28.2.1       tls 		return NULL;
    210  1.28.2.1       tls 	}
    211  1.28.2.1       tls 	ncf = _npf_config_consdict(npf_dict);
    212  1.28.2.1       tls 	if (ncf == NULL) {
    213  1.28.2.1       tls 		prop_object_release(npf_dict);
    214  1.28.2.1       tls 		return NULL;
    215  1.28.2.1       tls 	}
    216       1.8     rmind 	prop_dictionary_get_bool(npf_dict, "active", active);
    217       1.8     rmind 	*loaded = (ncf->ncf_rules_list != NULL);
    218       1.8     rmind 	return ncf;
    219       1.8     rmind }
    220       1.8     rmind 
    221       1.6     rmind int
    222  1.28.2.1       tls npf_config_export(const nl_config_t *ncf, const char *path)
    223  1.28.2.1       tls {
    224  1.28.2.1       tls 	prop_dictionary_t npf_dict = ncf->ncf_dict;
    225  1.28.2.1       tls 	int error = 0;
    226  1.28.2.1       tls 
    227  1.28.2.1       tls 	if (!prop_dictionary_externalize_to_file(npf_dict, path)) {
    228  1.28.2.1       tls 		error = errno;
    229  1.28.2.1       tls 	}
    230  1.28.2.1       tls 	return error;
    231  1.28.2.1       tls }
    232  1.28.2.1       tls 
    233  1.28.2.1       tls nl_config_t *
    234  1.28.2.1       tls npf_config_import(const char *path)
    235  1.28.2.1       tls {
    236  1.28.2.1       tls 	prop_dictionary_t npf_dict;
    237  1.28.2.1       tls 	nl_config_t *ncf;
    238  1.28.2.1       tls 
    239  1.28.2.1       tls 	npf_dict = prop_dictionary_internalize_from_file(path);
    240  1.28.2.1       tls 	if (npf_dict) {
    241  1.28.2.1       tls 		return NULL;
    242  1.28.2.1       tls 	}
    243  1.28.2.1       tls 	ncf = _npf_config_consdict(npf_dict);
    244  1.28.2.1       tls 	if (ncf == NULL) {
    245  1.28.2.1       tls 		prop_object_release(npf_dict);
    246  1.28.2.1       tls 		return NULL;
    247  1.28.2.1       tls 	}
    248  1.28.2.1       tls 	return ncf;
    249  1.28.2.1       tls }
    250  1.28.2.1       tls 
    251  1.28.2.1       tls int
    252       1.6     rmind npf_config_flush(int fd)
    253       1.6     rmind {
    254       1.6     rmind 	nl_config_t *ncf;
    255       1.6     rmind 	int error;
    256       1.6     rmind 
    257       1.6     rmind 	ncf = npf_config_create();
    258       1.6     rmind 	if (ncf == NULL) {
    259       1.6     rmind 		return ENOMEM;
    260       1.6     rmind 	}
    261       1.6     rmind 	ncf->ncf_flush = true;
    262       1.6     rmind 	error = npf_config_submit(ncf, fd);
    263       1.6     rmind 	npf_config_destroy(ncf);
    264       1.6     rmind 	return error;
    265       1.6     rmind }
    266       1.6     rmind 
    267       1.1     rmind void
    268       1.7     rmind _npf_config_error(nl_config_t *ncf, nl_error_t *ne)
    269       1.7     rmind {
    270       1.7     rmind 	memset(ne, 0, sizeof(*ne));
    271       1.7     rmind 	prop_dictionary_get_int32(ncf->ncf_err, "id", &ne->ne_id);
    272       1.7     rmind 	prop_dictionary_get_cstring(ncf->ncf_err,
    273       1.7     rmind 	    "source-file", &ne->ne_source_file);
    274       1.7     rmind 	prop_dictionary_get_uint32(ncf->ncf_err,
    275       1.7     rmind 	    "source-line", &ne->ne_source_line);
    276       1.7     rmind 	prop_dictionary_get_int32(ncf->ncf_err,
    277      1.16     rmind 	    "code-error", &ne->ne_ncode_error);
    278       1.7     rmind 	prop_dictionary_get_int32(ncf->ncf_err,
    279      1.16     rmind 	    "code-errat", &ne->ne_ncode_errat);
    280       1.7     rmind }
    281       1.7     rmind 
    282       1.7     rmind void
    283       1.1     rmind npf_config_destroy(nl_config_t *ncf)
    284       1.1     rmind {
    285      1.14     rmind 	if (!ncf->ncf_dict) {
    286      1.19  christos 		prop_object_release(ncf->ncf_alg_list);
    287       1.8     rmind 		prop_object_release(ncf->ncf_rules_list);
    288       1.8     rmind 		prop_object_release(ncf->ncf_rproc_list);
    289       1.8     rmind 		prop_object_release(ncf->ncf_table_list);
    290       1.8     rmind 		prop_object_release(ncf->ncf_nat_list);
    291       1.8     rmind 	}
    292       1.7     rmind 	if (ncf->ncf_err) {
    293       1.7     rmind 		prop_object_release(ncf->ncf_err);
    294       1.7     rmind 	}
    295      1.11     rmind 	if (ncf->ncf_debug) {
    296      1.11     rmind 		prop_object_release(ncf->ncf_debug);
    297      1.11     rmind 	}
    298       1.1     rmind 	free(ncf);
    299       1.1     rmind }
    300       1.1     rmind 
    301       1.4     rmind void
    302       1.4     rmind _npf_config_setsubmit(nl_config_t *ncf, const char *plist_file)
    303       1.4     rmind {
    304       1.4     rmind 	ncf->ncf_plist = plist_file;
    305       1.4     rmind }
    306       1.4     rmind 
    307       1.1     rmind static bool
    308       1.1     rmind _npf_prop_array_lookup(prop_array_t array, const char *key, const char *name)
    309       1.1     rmind {
    310       1.1     rmind 	prop_dictionary_t dict;
    311       1.1     rmind 	prop_object_iterator_t it;
    312       1.1     rmind 
    313       1.1     rmind 	it = prop_array_iterator(array);
    314       1.1     rmind 	while ((dict = prop_object_iterator_next(it)) != NULL) {
    315       1.1     rmind 		const char *lname;
    316       1.1     rmind 		prop_dictionary_get_cstring_nocopy(dict, key, &lname);
    317       1.1     rmind 		if (strcmp(name, lname) == 0)
    318       1.1     rmind 			break;
    319       1.1     rmind 	}
    320       1.1     rmind 	prop_object_iterator_release(it);
    321       1.1     rmind 	return dict ? true : false;
    322       1.1     rmind }
    323       1.1     rmind 
    324       1.1     rmind /*
    325      1.16     rmind  * DYNAMIC RULESET INTERFACE.
    326      1.16     rmind  */
    327      1.16     rmind 
    328      1.16     rmind int
    329      1.18     rmind npf_ruleset_add(int fd, const char *rname, nl_rule_t *rl, uint64_t *id)
    330      1.16     rmind {
    331      1.16     rmind 	prop_dictionary_t rldict = rl->nrl_dict;
    332      1.16     rmind 	prop_dictionary_t ret;
    333      1.16     rmind 	int error;
    334      1.16     rmind 
    335      1.16     rmind 	prop_dictionary_set_cstring(rldict, "ruleset-name", rname);
    336      1.16     rmind 	prop_dictionary_set_uint32(rldict, "command", NPF_CMD_RULE_ADD);
    337      1.16     rmind 	error = prop_dictionary_sendrecv_ioctl(rldict, fd, IOC_NPF_RULE, &ret);
    338      1.16     rmind 	if (!error) {
    339      1.18     rmind 		prop_dictionary_get_uint64(ret, "id", id);
    340      1.16     rmind 	}
    341      1.16     rmind 	return error;
    342      1.16     rmind }
    343      1.16     rmind 
    344      1.16     rmind int
    345      1.18     rmind npf_ruleset_remove(int fd, const char *rname, uint64_t id)
    346      1.16     rmind {
    347      1.16     rmind 	prop_dictionary_t rldict;
    348      1.16     rmind 
    349      1.16     rmind 	rldict = prop_dictionary_create();
    350      1.16     rmind 	if (rldict == NULL) {
    351      1.16     rmind 		return ENOMEM;
    352      1.16     rmind 	}
    353      1.16     rmind 	prop_dictionary_set_cstring(rldict, "ruleset-name", rname);
    354      1.16     rmind 	prop_dictionary_set_uint32(rldict, "command", NPF_CMD_RULE_REMOVE);
    355      1.18     rmind 	prop_dictionary_set_uint64(rldict, "id", id);
    356      1.16     rmind 	return prop_dictionary_send_ioctl(rldict, fd, IOC_NPF_RULE);
    357      1.16     rmind }
    358      1.16     rmind 
    359      1.16     rmind int
    360      1.16     rmind npf_ruleset_remkey(int fd, const char *rname, const void *key, size_t len)
    361      1.16     rmind {
    362      1.16     rmind 	prop_dictionary_t rldict;
    363      1.16     rmind 	prop_data_t keyobj;
    364      1.16     rmind 
    365      1.16     rmind 	rldict = prop_dictionary_create();
    366      1.16     rmind 	if (rldict == NULL) {
    367      1.16     rmind 		return ENOMEM;
    368      1.16     rmind 	}
    369      1.16     rmind 	prop_dictionary_set_cstring(rldict, "ruleset-name", rname);
    370      1.16     rmind 	prop_dictionary_set_uint32(rldict, "command", NPF_CMD_RULE_REMKEY);
    371      1.16     rmind 
    372      1.16     rmind 	keyobj = prop_data_create_data(key, len);
    373      1.16     rmind 	if (keyobj == NULL) {
    374      1.16     rmind 		prop_object_release(rldict);
    375      1.16     rmind 		return ENOMEM;
    376      1.16     rmind 	}
    377      1.16     rmind 	prop_dictionary_set(rldict, "key", keyobj);
    378      1.16     rmind 	prop_object_release(keyobj);
    379      1.16     rmind 
    380      1.16     rmind 	return prop_dictionary_send_ioctl(rldict, fd, IOC_NPF_RULE);
    381      1.16     rmind }
    382      1.16     rmind 
    383      1.17     rmind int
    384      1.17     rmind npf_ruleset_flush(int fd, const char *rname)
    385      1.17     rmind {
    386      1.17     rmind 	prop_dictionary_t rldict;
    387      1.17     rmind 
    388      1.17     rmind 	rldict = prop_dictionary_create();
    389      1.17     rmind 	if (rldict == NULL) {
    390      1.17     rmind 		return ENOMEM;
    391      1.17     rmind 	}
    392      1.17     rmind 	prop_dictionary_set_cstring(rldict, "ruleset-name", rname);
    393      1.17     rmind 	prop_dictionary_set_uint32(rldict, "command", NPF_CMD_RULE_FLUSH);
    394      1.17     rmind 	return prop_dictionary_send_ioctl(rldict, fd, IOC_NPF_RULE);
    395      1.17     rmind }
    396      1.17     rmind 
    397      1.16     rmind /*
    398      1.16     rmind  * _npf_ruleset_transform: transform the ruleset representing nested
    399      1.16     rmind  * rules with lists into an array.
    400      1.16     rmind  */
    401      1.16     rmind 
    402      1.16     rmind static void
    403      1.16     rmind _npf_ruleset_transform1(prop_array_t rlset, prop_array_t rules)
    404      1.16     rmind {
    405      1.16     rmind 	prop_object_iterator_t it;
    406      1.16     rmind 	prop_dictionary_t rldict;
    407      1.16     rmind 	prop_array_t subrlset;
    408      1.16     rmind 
    409      1.16     rmind 	it = prop_array_iterator(rules);
    410      1.16     rmind 	while ((rldict = prop_object_iterator_next(it)) != NULL) {
    411      1.16     rmind 		unsigned idx;
    412      1.16     rmind 
    413      1.16     rmind 		/* Add rules to the array (reference is retained). */
    414      1.16     rmind 		prop_array_add(rlset, rldict);
    415      1.16     rmind 
    416      1.16     rmind 		subrlset = prop_dictionary_get(rldict, "subrules");
    417      1.16     rmind 		if (subrlset) {
    418      1.16     rmind 			/* Process subrules recursively. */
    419      1.16     rmind 			_npf_ruleset_transform1(rlset, subrlset);
    420      1.16     rmind 			/* Add the skip-to position. */
    421      1.16     rmind 			idx = prop_array_count(rlset);
    422      1.16     rmind 			prop_dictionary_set_uint32(rldict, "skip-to", idx);
    423      1.16     rmind 			prop_dictionary_remove(rldict, "subrules");
    424      1.16     rmind 		}
    425      1.16     rmind 	}
    426      1.16     rmind 	prop_object_iterator_release(it);
    427      1.16     rmind }
    428      1.16     rmind 
    429      1.16     rmind static prop_array_t
    430      1.16     rmind _npf_ruleset_transform(prop_array_t rlset)
    431      1.16     rmind {
    432      1.16     rmind 	prop_array_t nrlset;
    433      1.16     rmind 
    434      1.16     rmind 	nrlset = prop_array_create();
    435      1.16     rmind 	_npf_ruleset_transform1(nrlset, rlset);
    436      1.16     rmind 	return nrlset;
    437      1.16     rmind }
    438      1.16     rmind 
    439      1.16     rmind /*
    440      1.13     rmind  * NPF EXTENSION INTERFACE.
    441      1.13     rmind  */
    442      1.13     rmind 
    443      1.13     rmind nl_ext_t *
    444      1.13     rmind npf_ext_construct(const char *name)
    445      1.13     rmind {
    446      1.13     rmind 	nl_ext_t *ext;
    447      1.13     rmind 
    448      1.13     rmind 	ext = malloc(sizeof(*ext));
    449      1.13     rmind 	if (ext == NULL) {
    450      1.13     rmind 		return NULL;
    451      1.13     rmind 	}
    452      1.13     rmind 	ext->nxt_name = strdup(name);
    453      1.13     rmind 	if (ext->nxt_name == NULL) {
    454      1.13     rmind 		free(ext);
    455      1.13     rmind 		return NULL;
    456      1.13     rmind 	}
    457      1.13     rmind 	ext->nxt_dict = prop_dictionary_create();
    458      1.13     rmind 
    459      1.13     rmind 	return ext;
    460      1.13     rmind }
    461      1.13     rmind 
    462      1.13     rmind void
    463      1.13     rmind npf_ext_param_u32(nl_ext_t *ext, const char *key, uint32_t val)
    464      1.13     rmind {
    465      1.13     rmind 	prop_dictionary_t extdict = ext->nxt_dict;
    466      1.13     rmind 	prop_dictionary_set_uint32(extdict, key, val);
    467      1.13     rmind }
    468      1.13     rmind 
    469      1.13     rmind void
    470      1.13     rmind npf_ext_param_bool(nl_ext_t *ext, const char *key, bool val)
    471      1.13     rmind {
    472      1.13     rmind 	prop_dictionary_t extdict = ext->nxt_dict;
    473      1.13     rmind 	prop_dictionary_set_bool(extdict, key, val);
    474      1.13     rmind }
    475      1.13     rmind 
    476  1.28.2.1       tls void
    477  1.28.2.1       tls npf_ext_param_string(nl_ext_t *ext, const char *key, const char *val)
    478  1.28.2.1       tls {
    479  1.28.2.1       tls 	prop_dictionary_t extdict = ext->nxt_dict;
    480  1.28.2.1       tls 	prop_dictionary_set_cstring(extdict, key, val);
    481  1.28.2.1       tls }
    482  1.28.2.1       tls 
    483      1.13     rmind /*
    484       1.1     rmind  * RULE INTERFACE.
    485       1.1     rmind  */
    486       1.1     rmind 
    487       1.1     rmind nl_rule_t *
    488      1.22     rmind npf_rule_create(const char *name, uint32_t attr, const char *ifname)
    489       1.1     rmind {
    490       1.1     rmind 	prop_dictionary_t rldict;
    491       1.1     rmind 	nl_rule_t *rl;
    492       1.1     rmind 
    493       1.5  christos 	rl = malloc(sizeof(*rl));
    494       1.1     rmind 	if (rl == NULL) {
    495       1.1     rmind 		return NULL;
    496       1.1     rmind 	}
    497       1.1     rmind 	rldict = prop_dictionary_create();
    498       1.1     rmind 	if (rldict == NULL) {
    499       1.1     rmind 		free(rl);
    500       1.1     rmind 		return NULL;
    501       1.1     rmind 	}
    502       1.1     rmind 	if (name) {
    503       1.1     rmind 		prop_dictionary_set_cstring(rldict, "name", name);
    504       1.1     rmind 	}
    505       1.1     rmind 	prop_dictionary_set_uint32(rldict, "attributes", attr);
    506       1.1     rmind 
    507      1.22     rmind 	if (ifname) {
    508      1.22     rmind 		prop_dictionary_set_cstring(rldict, "interface", ifname);
    509       1.1     rmind 	}
    510       1.1     rmind 	rl->nrl_dict = rldict;
    511       1.1     rmind 	return rl;
    512       1.1     rmind }
    513       1.1     rmind 
    514       1.1     rmind int
    515      1.16     rmind npf_rule_setcode(nl_rule_t *rl, int type, const void *code, size_t len)
    516       1.1     rmind {
    517       1.1     rmind 	prop_dictionary_t rldict = rl->nrl_dict;
    518       1.1     rmind 	prop_data_t cdata;
    519       1.1     rmind 
    520      1.16     rmind 	switch (type) {
    521      1.16     rmind 	case NPF_CODE_NC:
    522      1.16     rmind 	case NPF_CODE_BPF:
    523      1.16     rmind 		break;
    524      1.16     rmind 	default:
    525       1.1     rmind 		return ENOTSUP;
    526       1.1     rmind 	}
    527      1.16     rmind 	prop_dictionary_set_uint32(rldict, "code-type", type);
    528      1.16     rmind 	if ((cdata = prop_data_create_data(code, len)) == NULL) {
    529       1.1     rmind 		return ENOMEM;
    530       1.1     rmind 	}
    531      1.16     rmind 	prop_dictionary_set(rldict, "code", cdata);
    532       1.1     rmind 	prop_object_release(cdata);
    533       1.1     rmind 	return 0;
    534       1.1     rmind }
    535       1.1     rmind 
    536       1.1     rmind int
    537      1.16     rmind npf_rule_setkey(nl_rule_t *rl, const void *key, size_t len)
    538       1.1     rmind {
    539       1.1     rmind 	prop_dictionary_t rldict = rl->nrl_dict;
    540      1.16     rmind 	prop_data_t kdata;
    541       1.1     rmind 
    542      1.16     rmind 	if ((kdata = prop_data_create_data(key, len)) == NULL) {
    543      1.16     rmind 		return ENOMEM;
    544       1.1     rmind 	}
    545      1.16     rmind 	prop_dictionary_set(rldict, "key", kdata);
    546      1.16     rmind 	prop_object_release(kdata);
    547      1.16     rmind 	return 0;
    548      1.16     rmind }
    549      1.16     rmind 
    550      1.16     rmind int
    551      1.20     rmind npf_rule_setinfo(nl_rule_t *rl, const void *info, size_t len)
    552      1.20     rmind {
    553      1.20     rmind 	prop_dictionary_t rldict = rl->nrl_dict;
    554      1.20     rmind 	prop_data_t idata;
    555      1.20     rmind 
    556      1.20     rmind 	if ((idata = prop_data_create_data(info, len)) == NULL) {
    557      1.20     rmind 		return ENOMEM;
    558      1.20     rmind 	}
    559      1.20     rmind 	prop_dictionary_set(rldict, "info", idata);
    560      1.20     rmind 	prop_object_release(idata);
    561      1.20     rmind 	return 0;
    562      1.20     rmind }
    563      1.20     rmind 
    564      1.20     rmind int
    565      1.16     rmind npf_rule_setprio(nl_rule_t *rl, pri_t pri)
    566      1.16     rmind {
    567      1.16     rmind 	prop_dictionary_t rldict = rl->nrl_dict;
    568      1.16     rmind 
    569      1.16     rmind 	prop_dictionary_set_int32(rldict, "priority", pri);
    570      1.16     rmind 	return 0;
    571      1.16     rmind }
    572      1.16     rmind 
    573      1.16     rmind int
    574      1.16     rmind npf_rule_setproc(nl_rule_t *rl, const char *name)
    575      1.16     rmind {
    576      1.16     rmind 	prop_dictionary_t rldict = rl->nrl_dict;
    577      1.16     rmind 
    578       1.1     rmind 	prop_dictionary_set_cstring(rldict, "rproc", name);
    579       1.1     rmind 	return 0;
    580       1.1     rmind }
    581       1.1     rmind 
    582      1.16     rmind void *
    583      1.16     rmind npf_rule_export(nl_rule_t *rl, size_t *length)
    584      1.16     rmind {
    585      1.16     rmind 	prop_dictionary_t rldict = rl->nrl_dict;
    586      1.16     rmind 	void *xml;
    587      1.16     rmind 
    588      1.16     rmind 	if ((xml = prop_dictionary_externalize(rldict)) == NULL) {
    589      1.16     rmind 		return NULL;
    590      1.16     rmind 	}
    591      1.16     rmind 	*length = strlen(xml);
    592      1.16     rmind 	return xml;
    593      1.16     rmind }
    594      1.16     rmind 
    595       1.1     rmind bool
    596       1.1     rmind npf_rule_exists_p(nl_config_t *ncf, const char *name)
    597       1.1     rmind {
    598       1.1     rmind 	return _npf_prop_array_lookup(ncf->ncf_rules_list, "name", name);
    599       1.1     rmind }
    600       1.1     rmind 
    601       1.1     rmind int
    602      1.16     rmind npf_rule_insert(nl_config_t *ncf, nl_rule_t *parent, nl_rule_t *rl)
    603       1.1     rmind {
    604       1.1     rmind 	prop_dictionary_t rldict = rl->nrl_dict;
    605       1.1     rmind 	prop_array_t rlset;
    606       1.1     rmind 
    607       1.1     rmind 	if (parent) {
    608       1.1     rmind 		prop_dictionary_t pdict = parent->nrl_dict;
    609       1.1     rmind 		rlset = prop_dictionary_get(pdict, "subrules");
    610       1.1     rmind 		if (rlset == NULL) {
    611       1.1     rmind 			rlset = prop_array_create();
    612       1.1     rmind 			prop_dictionary_set(pdict, "subrules", rlset);
    613       1.1     rmind 			prop_object_release(rlset);
    614       1.1     rmind 		}
    615       1.1     rmind 	} else {
    616       1.1     rmind 		rlset = ncf->ncf_rules_list;
    617       1.1     rmind 	}
    618       1.1     rmind 	prop_array_add(rlset, rldict);
    619       1.1     rmind 	return 0;
    620       1.1     rmind }
    621       1.1     rmind 
    622      1.20     rmind static nl_rule_t *
    623      1.20     rmind _npf_rule_iterate1(nl_config_t *ncf, prop_array_t rlist, unsigned *level)
    624      1.20     rmind {
    625      1.20     rmind 	prop_dictionary_t rldict;
    626      1.20     rmind 	uint32_t skipto = 0;
    627      1.20     rmind 
    628      1.20     rmind 	if (!ncf->ncf_rule_iter) {
    629      1.20     rmind 		/* Initialise the iterator. */
    630      1.20     rmind 		ncf->ncf_rule_iter = prop_array_iterator(rlist);
    631      1.20     rmind 		ncf->ncf_nlevel = 0;
    632      1.20     rmind 		ncf->ncf_reduce[0] = 0;
    633      1.20     rmind 		ncf->ncf_counter = 0;
    634      1.20     rmind 	}
    635      1.20     rmind 
    636      1.20     rmind 	rldict = prop_object_iterator_next(ncf->ncf_rule_iter);
    637      1.20     rmind 	if ((ncf->ncf_cur_rule.nrl_dict = rldict) == NULL) {
    638      1.20     rmind 		prop_object_iterator_release(ncf->ncf_rule_iter);
    639      1.20     rmind 		ncf->ncf_rule_iter = NULL;
    640      1.20     rmind 		return NULL;
    641      1.20     rmind 	}
    642      1.20     rmind 	*level = ncf->ncf_nlevel;
    643      1.20     rmind 
    644      1.20     rmind 	prop_dictionary_get_uint32(rldict, "skip-to", &skipto);
    645      1.20     rmind 	if (skipto) {
    646      1.20     rmind 		ncf->ncf_nlevel++;
    647      1.20     rmind 		ncf->ncf_reduce[ncf->ncf_nlevel] = skipto;
    648      1.20     rmind 	}
    649      1.20     rmind 	if (ncf->ncf_reduce[ncf->ncf_nlevel] == ++ncf->ncf_counter) {
    650      1.20     rmind 		assert(ncf->ncf_nlevel > 0);
    651      1.20     rmind 		ncf->ncf_nlevel--;
    652      1.20     rmind 	}
    653      1.20     rmind 	return &ncf->ncf_cur_rule;
    654      1.20     rmind }
    655      1.20     rmind 
    656      1.20     rmind nl_rule_t *
    657      1.20     rmind npf_rule_iterate(nl_config_t *ncf, unsigned *level)
    658      1.20     rmind {
    659      1.20     rmind 	return _npf_rule_iterate1(ncf, ncf->ncf_rules_list, level);
    660      1.20     rmind }
    661      1.20     rmind 
    662      1.20     rmind const char *
    663      1.20     rmind npf_rule_getname(nl_rule_t *rl)
    664      1.20     rmind {
    665      1.20     rmind 	prop_dictionary_t rldict = rl->nrl_dict;
    666      1.20     rmind 	const char *rname = NULL;
    667      1.20     rmind 
    668      1.20     rmind 	prop_dictionary_get_cstring_nocopy(rldict, "name", &rname);
    669      1.20     rmind 	return rname;
    670      1.20     rmind }
    671      1.20     rmind 
    672      1.20     rmind uint32_t
    673      1.20     rmind npf_rule_getattr(nl_rule_t *rl)
    674      1.20     rmind {
    675      1.20     rmind 	prop_dictionary_t rldict = rl->nrl_dict;
    676      1.20     rmind 	uint32_t attr = 0;
    677      1.20     rmind 
    678      1.20     rmind 	prop_dictionary_get_uint32(rldict, "attributes", &attr);
    679      1.20     rmind 	return attr;
    680      1.20     rmind }
    681      1.20     rmind 
    682      1.22     rmind const char *
    683      1.20     rmind npf_rule_getinterface(nl_rule_t *rl)
    684      1.20     rmind {
    685      1.20     rmind 	prop_dictionary_t rldict = rl->nrl_dict;
    686      1.22     rmind 	const char *ifname = NULL;
    687      1.20     rmind 
    688      1.22     rmind 	prop_dictionary_get_cstring_nocopy(rldict, "interface", &ifname);
    689      1.22     rmind 	return ifname;
    690      1.20     rmind }
    691      1.20     rmind 
    692      1.20     rmind const void *
    693      1.20     rmind npf_rule_getinfo(nl_rule_t *rl, size_t *len)
    694      1.20     rmind {
    695      1.20     rmind 	prop_dictionary_t rldict = rl->nrl_dict;
    696      1.20     rmind 	prop_object_t obj = prop_dictionary_get(rldict, "info");
    697      1.20     rmind 
    698      1.20     rmind 	*len = prop_data_size(obj);
    699      1.20     rmind 	return prop_data_data_nocopy(obj);
    700      1.20     rmind }
    701      1.20     rmind 
    702      1.20     rmind const char *
    703      1.20     rmind npf_rule_getproc(nl_rule_t *rl)
    704      1.20     rmind {
    705      1.20     rmind 	prop_dictionary_t rldict = rl->nrl_dict;
    706      1.20     rmind 	const char *rpname = NULL;
    707      1.20     rmind 
    708      1.20     rmind 	prop_dictionary_get_cstring_nocopy(rldict, "rproc", &rpname);
    709      1.20     rmind 	return rpname;
    710      1.20     rmind }
    711      1.20     rmind 
    712      1.17     rmind int
    713      1.17     rmind _npf_ruleset_list(int fd, const char *rname, nl_config_t *ncf)
    714      1.17     rmind {
    715      1.17     rmind 	prop_dictionary_t rldict, ret;
    716      1.17     rmind 	int error;
    717      1.17     rmind 
    718      1.17     rmind 	rldict = prop_dictionary_create();
    719      1.17     rmind 	if (rldict == NULL) {
    720      1.17     rmind 		return ENOMEM;
    721      1.17     rmind 	}
    722      1.17     rmind 	prop_dictionary_set_cstring(rldict, "ruleset-name", rname);
    723      1.17     rmind 	prop_dictionary_set_uint32(rldict, "command", NPF_CMD_RULE_LIST);
    724      1.17     rmind 	error = prop_dictionary_sendrecv_ioctl(rldict, fd, IOC_NPF_RULE, &ret);
    725      1.17     rmind 	if (!error) {
    726      1.17     rmind 		prop_array_t rules;
    727      1.17     rmind 
    728      1.17     rmind 		rules = prop_dictionary_get(ret, "rules");
    729      1.17     rmind 		if (rules == NULL) {
    730      1.17     rmind 			return EINVAL;
    731      1.17     rmind 		}
    732      1.17     rmind 		prop_object_release(ncf->ncf_rules_list);
    733      1.17     rmind 		ncf->ncf_rules_list = rules;
    734      1.17     rmind 	}
    735      1.17     rmind 	return error;
    736      1.17     rmind }
    737      1.17     rmind 
    738       1.1     rmind void
    739       1.1     rmind npf_rule_destroy(nl_rule_t *rl)
    740       1.1     rmind {
    741       1.1     rmind 
    742       1.1     rmind 	prop_object_release(rl->nrl_dict);
    743       1.1     rmind 	free(rl);
    744       1.1     rmind }
    745       1.1     rmind 
    746       1.1     rmind /*
    747       1.1     rmind  * RULE PROCEDURE INTERFACE.
    748       1.1     rmind  */
    749       1.1     rmind 
    750       1.1     rmind nl_rproc_t *
    751       1.1     rmind npf_rproc_create(const char *name)
    752       1.1     rmind {
    753       1.1     rmind 	prop_dictionary_t rpdict;
    754      1.13     rmind 	prop_array_t extcalls;
    755       1.1     rmind 	nl_rproc_t *nrp;
    756       1.1     rmind 
    757       1.1     rmind 	nrp = malloc(sizeof(nl_rproc_t));
    758       1.1     rmind 	if (nrp == NULL) {
    759       1.1     rmind 		return NULL;
    760       1.1     rmind 	}
    761       1.1     rmind 	rpdict = prop_dictionary_create();
    762       1.1     rmind 	if (rpdict == NULL) {
    763       1.1     rmind 		free(nrp);
    764       1.1     rmind 		return NULL;
    765       1.1     rmind 	}
    766       1.1     rmind 	prop_dictionary_set_cstring(rpdict, "name", name);
    767      1.13     rmind 
    768      1.13     rmind 	extcalls = prop_array_create();
    769      1.13     rmind 	if (extcalls == NULL) {
    770      1.13     rmind 		prop_object_release(rpdict);
    771      1.13     rmind 		free(nrp);
    772      1.13     rmind 		return NULL;
    773      1.13     rmind 	}
    774      1.13     rmind 	prop_dictionary_set(rpdict, "extcalls", extcalls);
    775      1.13     rmind 	prop_object_release(extcalls);
    776      1.13     rmind 
    777       1.1     rmind 	nrp->nrp_dict = rpdict;
    778       1.1     rmind 	return nrp;
    779       1.1     rmind }
    780       1.1     rmind 
    781       1.1     rmind int
    782      1.13     rmind npf_rproc_extcall(nl_rproc_t *rp, nl_ext_t *ext)
    783       1.1     rmind {
    784       1.1     rmind 	prop_dictionary_t rpdict = rp->nrp_dict;
    785      1.13     rmind 	prop_dictionary_t extdict = ext->nxt_dict;
    786      1.13     rmind 	prop_array_t extcalls;
    787       1.1     rmind 
    788      1.13     rmind 	extcalls = prop_dictionary_get(rpdict, "extcalls");
    789      1.13     rmind 	if (_npf_prop_array_lookup(extcalls, "name", ext->nxt_name)) {
    790      1.13     rmind 		return EEXIST;
    791      1.13     rmind 	}
    792      1.13     rmind 	prop_dictionary_set_cstring(extdict, "name", ext->nxt_name);
    793      1.13     rmind 	prop_array_add(extcalls, extdict);
    794       1.1     rmind 	return 0;
    795       1.1     rmind }
    796       1.1     rmind 
    797      1.13     rmind bool
    798      1.13     rmind npf_rproc_exists_p(nl_config_t *ncf, const char *name)
    799       1.1     rmind {
    800      1.13     rmind 	return _npf_prop_array_lookup(ncf->ncf_rproc_list, "name", name);
    801       1.1     rmind }
    802       1.1     rmind 
    803       1.1     rmind int
    804       1.1     rmind npf_rproc_insert(nl_config_t *ncf, nl_rproc_t *rp)
    805       1.1     rmind {
    806       1.1     rmind 	prop_dictionary_t rpdict = rp->nrp_dict;
    807       1.1     rmind 	const char *name;
    808       1.1     rmind 
    809       1.1     rmind 	if (!prop_dictionary_get_cstring_nocopy(rpdict, "name", &name)) {
    810       1.1     rmind 		return EINVAL;
    811       1.1     rmind 	}
    812       1.1     rmind 	if (npf_rproc_exists_p(ncf, name)) {
    813       1.1     rmind 		return EEXIST;
    814       1.1     rmind 	}
    815       1.1     rmind 	prop_array_add(ncf->ncf_rproc_list, rpdict);
    816       1.1     rmind 	return 0;
    817       1.1     rmind }
    818       1.1     rmind 
    819      1.20     rmind nl_rproc_t *
    820      1.20     rmind npf_rproc_iterate(nl_config_t *ncf)
    821      1.20     rmind {
    822      1.20     rmind 	prop_dictionary_t rpdict;
    823      1.20     rmind 
    824      1.20     rmind 	if (!ncf->ncf_rproc_iter) {
    825      1.20     rmind 		/* Initialise the iterator. */
    826      1.20     rmind 		ncf->ncf_rproc_iter = prop_array_iterator(ncf->ncf_rproc_list);
    827      1.20     rmind 	}
    828      1.20     rmind 	rpdict = prop_object_iterator_next(ncf->ncf_rproc_iter);
    829      1.20     rmind 	if ((ncf->ncf_cur_rproc.nrp_dict = rpdict) == NULL) {
    830      1.20     rmind 		prop_object_iterator_release(ncf->ncf_rproc_iter);
    831      1.20     rmind 		ncf->ncf_rproc_iter = NULL;
    832      1.20     rmind 		return NULL;
    833      1.20     rmind 	}
    834      1.20     rmind 	return &ncf->ncf_cur_rproc;
    835      1.20     rmind }
    836      1.20     rmind 
    837      1.20     rmind const char *
    838      1.20     rmind npf_rproc_getname(nl_rproc_t *rp)
    839      1.20     rmind {
    840      1.20     rmind 	prop_dictionary_t rpdict = rp->nrp_dict;
    841      1.20     rmind 	const char *rpname = NULL;
    842      1.20     rmind 
    843      1.20     rmind 	prop_dictionary_get_cstring_nocopy(rpdict, "name", &rpname);
    844      1.20     rmind 	return rpname;
    845      1.20     rmind }
    846      1.20     rmind 
    847       1.1     rmind /*
    848       1.1     rmind  * TRANSLATION INTERFACE.
    849       1.1     rmind  */
    850       1.1     rmind 
    851       1.1     rmind nl_nat_t *
    852      1.22     rmind npf_nat_create(int type, u_int flags, const char *ifname,
    853      1.28     rmind     int af, npf_addr_t *addr, npf_netmask_t mask, in_port_t port)
    854       1.1     rmind {
    855       1.1     rmind 	nl_rule_t *rl;
    856       1.1     rmind 	prop_dictionary_t rldict;
    857       1.1     rmind 	prop_data_t addrdat;
    858       1.1     rmind 	uint32_t attr;
    859       1.1     rmind 	size_t sz;
    860       1.1     rmind 
    861       1.1     rmind 	if (af == AF_INET) {
    862       1.1     rmind 		sz = sizeof(struct in_addr);
    863       1.1     rmind 	} else if (af == AF_INET6) {
    864       1.1     rmind 		sz = sizeof(struct in6_addr);
    865       1.1     rmind 	} else {
    866       1.1     rmind 		return NULL;
    867       1.1     rmind 	}
    868       1.1     rmind 
    869       1.1     rmind 	attr = NPF_RULE_PASS | NPF_RULE_FINAL |
    870       1.2     rmind 	    (type == NPF_NATOUT ? NPF_RULE_OUT : NPF_RULE_IN);
    871       1.1     rmind 
    872       1.1     rmind 	/* Create a rule for NAT policy.  Next, will add translation data. */
    873      1.22     rmind 	rl = npf_rule_create(NULL, attr, ifname);
    874       1.1     rmind 	if (rl == NULL) {
    875       1.1     rmind 		return NULL;
    876       1.1     rmind 	}
    877       1.1     rmind 	rldict = rl->nrl_dict;
    878       1.1     rmind 
    879       1.1     rmind 	/* Translation type and flags. */
    880       1.1     rmind 	prop_dictionary_set_int32(rldict, "type", type);
    881       1.1     rmind 	prop_dictionary_set_uint32(rldict, "flags", flags);
    882       1.1     rmind 
    883      1.28     rmind 	/* Translation IP and mask. */
    884       1.1     rmind 	addrdat = prop_data_create_data(addr, sz);
    885       1.1     rmind 	if (addrdat == NULL) {
    886       1.1     rmind 		npf_rule_destroy(rl);
    887       1.1     rmind 		return NULL;
    888       1.1     rmind 	}
    889       1.1     rmind 	prop_dictionary_set(rldict, "translation-ip", addrdat);
    890      1.28     rmind 	prop_dictionary_set_uint32(rldict, "translation-mask", mask);
    891       1.1     rmind 	prop_object_release(addrdat);
    892       1.1     rmind 
    893       1.1     rmind 	/* Translation port (for redirect case). */
    894       1.1     rmind 	prop_dictionary_set_uint16(rldict, "translation-port", port);
    895       1.1     rmind 
    896       1.1     rmind 	return (nl_nat_t *)rl;
    897       1.1     rmind }
    898       1.1     rmind 
    899       1.1     rmind int
    900      1.19  christos npf_nat_insert(nl_config_t *ncf, nl_nat_t *nt, pri_t pri __unused)
    901       1.1     rmind {
    902       1.1     rmind 	prop_dictionary_t rldict = nt->nrl_dict;
    903       1.1     rmind 
    904      1.16     rmind 	prop_dictionary_set_int32(rldict, "priority", NPF_PRI_LAST);
    905       1.1     rmind 	prop_array_add(ncf->ncf_nat_list, rldict);
    906       1.1     rmind 	return 0;
    907       1.1     rmind }
    908       1.1     rmind 
    909      1.20     rmind nl_nat_t *
    910      1.20     rmind npf_nat_iterate(nl_config_t *ncf)
    911      1.20     rmind {
    912      1.20     rmind 	u_int level;
    913      1.20     rmind 	return _npf_rule_iterate1(ncf, ncf->ncf_nat_list, &level);
    914      1.20     rmind }
    915      1.20     rmind 
    916      1.20     rmind int
    917      1.28     rmind npf_nat_setalgo(nl_nat_t *nt, u_int algo)
    918      1.28     rmind {
    919      1.28     rmind 	prop_dictionary_t rldict = nt->nrl_dict;
    920      1.28     rmind 	prop_dictionary_set_uint32(rldict, "translation-algo", algo);
    921      1.28     rmind 	return 0;
    922      1.28     rmind }
    923      1.28     rmind 
    924      1.28     rmind int
    925      1.28     rmind npf_nat_setnpt66(nl_nat_t *nt, uint16_t adj)
    926      1.28     rmind {
    927      1.28     rmind 	prop_dictionary_t rldict = nt->nrl_dict;
    928      1.28     rmind 	int error;
    929      1.28     rmind 
    930      1.28     rmind 	if ((error = npf_nat_setalgo(nt, NPF_ALGO_NPT66)) != 0) {
    931      1.28     rmind 		return error;
    932      1.28     rmind 	}
    933      1.28     rmind 	prop_dictionary_set_uint16(rldict, "npt66-adjustment", adj);
    934      1.28     rmind 	return 0;
    935      1.28     rmind }
    936      1.28     rmind 
    937      1.28     rmind int
    938      1.20     rmind npf_nat_gettype(nl_nat_t *nt)
    939      1.20     rmind {
    940      1.20     rmind 	prop_dictionary_t rldict = nt->nrl_dict;
    941      1.20     rmind 	int type = 0;
    942      1.20     rmind 
    943      1.20     rmind 	prop_dictionary_get_int32(rldict, "type", &type);
    944      1.20     rmind 	return type;
    945      1.20     rmind }
    946      1.20     rmind 
    947      1.27     rmind u_int
    948      1.27     rmind npf_nat_getflags(nl_nat_t *nt)
    949      1.27     rmind {
    950      1.27     rmind 	prop_dictionary_t rldict = nt->nrl_dict;
    951      1.27     rmind 	unsigned flags = 0;
    952      1.27     rmind 
    953      1.27     rmind 	prop_dictionary_get_uint32(rldict, "flags", &flags);
    954      1.27     rmind 	return flags;
    955      1.27     rmind }
    956      1.27     rmind 
    957      1.20     rmind void
    958      1.20     rmind npf_nat_getmap(nl_nat_t *nt, npf_addr_t *addr, size_t *alen, in_port_t *port)
    959      1.20     rmind {
    960      1.20     rmind 	prop_dictionary_t rldict = nt->nrl_dict;
    961      1.20     rmind 	prop_object_t obj = prop_dictionary_get(rldict, "translation-ip");
    962      1.20     rmind 
    963      1.20     rmind 	*alen = prop_data_size(obj);
    964      1.20     rmind 	memcpy(addr, prop_data_data_nocopy(obj), *alen);
    965      1.20     rmind 
    966      1.20     rmind 	*port = 0;
    967      1.20     rmind 	prop_dictionary_get_uint16(rldict, "translation-port", port);
    968      1.20     rmind }
    969      1.20     rmind 
    970       1.1     rmind /*
    971       1.1     rmind  * TABLE INTERFACE.
    972       1.1     rmind  */
    973       1.1     rmind 
    974       1.1     rmind nl_table_t *
    975      1.23     rmind npf_table_create(const char *name, u_int id, int type)
    976       1.1     rmind {
    977       1.1     rmind 	prop_dictionary_t tldict;
    978       1.1     rmind 	prop_array_t tblents;
    979       1.1     rmind 	nl_table_t *tl;
    980       1.1     rmind 
    981       1.5  christos 	tl = malloc(sizeof(*tl));
    982       1.1     rmind 	if (tl == NULL) {
    983       1.1     rmind 		return NULL;
    984       1.1     rmind 	}
    985       1.1     rmind 	tldict = prop_dictionary_create();
    986       1.1     rmind 	if (tldict == NULL) {
    987       1.1     rmind 		free(tl);
    988       1.1     rmind 		return NULL;
    989       1.1     rmind 	}
    990      1.23     rmind 	prop_dictionary_set_cstring(tldict, "name", name);
    991       1.1     rmind 	prop_dictionary_set_uint32(tldict, "id", id);
    992       1.1     rmind 	prop_dictionary_set_int32(tldict, "type", type);
    993       1.1     rmind 
    994       1.1     rmind 	tblents = prop_array_create();
    995       1.1     rmind 	if (tblents == NULL) {
    996       1.1     rmind 		prop_object_release(tldict);
    997       1.1     rmind 		free(tl);
    998       1.1     rmind 		return NULL;
    999       1.1     rmind 	}
   1000       1.1     rmind 	prop_dictionary_set(tldict, "entries", tblents);
   1001       1.1     rmind 	prop_object_release(tblents);
   1002       1.1     rmind 
   1003       1.1     rmind 	tl->ntl_dict = tldict;
   1004       1.1     rmind 	return tl;
   1005       1.1     rmind }
   1006       1.1     rmind 
   1007       1.1     rmind int
   1008      1.15     rmind npf_table_add_entry(nl_table_t *tl, int af, const npf_addr_t *addr,
   1009      1.15     rmind     const npf_netmask_t mask)
   1010       1.1     rmind {
   1011       1.1     rmind 	prop_dictionary_t tldict = tl->ntl_dict, entdict;
   1012       1.1     rmind 	prop_array_t tblents;
   1013       1.3    zoltan 	prop_data_t addrdata;
   1014      1.15     rmind 	unsigned alen;
   1015       1.1     rmind 
   1016       1.1     rmind 	/* Create the table entry. */
   1017       1.1     rmind 	entdict = prop_dictionary_create();
   1018      1.10     rmind 	if (entdict == NULL) {
   1019       1.1     rmind 		return ENOMEM;
   1020       1.1     rmind 	}
   1021      1.15     rmind 
   1022      1.15     rmind 	switch (af) {
   1023      1.15     rmind 	case AF_INET:
   1024      1.15     rmind 		alen = sizeof(struct in_addr);
   1025      1.15     rmind 		break;
   1026      1.15     rmind 	case AF_INET6:
   1027      1.15     rmind 		alen = sizeof(struct in6_addr);
   1028      1.15     rmind 		break;
   1029      1.15     rmind 	default:
   1030      1.15     rmind 		return EINVAL;
   1031      1.15     rmind 	}
   1032      1.15     rmind 
   1033      1.10     rmind 	addrdata = prop_data_create_data(addr, alen);
   1034       1.3    zoltan 	prop_dictionary_set(entdict, "addr", addrdata);
   1035       1.3    zoltan 	prop_dictionary_set_uint8(entdict, "mask", mask);
   1036       1.3    zoltan 	prop_object_release(addrdata);
   1037       1.1     rmind 
   1038       1.1     rmind 	tblents = prop_dictionary_get(tldict, "entries");
   1039       1.1     rmind 	prop_array_add(tblents, entdict);
   1040       1.1     rmind 	prop_object_release(entdict);
   1041       1.1     rmind 	return 0;
   1042       1.1     rmind }
   1043       1.1     rmind 
   1044      1.26     rmind int
   1045      1.26     rmind npf_table_setdata(nl_table_t *tl, const void *blob, size_t len)
   1046      1.26     rmind {
   1047      1.26     rmind 	prop_dictionary_t tldict = tl->ntl_dict;
   1048      1.26     rmind 	prop_data_t bobj;
   1049      1.26     rmind 
   1050      1.26     rmind 	if ((bobj = prop_data_create_data(blob, len)) == NULL) {
   1051      1.26     rmind 		return ENOMEM;
   1052      1.26     rmind 	}
   1053      1.26     rmind 	prop_dictionary_set(tldict, "data", bobj);
   1054      1.26     rmind 	prop_object_release(bobj);
   1055      1.26     rmind 	return 0;
   1056      1.26     rmind }
   1057      1.26     rmind 
   1058      1.25     rmind static bool
   1059      1.25     rmind _npf_table_exists_p(nl_config_t *ncf, const char *name)
   1060       1.1     rmind {
   1061       1.1     rmind 	prop_dictionary_t tldict;
   1062       1.1     rmind 	prop_object_iterator_t it;
   1063       1.1     rmind 
   1064       1.1     rmind 	it = prop_array_iterator(ncf->ncf_table_list);
   1065       1.1     rmind 	while ((tldict = prop_object_iterator_next(it)) != NULL) {
   1066      1.24     rmind 		const char *tname = NULL;
   1067      1.24     rmind 
   1068      1.24     rmind 		if (prop_dictionary_get_cstring_nocopy(tldict, "name", &tname)
   1069      1.24     rmind 		    && strcmp(tname, name) == 0)
   1070       1.1     rmind 			break;
   1071       1.1     rmind 	}
   1072       1.1     rmind 	prop_object_iterator_release(it);
   1073       1.1     rmind 	return tldict ? true : false;
   1074       1.1     rmind }
   1075       1.1     rmind 
   1076       1.1     rmind int
   1077       1.1     rmind npf_table_insert(nl_config_t *ncf, nl_table_t *tl)
   1078       1.1     rmind {
   1079       1.1     rmind 	prop_dictionary_t tldict = tl->ntl_dict;
   1080      1.24     rmind 	const char *name = NULL;
   1081       1.1     rmind 
   1082      1.24     rmind 	if (!prop_dictionary_get_cstring_nocopy(tldict, "name", &name)) {
   1083       1.1     rmind 		return EINVAL;
   1084       1.1     rmind 	}
   1085      1.25     rmind 	if (_npf_table_exists_p(ncf, name)) {
   1086       1.1     rmind 		return EEXIST;
   1087       1.1     rmind 	}
   1088       1.1     rmind 	prop_array_add(ncf->ncf_table_list, tldict);
   1089       1.1     rmind 	return 0;
   1090       1.1     rmind }
   1091       1.1     rmind 
   1092      1.20     rmind nl_table_t *
   1093      1.20     rmind npf_table_iterate(nl_config_t *ncf)
   1094      1.20     rmind {
   1095      1.20     rmind 	prop_dictionary_t tldict;
   1096      1.20     rmind 
   1097      1.20     rmind 	if (!ncf->ncf_table_iter) {
   1098      1.20     rmind 		/* Initialise the iterator. */
   1099      1.20     rmind 		ncf->ncf_table_iter = prop_array_iterator(ncf->ncf_table_list);
   1100      1.20     rmind 	}
   1101      1.20     rmind 	tldict = prop_object_iterator_next(ncf->ncf_table_iter);
   1102      1.20     rmind 	if ((ncf->ncf_cur_table.ntl_dict = tldict) == NULL) {
   1103      1.20     rmind 		prop_object_iterator_release(ncf->ncf_table_iter);
   1104      1.20     rmind 		ncf->ncf_table_iter = NULL;
   1105      1.20     rmind 		return NULL;
   1106      1.20     rmind 	}
   1107      1.20     rmind 	return &ncf->ncf_cur_table;
   1108      1.20     rmind }
   1109      1.20     rmind 
   1110      1.20     rmind unsigned
   1111      1.20     rmind npf_table_getid(nl_table_t *tl)
   1112      1.20     rmind {
   1113      1.20     rmind 	prop_dictionary_t tldict = tl->ntl_dict;
   1114      1.23     rmind 	unsigned id = (unsigned)-1;
   1115      1.20     rmind 
   1116      1.20     rmind 	prop_dictionary_get_uint32(tldict, "id", &id);
   1117      1.20     rmind 	return id;
   1118      1.20     rmind }
   1119      1.20     rmind 
   1120      1.23     rmind const char *
   1121      1.23     rmind npf_table_getname(nl_table_t *tl)
   1122      1.23     rmind {
   1123      1.23     rmind 	prop_dictionary_t tldict = tl->ntl_dict;
   1124      1.23     rmind 	const char *tname = NULL;
   1125      1.23     rmind 
   1126      1.23     rmind 	prop_dictionary_get_cstring_nocopy(tldict, "name", &tname);
   1127      1.23     rmind 	return tname;
   1128      1.23     rmind }
   1129      1.23     rmind 
   1130      1.20     rmind int
   1131      1.20     rmind npf_table_gettype(nl_table_t *tl)
   1132      1.20     rmind {
   1133      1.20     rmind 	prop_dictionary_t tldict = tl->ntl_dict;
   1134      1.20     rmind 	int type = 0;
   1135      1.20     rmind 
   1136      1.20     rmind 	prop_dictionary_get_int32(tldict, "type", &type);
   1137      1.20     rmind 	return type;
   1138      1.20     rmind }
   1139      1.20     rmind 
   1140       1.1     rmind void
   1141       1.1     rmind npf_table_destroy(nl_table_t *tl)
   1142       1.1     rmind {
   1143       1.1     rmind 	prop_object_release(tl->ntl_dict);
   1144       1.1     rmind 	free(tl);
   1145       1.1     rmind }
   1146       1.1     rmind 
   1147       1.1     rmind /*
   1148      1.19  christos  * ALG INTERFACE.
   1149      1.19  christos  */
   1150      1.19  christos 
   1151      1.19  christos int
   1152      1.19  christos _npf_alg_load(nl_config_t *ncf, const char *name)
   1153      1.19  christos {
   1154      1.19  christos 	prop_dictionary_t al_dict;
   1155      1.19  christos 
   1156      1.19  christos 	if (_npf_prop_array_lookup(ncf->ncf_alg_list, "name", name))
   1157      1.19  christos 		return EEXIST;
   1158      1.19  christos 
   1159      1.19  christos 	al_dict = prop_dictionary_create();
   1160      1.19  christos 	prop_dictionary_set_cstring(al_dict, "name", name);
   1161      1.19  christos 	prop_array_add(ncf->ncf_alg_list, al_dict);
   1162      1.19  christos 	prop_object_release(al_dict);
   1163      1.19  christos 	return 0;
   1164      1.19  christos }
   1165      1.19  christos 
   1166      1.19  christos int
   1167      1.19  christos _npf_alg_unload(nl_config_t *ncf, const char *name)
   1168      1.19  christos {
   1169      1.19  christos 	if (!_npf_prop_array_lookup(ncf->ncf_alg_list, "name", name))
   1170      1.19  christos 		return ENOENT;
   1171      1.19  christos 
   1172      1.19  christos 	// Not yet: prop_array_add(ncf->ncf_alg_list, al_dict);
   1173      1.19  christos 	return ENOTSUP;
   1174      1.19  christos }
   1175      1.19  christos 
   1176      1.19  christos /*
   1177       1.1     rmind  * MISC.
   1178       1.1     rmind  */
   1179       1.1     rmind 
   1180      1.11     rmind static prop_dictionary_t
   1181      1.11     rmind _npf_debug_initonce(nl_config_t *ncf)
   1182      1.11     rmind {
   1183      1.11     rmind 	if (!ncf->ncf_debug) {
   1184      1.11     rmind 		prop_array_t iflist = prop_array_create();
   1185      1.11     rmind 		ncf->ncf_debug = prop_dictionary_create();
   1186      1.11     rmind 		prop_dictionary_set(ncf->ncf_debug, "interfaces", iflist);
   1187      1.11     rmind 		prop_object_release(iflist);
   1188      1.11     rmind 	}
   1189      1.11     rmind 	return ncf->ncf_debug;
   1190      1.11     rmind }
   1191      1.11     rmind 
   1192      1.11     rmind void
   1193      1.22     rmind _npf_debug_addif(nl_config_t *ncf, const char *ifname)
   1194      1.11     rmind {
   1195      1.11     rmind 	prop_dictionary_t ifdict, dbg = _npf_debug_initonce(ncf);
   1196      1.11     rmind 	prop_array_t iflist = prop_dictionary_get(dbg, "interfaces");
   1197      1.22     rmind 	u_int if_idx = if_nametoindex(ifname);
   1198      1.11     rmind 
   1199      1.22     rmind 	if (_npf_prop_array_lookup(iflist, "name", ifname)) {
   1200      1.11     rmind 		return;
   1201      1.11     rmind 	}
   1202      1.11     rmind 	ifdict = prop_dictionary_create();
   1203      1.22     rmind 	prop_dictionary_set_cstring(ifdict, "name", ifname);
   1204      1.22     rmind 	prop_dictionary_set_uint32(ifdict, "index", if_idx);
   1205      1.11     rmind 	prop_array_add(iflist, ifdict);
   1206      1.11     rmind 	prop_object_release(ifdict);
   1207      1.11     rmind }
   1208