Home | History | Annotate | Line # | Download | only in libnpf
npf.c revision 1.41
      1  1.41  christos /*	$NetBSD: npf.c,v 1.41 2016/12/27 20:14:07 christos Exp $	*/
      2   1.1     rmind 
      3   1.1     rmind /*-
      4  1.35     rmind  * Copyright (c) 2010-2015 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.41  christos __KERNEL_RCSID(0, "$NetBSD: npf.c,v 1.41 2016/12/27 20:14:07 christos 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.34     rmind 	/* Rules, translations, procedures, tables, connections. */
     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.34     rmind 	prop_array_t		ncf_conn_list;
     80  1.20     rmind 
     81  1.20     rmind 	/* Iterators. */
     82  1.20     rmind 	prop_object_iterator_t	ncf_rule_iter;
     83  1.20     rmind 	unsigned		ncf_reduce[16];
     84  1.20     rmind 	unsigned		ncf_nlevel;
     85  1.20     rmind 	unsigned		ncf_counter;
     86  1.20     rmind 	nl_rule_t		ncf_cur_rule;
     87  1.20     rmind 
     88  1.20     rmind 	prop_object_iterator_t	ncf_table_iter;
     89  1.20     rmind 	nl_table_t		ncf_cur_table;
     90  1.20     rmind 
     91  1.20     rmind 	prop_object_iterator_t	ncf_rproc_iter;
     92  1.20     rmind 	nl_rproc_t		ncf_cur_rproc;
     93  1.20     rmind 
     94  1.20     rmind 	/* Error report and debug information. */
     95  1.20     rmind 	prop_dictionary_t	ncf_err;
     96  1.20     rmind 	prop_dictionary_t	ncf_debug;
     97  1.20     rmind 
     98  1.20     rmind 	bool			ncf_flush;
     99  1.20     rmind };
    100  1.20     rmind 
    101  1.16     rmind static prop_array_t	_npf_ruleset_transform(prop_array_t);
    102  1.16     rmind 
    103  1.36  christos static bool
    104  1.36  christos _npf_add_addr(prop_dictionary_t dict, const char *name, int af,
    105  1.36  christos     const npf_addr_t *addr)
    106  1.36  christos {
    107  1.36  christos 	size_t sz;
    108  1.36  christos 
    109  1.36  christos 	if (af == AF_INET) {
    110  1.36  christos 		sz = sizeof(struct in_addr);
    111  1.36  christos 	} else if (af == AF_INET6) {
    112  1.36  christos 		sz = sizeof(struct in6_addr);
    113  1.36  christos 	} else {
    114  1.36  christos 		return false;
    115  1.36  christos 	}
    116  1.36  christos 	prop_data_t addrdat = prop_data_create_data(addr, sz);
    117  1.36  christos 	if (addrdat == NULL) {
    118  1.36  christos 		return false;
    119  1.36  christos 	}
    120  1.36  christos 	prop_dictionary_set(dict, name, addrdat);
    121  1.36  christos 	prop_object_release(addrdat);
    122  1.36  christos 	return true;
    123  1.36  christos }
    124  1.36  christos 
    125  1.41  christos static unsigned
    126  1.36  christos _npf_get_addr(prop_dictionary_t dict, const char *name, npf_addr_t *addr)
    127  1.36  christos {
    128  1.36  christos 	prop_object_t obj = prop_dictionary_get(dict, name);
    129  1.36  christos 	const void *d = prop_data_data_nocopy(obj);
    130  1.36  christos 
    131  1.36  christos 	if (d == NULL)
    132  1.36  christos 		return false;
    133  1.36  christos 
    134  1.36  christos 	size_t sz = prop_data_size(obj);
    135  1.36  christos 	switch (sz) {
    136  1.36  christos 	case sizeof(struct in_addr):
    137  1.36  christos 	case sizeof(struct in6_addr):
    138  1.36  christos 		memcpy(addr, d, sz);
    139  1.41  christos 		return (unsigned)sz;
    140  1.36  christos 	default:
    141  1.41  christos 		return 0;
    142  1.36  christos 	}
    143  1.36  christos }
    144  1.40  christos 
    145   1.1     rmind /*
    146   1.1     rmind  * CONFIGURATION INTERFACE.
    147   1.1     rmind  */
    148   1.1     rmind 
    149   1.1     rmind nl_config_t *
    150   1.1     rmind npf_config_create(void)
    151   1.1     rmind {
    152   1.1     rmind 	nl_config_t *ncf;
    153   1.1     rmind 
    154   1.7     rmind 	ncf = calloc(1, sizeof(*ncf));
    155   1.1     rmind 	if (ncf == NULL) {
    156   1.1     rmind 		return NULL;
    157   1.1     rmind 	}
    158  1.19  christos 	ncf->ncf_alg_list = prop_array_create();
    159   1.1     rmind 	ncf->ncf_rules_list = prop_array_create();
    160   1.1     rmind 	ncf->ncf_rproc_list = prop_array_create();
    161   1.1     rmind 	ncf->ncf_table_list = prop_array_create();
    162   1.1     rmind 	ncf->ncf_nat_list = prop_array_create();
    163   1.6     rmind 	ncf->ncf_flush = false;
    164   1.1     rmind 	return ncf;
    165   1.1     rmind }
    166   1.1     rmind 
    167  1.40  christos static prop_dictionary_t
    168  1.40  christos _npf_build_config(nl_config_t *ncf)
    169   1.1     rmind {
    170   1.1     rmind 	prop_dictionary_t npf_dict;
    171  1.16     rmind 	prop_array_t rlset;
    172   1.1     rmind 
    173   1.1     rmind 	npf_dict = prop_dictionary_create();
    174   1.1     rmind 	if (npf_dict == NULL) {
    175  1.40  christos 		return NULL;
    176   1.1     rmind 	}
    177  1.15     rmind 	prop_dictionary_set_uint32(npf_dict, "version", NPF_VERSION);
    178  1.16     rmind 
    179  1.16     rmind 	rlset = _npf_ruleset_transform(ncf->ncf_rules_list);
    180  1.16     rmind 	if (rlset == NULL) {
    181  1.16     rmind 		prop_object_release(npf_dict);
    182  1.40  christos 		return NULL;
    183  1.16     rmind 	}
    184  1.20     rmind 	prop_object_release(ncf->ncf_rules_list);
    185  1.20     rmind 	ncf->ncf_rules_list = rlset;
    186  1.16     rmind 
    187  1.20     rmind 	prop_dictionary_set(npf_dict, "rules", ncf->ncf_rules_list);
    188  1.19  christos 	prop_dictionary_set(npf_dict, "algs", ncf->ncf_alg_list);
    189   1.1     rmind 	prop_dictionary_set(npf_dict, "rprocs", ncf->ncf_rproc_list);
    190   1.1     rmind 	prop_dictionary_set(npf_dict, "tables", ncf->ncf_table_list);
    191  1.32     rmind 	prop_dictionary_set(npf_dict, "nat", ncf->ncf_nat_list);
    192  1.34     rmind 	if (ncf->ncf_conn_list) {
    193  1.34     rmind 		prop_dictionary_set(npf_dict, "conn-list",
    194  1.34     rmind 		    ncf->ncf_conn_list);
    195  1.34     rmind 	}
    196   1.6     rmind 	prop_dictionary_set_bool(npf_dict, "flush", ncf->ncf_flush);
    197  1.15     rmind 	if (ncf->ncf_debug) {
    198  1.15     rmind 		prop_dictionary_set(npf_dict, "debug", ncf->ncf_debug);
    199  1.15     rmind 	}
    200  1.40  christos 	return npf_dict;
    201  1.40  christos }
    202   1.1     rmind 
    203  1.40  christos int
    204  1.40  christos npf_config_submit(nl_config_t *ncf, int fd, npf_error_t *errinfo)
    205  1.40  christos {
    206  1.40  christos #if !defined(_NPF_STANDALONE)
    207  1.40  christos 	prop_dictionary_t npf_dict;
    208  1.40  christos 	int error = 0;
    209  1.40  christos 
    210  1.40  christos 	npf_dict = _npf_build_config(ncf);
    211  1.40  christos 	if (!npf_dict) {
    212  1.40  christos 		return ENOMEM;
    213  1.40  christos 	}
    214  1.40  christos 	error = prop_dictionary_sendrecv_ioctl(npf_dict, fd,
    215  1.40  christos 	    IOC_NPF_LOAD, &ncf->ncf_err);
    216  1.40  christos 	if (error) {
    217   1.7     rmind 		prop_object_release(npf_dict);
    218  1.40  christos 		assert(ncf->ncf_err == NULL);
    219   1.7     rmind 		return error;
    220   1.7     rmind 	}
    221  1.40  christos 	prop_dictionary_get_int32(ncf->ncf_err, "errno", &error);
    222  1.40  christos 	if (error) {
    223  1.40  christos 		memset(errinfo, 0, sizeof(*errinfo));
    224  1.40  christos 
    225  1.40  christos 		prop_dictionary_get_int64(ncf->ncf_err, "id",
    226  1.40  christos 		    &errinfo->id);
    227  1.40  christos 		prop_dictionary_get_cstring(ncf->ncf_err,
    228  1.40  christos 		    "source-file", &errinfo->source_file);
    229  1.40  christos 		prop_dictionary_get_uint32(ncf->ncf_err,
    230  1.40  christos 		    "source-line", &errinfo->source_line);
    231   1.1     rmind 	}
    232   1.1     rmind 	prop_object_release(npf_dict);
    233   1.1     rmind 	return error;
    234  1.40  christos #else
    235  1.40  christos 	(void)ncf; (void)fd;
    236  1.40  christos 	return ENOTSUP;
    237  1.40  christos #endif
    238   1.1     rmind }
    239   1.1     rmind 
    240  1.30     rmind static nl_config_t *
    241  1.30     rmind _npf_config_consdict(prop_dictionary_t npf_dict)
    242  1.30     rmind {
    243  1.30     rmind 	nl_config_t *ncf;
    244  1.30     rmind 
    245  1.30     rmind 	ncf = calloc(1, sizeof(*ncf));
    246  1.30     rmind 	if (ncf == NULL) {
    247  1.30     rmind 		return NULL;
    248  1.30     rmind 	}
    249  1.30     rmind 	ncf->ncf_dict = npf_dict;
    250  1.30     rmind 	ncf->ncf_alg_list = prop_dictionary_get(npf_dict, "algs");
    251  1.30     rmind 	ncf->ncf_rules_list = prop_dictionary_get(npf_dict, "rules");
    252  1.30     rmind 	ncf->ncf_rproc_list = prop_dictionary_get(npf_dict, "rprocs");
    253  1.30     rmind 	ncf->ncf_table_list = prop_dictionary_get(npf_dict, "tables");
    254  1.32     rmind 	ncf->ncf_nat_list = prop_dictionary_get(npf_dict, "nat");
    255  1.34     rmind 	ncf->ncf_conn_list = prop_dictionary_get(npf_dict, "conn-list");
    256  1.30     rmind 	return ncf;
    257  1.30     rmind }
    258  1.30     rmind 
    259   1.8     rmind nl_config_t *
    260  1.40  christos npf_config_retrieve(int fd)
    261   1.8     rmind {
    262   1.8     rmind 	prop_dictionary_t npf_dict;
    263   1.8     rmind 	nl_config_t *ncf;
    264   1.8     rmind 	int error;
    265   1.8     rmind 
    266  1.40  christos #ifdef _NPF_STANDALONE
    267  1.40  christos 	error = ENOTSUP;
    268  1.40  christos #else
    269  1.30     rmind 	error = prop_dictionary_recv_ioctl(fd, IOC_NPF_SAVE, &npf_dict);
    270  1.40  christos #endif
    271   1.8     rmind 	if (error) {
    272   1.8     rmind 		return NULL;
    273   1.8     rmind 	}
    274  1.30     rmind 	ncf = _npf_config_consdict(npf_dict);
    275   1.8     rmind 	if (ncf == NULL) {
    276   1.8     rmind 		prop_object_release(npf_dict);
    277   1.8     rmind 		return NULL;
    278   1.8     rmind 	}
    279   1.8     rmind 	return ncf;
    280   1.8     rmind }
    281   1.8     rmind 
    282  1.40  christos void *
    283  1.40  christos npf_config_export(nl_config_t *ncf, size_t *length)
    284  1.30     rmind {
    285  1.30     rmind 	prop_dictionary_t npf_dict = ncf->ncf_dict;
    286  1.40  christos 	void *blob;
    287  1.30     rmind 
    288  1.40  christos 	if (!npf_dict && (npf_dict = _npf_build_config(ncf)) == NULL) {
    289  1.40  christos 		errno = ENOMEM;
    290  1.40  christos 		return NULL;
    291  1.30     rmind 	}
    292  1.40  christos 	if ((blob = prop_dictionary_externalize(npf_dict)) == NULL) {
    293  1.40  christos 		prop_object_release(npf_dict);
    294  1.40  christos 		return NULL;
    295  1.40  christos 	}
    296  1.40  christos 	prop_object_release(npf_dict);
    297  1.40  christos 	*length = strlen(blob);
    298  1.40  christos 	return blob;
    299  1.30     rmind }
    300  1.30     rmind 
    301  1.30     rmind nl_config_t *
    302  1.40  christos npf_config_import(const void *blob, size_t len __unused)
    303  1.30     rmind {
    304  1.30     rmind 	prop_dictionary_t npf_dict;
    305  1.30     rmind 	nl_config_t *ncf;
    306  1.30     rmind 
    307  1.40  christos 	npf_dict = prop_dictionary_internalize(blob);
    308  1.33     rmind 	if (!npf_dict) {
    309  1.30     rmind 		return NULL;
    310  1.30     rmind 	}
    311  1.30     rmind 	ncf = _npf_config_consdict(npf_dict);
    312  1.33     rmind 	if (!ncf) {
    313  1.30     rmind 		prop_object_release(npf_dict);
    314  1.30     rmind 		return NULL;
    315  1.30     rmind 	}
    316  1.30     rmind 	return ncf;
    317  1.30     rmind }
    318  1.30     rmind 
    319  1.30     rmind int
    320   1.6     rmind npf_config_flush(int fd)
    321   1.6     rmind {
    322   1.6     rmind 	nl_config_t *ncf;
    323  1.40  christos 	npf_error_t errinfo;
    324   1.6     rmind 	int error;
    325   1.6     rmind 
    326   1.6     rmind 	ncf = npf_config_create();
    327   1.6     rmind 	if (ncf == NULL) {
    328   1.6     rmind 		return ENOMEM;
    329   1.6     rmind 	}
    330   1.6     rmind 	ncf->ncf_flush = true;
    331  1.40  christos 	error = npf_config_submit(ncf, fd, &errinfo);
    332   1.6     rmind 	npf_config_destroy(ncf);
    333   1.6     rmind 	return error;
    334   1.6     rmind }
    335   1.6     rmind 
    336  1.40  christos bool
    337  1.40  christos npf_config_active_p(nl_config_t *ncf)
    338  1.40  christos {
    339  1.40  christos 	bool active = false;
    340  1.40  christos 	prop_dictionary_get_bool(ncf->ncf_dict, "active", &active);
    341  1.40  christos 	return active;
    342  1.40  christos }
    343  1.40  christos 
    344  1.40  christos bool
    345  1.40  christos npf_config_loaded_p(nl_config_t *ncf)
    346  1.40  christos {
    347  1.40  christos 	return ncf->ncf_rules_list != NULL;
    348  1.40  christos }
    349  1.40  christos 
    350  1.40  christos void *
    351  1.40  christos npf_config_build(nl_config_t *ncf)
    352   1.7     rmind {
    353  1.40  christos 	if (!ncf->ncf_dict && !(ncf->ncf_dict = _npf_build_config(ncf))) {
    354  1.40  christos 		errno = ENOMEM;
    355  1.40  christos 		return NULL;
    356  1.40  christos 	}
    357  1.40  christos 	return (void *)ncf->ncf_dict;
    358   1.7     rmind }
    359   1.7     rmind 
    360   1.7     rmind void
    361   1.1     rmind npf_config_destroy(nl_config_t *ncf)
    362   1.1     rmind {
    363  1.14     rmind 	if (!ncf->ncf_dict) {
    364  1.19  christos 		prop_object_release(ncf->ncf_alg_list);
    365   1.8     rmind 		prop_object_release(ncf->ncf_rules_list);
    366   1.8     rmind 		prop_object_release(ncf->ncf_rproc_list);
    367   1.8     rmind 		prop_object_release(ncf->ncf_table_list);
    368   1.8     rmind 		prop_object_release(ncf->ncf_nat_list);
    369   1.8     rmind 	}
    370   1.7     rmind 	if (ncf->ncf_err) {
    371   1.7     rmind 		prop_object_release(ncf->ncf_err);
    372   1.7     rmind 	}
    373  1.11     rmind 	if (ncf->ncf_debug) {
    374  1.11     rmind 		prop_object_release(ncf->ncf_debug);
    375  1.11     rmind 	}
    376   1.1     rmind 	free(ncf);
    377   1.1     rmind }
    378   1.1     rmind 
    379   1.1     rmind static bool
    380   1.1     rmind _npf_prop_array_lookup(prop_array_t array, const char *key, const char *name)
    381   1.1     rmind {
    382   1.1     rmind 	prop_dictionary_t dict;
    383   1.1     rmind 	prop_object_iterator_t it;
    384   1.1     rmind 
    385   1.1     rmind 	it = prop_array_iterator(array);
    386   1.1     rmind 	while ((dict = prop_object_iterator_next(it)) != NULL) {
    387   1.1     rmind 		const char *lname;
    388   1.1     rmind 		prop_dictionary_get_cstring_nocopy(dict, key, &lname);
    389   1.1     rmind 		if (strcmp(name, lname) == 0)
    390   1.1     rmind 			break;
    391   1.1     rmind 	}
    392   1.1     rmind 	prop_object_iterator_release(it);
    393   1.1     rmind 	return dict ? true : false;
    394   1.1     rmind }
    395   1.1     rmind 
    396   1.1     rmind /*
    397  1.16     rmind  * DYNAMIC RULESET INTERFACE.
    398  1.16     rmind  */
    399  1.16     rmind 
    400  1.16     rmind int
    401  1.18     rmind npf_ruleset_add(int fd, const char *rname, nl_rule_t *rl, uint64_t *id)
    402  1.16     rmind {
    403  1.16     rmind 	prop_dictionary_t rldict = rl->nrl_dict;
    404  1.16     rmind 	prop_dictionary_t ret;
    405  1.16     rmind 	int error;
    406  1.16     rmind 
    407  1.16     rmind 	prop_dictionary_set_cstring(rldict, "ruleset-name", rname);
    408  1.16     rmind 	prop_dictionary_set_uint32(rldict, "command", NPF_CMD_RULE_ADD);
    409  1.40  christos #ifdef _NPF_STANDALONE
    410  1.40  christos 	error = ENOTSUP;
    411  1.40  christos #else
    412  1.16     rmind 	error = prop_dictionary_sendrecv_ioctl(rldict, fd, IOC_NPF_RULE, &ret);
    413  1.40  christos #endif
    414  1.16     rmind 	if (!error) {
    415  1.18     rmind 		prop_dictionary_get_uint64(ret, "id", id);
    416  1.16     rmind 	}
    417  1.16     rmind 	return error;
    418  1.16     rmind }
    419  1.16     rmind 
    420  1.16     rmind int
    421  1.18     rmind npf_ruleset_remove(int fd, const char *rname, uint64_t id)
    422  1.16     rmind {
    423  1.16     rmind 	prop_dictionary_t rldict;
    424  1.16     rmind 
    425  1.16     rmind 	rldict = prop_dictionary_create();
    426  1.16     rmind 	if (rldict == NULL) {
    427  1.16     rmind 		return ENOMEM;
    428  1.16     rmind 	}
    429  1.16     rmind 	prop_dictionary_set_cstring(rldict, "ruleset-name", rname);
    430  1.16     rmind 	prop_dictionary_set_uint32(rldict, "command", NPF_CMD_RULE_REMOVE);
    431  1.18     rmind 	prop_dictionary_set_uint64(rldict, "id", id);
    432  1.40  christos #ifdef _NPF_STANDALONE
    433  1.40  christos 	return ENOTSUP;
    434  1.40  christos #else
    435  1.16     rmind 	return prop_dictionary_send_ioctl(rldict, fd, IOC_NPF_RULE);
    436  1.40  christos #endif
    437  1.16     rmind }
    438  1.16     rmind 
    439  1.16     rmind int
    440  1.16     rmind npf_ruleset_remkey(int fd, const char *rname, const void *key, size_t len)
    441  1.16     rmind {
    442  1.16     rmind 	prop_dictionary_t rldict;
    443  1.16     rmind 	prop_data_t keyobj;
    444  1.16     rmind 
    445  1.16     rmind 	rldict = prop_dictionary_create();
    446  1.16     rmind 	if (rldict == NULL) {
    447  1.16     rmind 		return ENOMEM;
    448  1.16     rmind 	}
    449  1.16     rmind 	prop_dictionary_set_cstring(rldict, "ruleset-name", rname);
    450  1.16     rmind 	prop_dictionary_set_uint32(rldict, "command", NPF_CMD_RULE_REMKEY);
    451  1.16     rmind 
    452  1.16     rmind 	keyobj = prop_data_create_data(key, len);
    453  1.16     rmind 	if (keyobj == NULL) {
    454  1.16     rmind 		prop_object_release(rldict);
    455  1.16     rmind 		return ENOMEM;
    456  1.16     rmind 	}
    457  1.16     rmind 	prop_dictionary_set(rldict, "key", keyobj);
    458  1.16     rmind 	prop_object_release(keyobj);
    459  1.16     rmind 
    460  1.40  christos #ifdef _NPF_STANDALONE
    461  1.40  christos 	return ENOTSUP;
    462  1.40  christos #else
    463  1.16     rmind 	return prop_dictionary_send_ioctl(rldict, fd, IOC_NPF_RULE);
    464  1.40  christos #endif
    465  1.16     rmind }
    466  1.16     rmind 
    467  1.17     rmind int
    468  1.17     rmind npf_ruleset_flush(int fd, const char *rname)
    469  1.17     rmind {
    470  1.17     rmind 	prop_dictionary_t rldict;
    471  1.17     rmind 
    472  1.17     rmind 	rldict = prop_dictionary_create();
    473  1.17     rmind 	if (rldict == NULL) {
    474  1.17     rmind 		return ENOMEM;
    475  1.17     rmind 	}
    476  1.17     rmind 	prop_dictionary_set_cstring(rldict, "ruleset-name", rname);
    477  1.17     rmind 	prop_dictionary_set_uint32(rldict, "command", NPF_CMD_RULE_FLUSH);
    478  1.40  christos #ifdef _NPF_STANDALONE
    479  1.40  christos 	return ENOTSUP;
    480  1.40  christos #else
    481  1.17     rmind 	return prop_dictionary_send_ioctl(rldict, fd, IOC_NPF_RULE);
    482  1.40  christos #endif
    483  1.17     rmind }
    484  1.17     rmind 
    485  1.16     rmind /*
    486  1.16     rmind  * _npf_ruleset_transform: transform the ruleset representing nested
    487  1.16     rmind  * rules with lists into an array.
    488  1.16     rmind  */
    489  1.16     rmind 
    490  1.16     rmind static void
    491  1.16     rmind _npf_ruleset_transform1(prop_array_t rlset, prop_array_t rules)
    492  1.16     rmind {
    493  1.16     rmind 	prop_object_iterator_t it;
    494  1.16     rmind 	prop_dictionary_t rldict;
    495  1.16     rmind 	prop_array_t subrlset;
    496  1.16     rmind 
    497  1.16     rmind 	it = prop_array_iterator(rules);
    498  1.16     rmind 	while ((rldict = prop_object_iterator_next(it)) != NULL) {
    499  1.16     rmind 		unsigned idx;
    500  1.16     rmind 
    501  1.16     rmind 		/* Add rules to the array (reference is retained). */
    502  1.16     rmind 		prop_array_add(rlset, rldict);
    503  1.16     rmind 
    504  1.16     rmind 		subrlset = prop_dictionary_get(rldict, "subrules");
    505  1.16     rmind 		if (subrlset) {
    506  1.16     rmind 			/* Process subrules recursively. */
    507  1.16     rmind 			_npf_ruleset_transform1(rlset, subrlset);
    508  1.16     rmind 			/* Add the skip-to position. */
    509  1.16     rmind 			idx = prop_array_count(rlset);
    510  1.16     rmind 			prop_dictionary_set_uint32(rldict, "skip-to", idx);
    511  1.16     rmind 			prop_dictionary_remove(rldict, "subrules");
    512  1.16     rmind 		}
    513  1.16     rmind 	}
    514  1.16     rmind 	prop_object_iterator_release(it);
    515  1.16     rmind }
    516  1.16     rmind 
    517  1.16     rmind static prop_array_t
    518  1.16     rmind _npf_ruleset_transform(prop_array_t rlset)
    519  1.16     rmind {
    520  1.16     rmind 	prop_array_t nrlset;
    521  1.16     rmind 
    522  1.16     rmind 	nrlset = prop_array_create();
    523  1.16     rmind 	_npf_ruleset_transform1(nrlset, rlset);
    524  1.16     rmind 	return nrlset;
    525  1.16     rmind }
    526  1.16     rmind 
    527  1.16     rmind /*
    528  1.13     rmind  * NPF EXTENSION INTERFACE.
    529  1.13     rmind  */
    530  1.13     rmind 
    531  1.13     rmind nl_ext_t *
    532  1.13     rmind npf_ext_construct(const char *name)
    533  1.13     rmind {
    534  1.13     rmind 	nl_ext_t *ext;
    535  1.13     rmind 
    536  1.13     rmind 	ext = malloc(sizeof(*ext));
    537  1.13     rmind 	if (ext == NULL) {
    538  1.13     rmind 		return NULL;
    539  1.13     rmind 	}
    540  1.13     rmind 	ext->nxt_name = strdup(name);
    541  1.13     rmind 	if (ext->nxt_name == NULL) {
    542  1.13     rmind 		free(ext);
    543  1.13     rmind 		return NULL;
    544  1.13     rmind 	}
    545  1.13     rmind 	ext->nxt_dict = prop_dictionary_create();
    546  1.13     rmind 
    547  1.13     rmind 	return ext;
    548  1.13     rmind }
    549  1.13     rmind 
    550  1.13     rmind void
    551  1.13     rmind npf_ext_param_u32(nl_ext_t *ext, const char *key, uint32_t val)
    552  1.13     rmind {
    553  1.13     rmind 	prop_dictionary_t extdict = ext->nxt_dict;
    554  1.13     rmind 	prop_dictionary_set_uint32(extdict, key, val);
    555  1.13     rmind }
    556  1.13     rmind 
    557  1.13     rmind void
    558  1.13     rmind npf_ext_param_bool(nl_ext_t *ext, const char *key, bool val)
    559  1.13     rmind {
    560  1.13     rmind 	prop_dictionary_t extdict = ext->nxt_dict;
    561  1.13     rmind 	prop_dictionary_set_bool(extdict, key, val);
    562  1.13     rmind }
    563  1.13     rmind 
    564  1.29  jakllsch void
    565  1.29  jakllsch npf_ext_param_string(nl_ext_t *ext, const char *key, const char *val)
    566  1.29  jakllsch {
    567  1.29  jakllsch 	prop_dictionary_t extdict = ext->nxt_dict;
    568  1.29  jakllsch 	prop_dictionary_set_cstring(extdict, key, val);
    569  1.29  jakllsch }
    570  1.29  jakllsch 
    571  1.13     rmind /*
    572   1.1     rmind  * RULE INTERFACE.
    573   1.1     rmind  */
    574   1.1     rmind 
    575   1.1     rmind nl_rule_t *
    576  1.22     rmind npf_rule_create(const char *name, uint32_t attr, const char *ifname)
    577   1.1     rmind {
    578   1.1     rmind 	prop_dictionary_t rldict;
    579   1.1     rmind 	nl_rule_t *rl;
    580   1.1     rmind 
    581   1.5  christos 	rl = malloc(sizeof(*rl));
    582   1.1     rmind 	if (rl == NULL) {
    583   1.1     rmind 		return NULL;
    584   1.1     rmind 	}
    585   1.1     rmind 	rldict = prop_dictionary_create();
    586   1.1     rmind 	if (rldict == NULL) {
    587   1.1     rmind 		free(rl);
    588   1.1     rmind 		return NULL;
    589   1.1     rmind 	}
    590   1.1     rmind 	if (name) {
    591   1.1     rmind 		prop_dictionary_set_cstring(rldict, "name", name);
    592   1.1     rmind 	}
    593  1.32     rmind 	prop_dictionary_set_uint32(rldict, "attr", attr);
    594   1.1     rmind 
    595  1.22     rmind 	if (ifname) {
    596  1.32     rmind 		prop_dictionary_set_cstring(rldict, "ifname", ifname);
    597   1.1     rmind 	}
    598   1.1     rmind 	rl->nrl_dict = rldict;
    599   1.1     rmind 	return rl;
    600   1.1     rmind }
    601   1.1     rmind 
    602   1.1     rmind int
    603  1.16     rmind npf_rule_setcode(nl_rule_t *rl, int type, const void *code, size_t len)
    604   1.1     rmind {
    605   1.1     rmind 	prop_dictionary_t rldict = rl->nrl_dict;
    606   1.1     rmind 	prop_data_t cdata;
    607   1.1     rmind 
    608  1.16     rmind 	switch (type) {
    609  1.16     rmind 	case NPF_CODE_NC:
    610  1.16     rmind 	case NPF_CODE_BPF:
    611  1.16     rmind 		break;
    612  1.16     rmind 	default:
    613   1.1     rmind 		return ENOTSUP;
    614   1.1     rmind 	}
    615  1.36  christos 	prop_dictionary_set_uint32(rldict, "code-type", (uint32_t)type);
    616  1.16     rmind 	if ((cdata = prop_data_create_data(code, len)) == NULL) {
    617   1.1     rmind 		return ENOMEM;
    618   1.1     rmind 	}
    619  1.16     rmind 	prop_dictionary_set(rldict, "code", cdata);
    620   1.1     rmind 	prop_object_release(cdata);
    621   1.1     rmind 	return 0;
    622   1.1     rmind }
    623   1.1     rmind 
    624   1.1     rmind int
    625  1.16     rmind npf_rule_setkey(nl_rule_t *rl, const void *key, size_t len)
    626   1.1     rmind {
    627   1.1     rmind 	prop_dictionary_t rldict = rl->nrl_dict;
    628  1.16     rmind 	prop_data_t kdata;
    629   1.1     rmind 
    630  1.16     rmind 	if ((kdata = prop_data_create_data(key, len)) == NULL) {
    631  1.16     rmind 		return ENOMEM;
    632   1.1     rmind 	}
    633  1.16     rmind 	prop_dictionary_set(rldict, "key", kdata);
    634  1.16     rmind 	prop_object_release(kdata);
    635  1.16     rmind 	return 0;
    636  1.16     rmind }
    637  1.16     rmind 
    638  1.16     rmind int
    639  1.20     rmind npf_rule_setinfo(nl_rule_t *rl, const void *info, size_t len)
    640  1.20     rmind {
    641  1.20     rmind 	prop_dictionary_t rldict = rl->nrl_dict;
    642  1.20     rmind 	prop_data_t idata;
    643  1.20     rmind 
    644  1.20     rmind 	if ((idata = prop_data_create_data(info, len)) == NULL) {
    645  1.20     rmind 		return ENOMEM;
    646  1.20     rmind 	}
    647  1.20     rmind 	prop_dictionary_set(rldict, "info", idata);
    648  1.20     rmind 	prop_object_release(idata);
    649  1.20     rmind 	return 0;
    650  1.20     rmind }
    651  1.20     rmind 
    652  1.20     rmind int
    653  1.40  christos npf_rule_setprio(nl_rule_t *rl, int pri)
    654  1.16     rmind {
    655  1.16     rmind 	prop_dictionary_t rldict = rl->nrl_dict;
    656  1.16     rmind 
    657  1.32     rmind 	prop_dictionary_set_int32(rldict, "prio", pri);
    658  1.16     rmind 	return 0;
    659  1.16     rmind }
    660  1.16     rmind 
    661  1.16     rmind int
    662  1.16     rmind npf_rule_setproc(nl_rule_t *rl, const char *name)
    663  1.16     rmind {
    664  1.16     rmind 	prop_dictionary_t rldict = rl->nrl_dict;
    665  1.16     rmind 
    666   1.1     rmind 	prop_dictionary_set_cstring(rldict, "rproc", name);
    667   1.1     rmind 	return 0;
    668   1.1     rmind }
    669   1.1     rmind 
    670  1.16     rmind void *
    671  1.16     rmind npf_rule_export(nl_rule_t *rl, size_t *length)
    672  1.16     rmind {
    673  1.16     rmind 	prop_dictionary_t rldict = rl->nrl_dict;
    674  1.16     rmind 	void *xml;
    675  1.16     rmind 
    676  1.16     rmind 	if ((xml = prop_dictionary_externalize(rldict)) == NULL) {
    677  1.16     rmind 		return NULL;
    678  1.16     rmind 	}
    679  1.16     rmind 	*length = strlen(xml);
    680  1.16     rmind 	return xml;
    681  1.16     rmind }
    682  1.16     rmind 
    683   1.1     rmind bool
    684   1.1     rmind npf_rule_exists_p(nl_config_t *ncf, const char *name)
    685   1.1     rmind {
    686   1.1     rmind 	return _npf_prop_array_lookup(ncf->ncf_rules_list, "name", name);
    687   1.1     rmind }
    688   1.1     rmind 
    689   1.1     rmind int
    690  1.16     rmind npf_rule_insert(nl_config_t *ncf, nl_rule_t *parent, nl_rule_t *rl)
    691   1.1     rmind {
    692   1.1     rmind 	prop_dictionary_t rldict = rl->nrl_dict;
    693   1.1     rmind 	prop_array_t rlset;
    694   1.1     rmind 
    695   1.1     rmind 	if (parent) {
    696   1.1     rmind 		prop_dictionary_t pdict = parent->nrl_dict;
    697   1.1     rmind 		rlset = prop_dictionary_get(pdict, "subrules");
    698   1.1     rmind 		if (rlset == NULL) {
    699   1.1     rmind 			rlset = prop_array_create();
    700   1.1     rmind 			prop_dictionary_set(pdict, "subrules", rlset);
    701   1.1     rmind 			prop_object_release(rlset);
    702   1.1     rmind 		}
    703   1.1     rmind 	} else {
    704   1.1     rmind 		rlset = ncf->ncf_rules_list;
    705   1.1     rmind 	}
    706   1.1     rmind 	prop_array_add(rlset, rldict);
    707  1.40  christos 	prop_object_release(rldict);
    708   1.1     rmind 	return 0;
    709   1.1     rmind }
    710   1.1     rmind 
    711  1.20     rmind static nl_rule_t *
    712  1.20     rmind _npf_rule_iterate1(nl_config_t *ncf, prop_array_t rlist, unsigned *level)
    713  1.20     rmind {
    714  1.20     rmind 	prop_dictionary_t rldict;
    715  1.20     rmind 	uint32_t skipto = 0;
    716  1.20     rmind 
    717  1.20     rmind 	if (!ncf->ncf_rule_iter) {
    718  1.20     rmind 		/* Initialise the iterator. */
    719  1.20     rmind 		ncf->ncf_rule_iter = prop_array_iterator(rlist);
    720  1.20     rmind 		ncf->ncf_nlevel = 0;
    721  1.20     rmind 		ncf->ncf_reduce[0] = 0;
    722  1.20     rmind 		ncf->ncf_counter = 0;
    723  1.20     rmind 	}
    724  1.20     rmind 
    725  1.20     rmind 	rldict = prop_object_iterator_next(ncf->ncf_rule_iter);
    726  1.20     rmind 	if ((ncf->ncf_cur_rule.nrl_dict = rldict) == NULL) {
    727  1.20     rmind 		prop_object_iterator_release(ncf->ncf_rule_iter);
    728  1.20     rmind 		ncf->ncf_rule_iter = NULL;
    729  1.20     rmind 		return NULL;
    730  1.20     rmind 	}
    731  1.20     rmind 	*level = ncf->ncf_nlevel;
    732  1.20     rmind 
    733  1.20     rmind 	prop_dictionary_get_uint32(rldict, "skip-to", &skipto);
    734  1.20     rmind 	if (skipto) {
    735  1.20     rmind 		ncf->ncf_nlevel++;
    736  1.20     rmind 		ncf->ncf_reduce[ncf->ncf_nlevel] = skipto;
    737  1.20     rmind 	}
    738  1.20     rmind 	if (ncf->ncf_reduce[ncf->ncf_nlevel] == ++ncf->ncf_counter) {
    739  1.20     rmind 		assert(ncf->ncf_nlevel > 0);
    740  1.20     rmind 		ncf->ncf_nlevel--;
    741  1.20     rmind 	}
    742  1.20     rmind 	return &ncf->ncf_cur_rule;
    743  1.20     rmind }
    744  1.20     rmind 
    745  1.20     rmind nl_rule_t *
    746  1.20     rmind npf_rule_iterate(nl_config_t *ncf, unsigned *level)
    747  1.20     rmind {
    748  1.20     rmind 	return _npf_rule_iterate1(ncf, ncf->ncf_rules_list, level);
    749  1.20     rmind }
    750  1.20     rmind 
    751  1.20     rmind const char *
    752  1.20     rmind npf_rule_getname(nl_rule_t *rl)
    753  1.20     rmind {
    754  1.20     rmind 	prop_dictionary_t rldict = rl->nrl_dict;
    755  1.20     rmind 	const char *rname = NULL;
    756  1.20     rmind 
    757  1.20     rmind 	prop_dictionary_get_cstring_nocopy(rldict, "name", &rname);
    758  1.20     rmind 	return rname;
    759  1.20     rmind }
    760  1.20     rmind 
    761  1.20     rmind uint32_t
    762  1.20     rmind npf_rule_getattr(nl_rule_t *rl)
    763  1.20     rmind {
    764  1.20     rmind 	prop_dictionary_t rldict = rl->nrl_dict;
    765  1.20     rmind 	uint32_t attr = 0;
    766  1.20     rmind 
    767  1.32     rmind 	prop_dictionary_get_uint32(rldict, "attr", &attr);
    768  1.20     rmind 	return attr;
    769  1.20     rmind }
    770  1.20     rmind 
    771  1.22     rmind const char *
    772  1.20     rmind npf_rule_getinterface(nl_rule_t *rl)
    773  1.20     rmind {
    774  1.20     rmind 	prop_dictionary_t rldict = rl->nrl_dict;
    775  1.22     rmind 	const char *ifname = NULL;
    776  1.20     rmind 
    777  1.32     rmind 	prop_dictionary_get_cstring_nocopy(rldict, "ifname", &ifname);
    778  1.22     rmind 	return ifname;
    779  1.20     rmind }
    780  1.20     rmind 
    781  1.20     rmind const void *
    782  1.20     rmind npf_rule_getinfo(nl_rule_t *rl, size_t *len)
    783  1.20     rmind {
    784  1.20     rmind 	prop_dictionary_t rldict = rl->nrl_dict;
    785  1.20     rmind 	prop_object_t obj = prop_dictionary_get(rldict, "info");
    786  1.20     rmind 
    787  1.20     rmind 	*len = prop_data_size(obj);
    788  1.20     rmind 	return prop_data_data_nocopy(obj);
    789  1.20     rmind }
    790  1.20     rmind 
    791  1.20     rmind const char *
    792  1.20     rmind npf_rule_getproc(nl_rule_t *rl)
    793  1.20     rmind {
    794  1.20     rmind 	prop_dictionary_t rldict = rl->nrl_dict;
    795  1.20     rmind 	const char *rpname = NULL;
    796  1.20     rmind 
    797  1.20     rmind 	prop_dictionary_get_cstring_nocopy(rldict, "rproc", &rpname);
    798  1.20     rmind 	return rpname;
    799  1.20     rmind }
    800  1.20     rmind 
    801  1.35     rmind uint64_t
    802  1.35     rmind npf_rule_getid(nl_rule_t *rl)
    803  1.35     rmind {
    804  1.35     rmind 	prop_dictionary_t rldict = rl->nrl_dict;
    805  1.35     rmind 	uint64_t id = 0;
    806  1.35     rmind 
    807  1.35     rmind 	(void)prop_dictionary_get_uint64(rldict, "id", &id);
    808  1.40  christos 	return (unsigned)id;
    809  1.35     rmind }
    810  1.35     rmind 
    811  1.35     rmind const void *
    812  1.35     rmind npf_rule_getcode(nl_rule_t *rl, int *type, size_t *len)
    813  1.35     rmind {
    814  1.35     rmind 	prop_dictionary_t rldict = rl->nrl_dict;
    815  1.35     rmind 	prop_object_t obj = prop_dictionary_get(rldict, "code");
    816  1.35     rmind 
    817  1.35     rmind 	prop_dictionary_get_uint32(rldict, "code-type", (uint32_t *)type);
    818  1.35     rmind 	*len = prop_data_size(obj);
    819  1.35     rmind 	return prop_data_data_nocopy(obj);
    820  1.35     rmind }
    821  1.35     rmind 
    822  1.17     rmind int
    823  1.17     rmind _npf_ruleset_list(int fd, const char *rname, nl_config_t *ncf)
    824  1.17     rmind {
    825  1.17     rmind 	prop_dictionary_t rldict, ret;
    826  1.17     rmind 	int error;
    827  1.17     rmind 
    828  1.17     rmind 	rldict = prop_dictionary_create();
    829  1.17     rmind 	if (rldict == NULL) {
    830  1.17     rmind 		return ENOMEM;
    831  1.17     rmind 	}
    832  1.17     rmind 	prop_dictionary_set_cstring(rldict, "ruleset-name", rname);
    833  1.17     rmind 	prop_dictionary_set_uint32(rldict, "command", NPF_CMD_RULE_LIST);
    834  1.40  christos #ifdef _NPF_STANDALONE
    835  1.40  christos 	error = ENOTSUP;
    836  1.40  christos #else
    837  1.17     rmind 	error = prop_dictionary_sendrecv_ioctl(rldict, fd, IOC_NPF_RULE, &ret);
    838  1.40  christos #endif
    839  1.17     rmind 	if (!error) {
    840  1.17     rmind 		prop_array_t rules;
    841  1.17     rmind 
    842  1.17     rmind 		rules = prop_dictionary_get(ret, "rules");
    843  1.17     rmind 		if (rules == NULL) {
    844  1.17     rmind 			return EINVAL;
    845  1.17     rmind 		}
    846  1.17     rmind 		prop_object_release(ncf->ncf_rules_list);
    847  1.17     rmind 		ncf->ncf_rules_list = rules;
    848  1.17     rmind 	}
    849  1.17     rmind 	return error;
    850  1.17     rmind }
    851  1.17     rmind 
    852   1.1     rmind void
    853   1.1     rmind npf_rule_destroy(nl_rule_t *rl)
    854   1.1     rmind {
    855   1.1     rmind 
    856   1.1     rmind 	prop_object_release(rl->nrl_dict);
    857   1.1     rmind 	free(rl);
    858   1.1     rmind }
    859   1.1     rmind 
    860   1.1     rmind /*
    861   1.1     rmind  * RULE PROCEDURE INTERFACE.
    862   1.1     rmind  */
    863   1.1     rmind 
    864   1.1     rmind nl_rproc_t *
    865   1.1     rmind npf_rproc_create(const char *name)
    866   1.1     rmind {
    867   1.1     rmind 	prop_dictionary_t rpdict;
    868  1.13     rmind 	prop_array_t extcalls;
    869   1.1     rmind 	nl_rproc_t *nrp;
    870   1.1     rmind 
    871   1.1     rmind 	nrp = malloc(sizeof(nl_rproc_t));
    872   1.1     rmind 	if (nrp == NULL) {
    873   1.1     rmind 		return NULL;
    874   1.1     rmind 	}
    875   1.1     rmind 	rpdict = prop_dictionary_create();
    876   1.1     rmind 	if (rpdict == NULL) {
    877   1.1     rmind 		free(nrp);
    878   1.1     rmind 		return NULL;
    879   1.1     rmind 	}
    880   1.1     rmind 	prop_dictionary_set_cstring(rpdict, "name", name);
    881  1.13     rmind 
    882  1.13     rmind 	extcalls = prop_array_create();
    883  1.13     rmind 	if (extcalls == NULL) {
    884  1.13     rmind 		prop_object_release(rpdict);
    885  1.13     rmind 		free(nrp);
    886  1.13     rmind 		return NULL;
    887  1.13     rmind 	}
    888  1.13     rmind 	prop_dictionary_set(rpdict, "extcalls", extcalls);
    889  1.13     rmind 	prop_object_release(extcalls);
    890  1.13     rmind 
    891   1.1     rmind 	nrp->nrp_dict = rpdict;
    892   1.1     rmind 	return nrp;
    893   1.1     rmind }
    894   1.1     rmind 
    895   1.1     rmind int
    896  1.13     rmind npf_rproc_extcall(nl_rproc_t *rp, nl_ext_t *ext)
    897   1.1     rmind {
    898   1.1     rmind 	prop_dictionary_t rpdict = rp->nrp_dict;
    899  1.13     rmind 	prop_dictionary_t extdict = ext->nxt_dict;
    900  1.13     rmind 	prop_array_t extcalls;
    901   1.1     rmind 
    902  1.13     rmind 	extcalls = prop_dictionary_get(rpdict, "extcalls");
    903  1.13     rmind 	if (_npf_prop_array_lookup(extcalls, "name", ext->nxt_name)) {
    904  1.13     rmind 		return EEXIST;
    905  1.13     rmind 	}
    906  1.13     rmind 	prop_dictionary_set_cstring(extdict, "name", ext->nxt_name);
    907  1.13     rmind 	prop_array_add(extcalls, extdict);
    908  1.40  christos 	prop_object_release(extdict);
    909   1.1     rmind 	return 0;
    910   1.1     rmind }
    911   1.1     rmind 
    912  1.13     rmind bool
    913  1.13     rmind npf_rproc_exists_p(nl_config_t *ncf, const char *name)
    914   1.1     rmind {
    915  1.13     rmind 	return _npf_prop_array_lookup(ncf->ncf_rproc_list, "name", name);
    916   1.1     rmind }
    917   1.1     rmind 
    918   1.1     rmind int
    919   1.1     rmind npf_rproc_insert(nl_config_t *ncf, nl_rproc_t *rp)
    920   1.1     rmind {
    921   1.1     rmind 	prop_dictionary_t rpdict = rp->nrp_dict;
    922   1.1     rmind 	const char *name;
    923   1.1     rmind 
    924   1.1     rmind 	if (!prop_dictionary_get_cstring_nocopy(rpdict, "name", &name)) {
    925   1.1     rmind 		return EINVAL;
    926   1.1     rmind 	}
    927   1.1     rmind 	if (npf_rproc_exists_p(ncf, name)) {
    928   1.1     rmind 		return EEXIST;
    929   1.1     rmind 	}
    930   1.1     rmind 	prop_array_add(ncf->ncf_rproc_list, rpdict);
    931  1.40  christos 	prop_object_release(rpdict);
    932   1.1     rmind 	return 0;
    933   1.1     rmind }
    934   1.1     rmind 
    935  1.20     rmind nl_rproc_t *
    936  1.20     rmind npf_rproc_iterate(nl_config_t *ncf)
    937  1.20     rmind {
    938  1.20     rmind 	prop_dictionary_t rpdict;
    939  1.20     rmind 
    940  1.20     rmind 	if (!ncf->ncf_rproc_iter) {
    941  1.20     rmind 		/* Initialise the iterator. */
    942  1.20     rmind 		ncf->ncf_rproc_iter = prop_array_iterator(ncf->ncf_rproc_list);
    943  1.20     rmind 	}
    944  1.20     rmind 	rpdict = prop_object_iterator_next(ncf->ncf_rproc_iter);
    945  1.20     rmind 	if ((ncf->ncf_cur_rproc.nrp_dict = rpdict) == NULL) {
    946  1.20     rmind 		prop_object_iterator_release(ncf->ncf_rproc_iter);
    947  1.20     rmind 		ncf->ncf_rproc_iter = NULL;
    948  1.20     rmind 		return NULL;
    949  1.20     rmind 	}
    950  1.20     rmind 	return &ncf->ncf_cur_rproc;
    951  1.20     rmind }
    952  1.20     rmind 
    953  1.20     rmind const char *
    954  1.20     rmind npf_rproc_getname(nl_rproc_t *rp)
    955  1.20     rmind {
    956  1.20     rmind 	prop_dictionary_t rpdict = rp->nrp_dict;
    957  1.20     rmind 	const char *rpname = NULL;
    958  1.20     rmind 
    959  1.20     rmind 	prop_dictionary_get_cstring_nocopy(rpdict, "name", &rpname);
    960  1.20     rmind 	return rpname;
    961  1.20     rmind }
    962  1.20     rmind 
    963   1.1     rmind /*
    964  1.32     rmind  * NAT INTERFACE.
    965   1.1     rmind  */
    966   1.1     rmind 
    967   1.1     rmind nl_nat_t *
    968  1.22     rmind npf_nat_create(int type, u_int flags, const char *ifname,
    969  1.28     rmind     int af, npf_addr_t *addr, npf_netmask_t mask, in_port_t port)
    970   1.1     rmind {
    971   1.1     rmind 	nl_rule_t *rl;
    972   1.1     rmind 	prop_dictionary_t rldict;
    973   1.1     rmind 	uint32_t attr;
    974   1.1     rmind 
    975   1.1     rmind 	attr = NPF_RULE_PASS | NPF_RULE_FINAL |
    976   1.2     rmind 	    (type == NPF_NATOUT ? NPF_RULE_OUT : NPF_RULE_IN);
    977   1.1     rmind 
    978  1.32     rmind 	/* Create a rule for NAT policy.  Next, will add NAT data. */
    979  1.22     rmind 	rl = npf_rule_create(NULL, attr, ifname);
    980   1.1     rmind 	if (rl == NULL) {
    981   1.1     rmind 		return NULL;
    982   1.1     rmind 	}
    983   1.1     rmind 	rldict = rl->nrl_dict;
    984   1.1     rmind 
    985   1.1     rmind 	/* Translation type and flags. */
    986   1.1     rmind 	prop_dictionary_set_int32(rldict, "type", type);
    987   1.1     rmind 	prop_dictionary_set_uint32(rldict, "flags", flags);
    988   1.1     rmind 
    989  1.28     rmind 	/* Translation IP and mask. */
    990  1.36  christos 	if (!_npf_add_addr(rldict, "nat-ip", af, addr)) {
    991   1.1     rmind 		npf_rule_destroy(rl);
    992   1.1     rmind 		return NULL;
    993   1.1     rmind 	}
    994  1.36  christos 	prop_dictionary_set_uint32(rldict, "nat-mask", (uint32_t)mask);
    995   1.1     rmind 
    996   1.1     rmind 	/* Translation port (for redirect case). */
    997  1.32     rmind 	prop_dictionary_set_uint16(rldict, "nat-port", port);
    998   1.1     rmind 
    999   1.1     rmind 	return (nl_nat_t *)rl;
   1000   1.1     rmind }
   1001   1.1     rmind 
   1002   1.1     rmind int
   1003  1.40  christos npf_nat_insert(nl_config_t *ncf, nl_nat_t *nt, int pri __unused)
   1004   1.1     rmind {
   1005   1.1     rmind 	prop_dictionary_t rldict = nt->nrl_dict;
   1006   1.1     rmind 
   1007  1.32     rmind 	prop_dictionary_set_int32(rldict, "prio", NPF_PRI_LAST);
   1008   1.1     rmind 	prop_array_add(ncf->ncf_nat_list, rldict);
   1009  1.40  christos 	prop_object_release(rldict);
   1010   1.1     rmind 	return 0;
   1011   1.1     rmind }
   1012   1.1     rmind 
   1013  1.20     rmind nl_nat_t *
   1014  1.20     rmind npf_nat_iterate(nl_config_t *ncf)
   1015  1.20     rmind {
   1016  1.20     rmind 	u_int level;
   1017  1.20     rmind 	return _npf_rule_iterate1(ncf, ncf->ncf_nat_list, &level);
   1018  1.20     rmind }
   1019  1.20     rmind 
   1020  1.20     rmind int
   1021  1.28     rmind npf_nat_setalgo(nl_nat_t *nt, u_int algo)
   1022  1.28     rmind {
   1023  1.28     rmind 	prop_dictionary_t rldict = nt->nrl_dict;
   1024  1.32     rmind 	prop_dictionary_set_uint32(rldict, "nat-algo", algo);
   1025  1.28     rmind 	return 0;
   1026  1.28     rmind }
   1027  1.28     rmind 
   1028  1.28     rmind int
   1029  1.28     rmind npf_nat_setnpt66(nl_nat_t *nt, uint16_t adj)
   1030  1.28     rmind {
   1031  1.28     rmind 	prop_dictionary_t rldict = nt->nrl_dict;
   1032  1.28     rmind 	int error;
   1033  1.28     rmind 
   1034  1.28     rmind 	if ((error = npf_nat_setalgo(nt, NPF_ALGO_NPT66)) != 0) {
   1035  1.28     rmind 		return error;
   1036  1.28     rmind 	}
   1037  1.32     rmind 	prop_dictionary_set_uint16(rldict, "npt66-adj", adj);
   1038  1.28     rmind 	return 0;
   1039  1.28     rmind }
   1040  1.28     rmind 
   1041  1.28     rmind int
   1042  1.20     rmind npf_nat_gettype(nl_nat_t *nt)
   1043  1.20     rmind {
   1044  1.20     rmind 	prop_dictionary_t rldict = nt->nrl_dict;
   1045  1.20     rmind 	int type = 0;
   1046  1.20     rmind 
   1047  1.20     rmind 	prop_dictionary_get_int32(rldict, "type", &type);
   1048  1.20     rmind 	return type;
   1049  1.20     rmind }
   1050  1.20     rmind 
   1051  1.27     rmind u_int
   1052  1.27     rmind npf_nat_getflags(nl_nat_t *nt)
   1053  1.27     rmind {
   1054  1.27     rmind 	prop_dictionary_t rldict = nt->nrl_dict;
   1055  1.27     rmind 	unsigned flags = 0;
   1056  1.27     rmind 
   1057  1.27     rmind 	prop_dictionary_get_uint32(rldict, "flags", &flags);
   1058  1.27     rmind 	return flags;
   1059  1.27     rmind }
   1060  1.27     rmind 
   1061  1.20     rmind void
   1062  1.20     rmind npf_nat_getmap(nl_nat_t *nt, npf_addr_t *addr, size_t *alen, in_port_t *port)
   1063  1.20     rmind {
   1064  1.20     rmind 	prop_dictionary_t rldict = nt->nrl_dict;
   1065  1.32     rmind 	prop_object_t obj = prop_dictionary_get(rldict, "nat-ip");
   1066  1.20     rmind 
   1067  1.20     rmind 	*alen = prop_data_size(obj);
   1068  1.20     rmind 	memcpy(addr, prop_data_data_nocopy(obj), *alen);
   1069  1.20     rmind 
   1070  1.20     rmind 	*port = 0;
   1071  1.32     rmind 	prop_dictionary_get_uint16(rldict, "nat-port", port);
   1072  1.20     rmind }
   1073  1.20     rmind 
   1074   1.1     rmind /*
   1075   1.1     rmind  * TABLE INTERFACE.
   1076   1.1     rmind  */
   1077   1.1     rmind 
   1078   1.1     rmind nl_table_t *
   1079  1.23     rmind npf_table_create(const char *name, u_int id, int type)
   1080   1.1     rmind {
   1081   1.1     rmind 	prop_dictionary_t tldict;
   1082   1.1     rmind 	prop_array_t tblents;
   1083   1.1     rmind 	nl_table_t *tl;
   1084   1.1     rmind 
   1085   1.5  christos 	tl = malloc(sizeof(*tl));
   1086   1.1     rmind 	if (tl == NULL) {
   1087   1.1     rmind 		return NULL;
   1088   1.1     rmind 	}
   1089   1.1     rmind 	tldict = prop_dictionary_create();
   1090   1.1     rmind 	if (tldict == NULL) {
   1091   1.1     rmind 		free(tl);
   1092   1.1     rmind 		return NULL;
   1093   1.1     rmind 	}
   1094  1.23     rmind 	prop_dictionary_set_cstring(tldict, "name", name);
   1095  1.40  christos 	prop_dictionary_set_uint64(tldict, "id", (uint64_t)id);
   1096   1.1     rmind 	prop_dictionary_set_int32(tldict, "type", type);
   1097   1.1     rmind 
   1098   1.1     rmind 	tblents = prop_array_create();
   1099   1.1     rmind 	if (tblents == NULL) {
   1100   1.1     rmind 		prop_object_release(tldict);
   1101   1.1     rmind 		free(tl);
   1102   1.1     rmind 		return NULL;
   1103   1.1     rmind 	}
   1104   1.1     rmind 	prop_dictionary_set(tldict, "entries", tblents);
   1105   1.1     rmind 	prop_object_release(tblents);
   1106   1.1     rmind 
   1107   1.1     rmind 	tl->ntl_dict = tldict;
   1108   1.1     rmind 	return tl;
   1109   1.1     rmind }
   1110   1.1     rmind 
   1111   1.1     rmind int
   1112  1.15     rmind npf_table_add_entry(nl_table_t *tl, int af, const npf_addr_t *addr,
   1113  1.15     rmind     const npf_netmask_t mask)
   1114   1.1     rmind {
   1115   1.1     rmind 	prop_dictionary_t tldict = tl->ntl_dict, entdict;
   1116   1.1     rmind 	prop_array_t tblents;
   1117   1.1     rmind 
   1118   1.1     rmind 	/* Create the table entry. */
   1119   1.1     rmind 	entdict = prop_dictionary_create();
   1120  1.10     rmind 	if (entdict == NULL) {
   1121   1.1     rmind 		return ENOMEM;
   1122   1.1     rmind 	}
   1123  1.15     rmind 
   1124  1.36  christos 	if (!_npf_add_addr(entdict, "addr", af, addr)) {
   1125  1.15     rmind 		return EINVAL;
   1126  1.15     rmind 	}
   1127   1.3    zoltan 	prop_dictionary_set_uint8(entdict, "mask", mask);
   1128   1.1     rmind 
   1129   1.1     rmind 	tblents = prop_dictionary_get(tldict, "entries");
   1130   1.1     rmind 	prop_array_add(tblents, entdict);
   1131   1.1     rmind 	prop_object_release(entdict);
   1132   1.1     rmind 	return 0;
   1133   1.1     rmind }
   1134   1.1     rmind 
   1135  1.26     rmind int
   1136  1.26     rmind npf_table_setdata(nl_table_t *tl, const void *blob, size_t len)
   1137  1.26     rmind {
   1138  1.26     rmind 	prop_dictionary_t tldict = tl->ntl_dict;
   1139  1.26     rmind 	prop_data_t bobj;
   1140  1.26     rmind 
   1141  1.26     rmind 	if ((bobj = prop_data_create_data(blob, len)) == NULL) {
   1142  1.26     rmind 		return ENOMEM;
   1143  1.26     rmind 	}
   1144  1.26     rmind 	prop_dictionary_set(tldict, "data", bobj);
   1145  1.26     rmind 	prop_object_release(bobj);
   1146  1.26     rmind 	return 0;
   1147  1.26     rmind }
   1148  1.26     rmind 
   1149  1.25     rmind static bool
   1150  1.25     rmind _npf_table_exists_p(nl_config_t *ncf, const char *name)
   1151   1.1     rmind {
   1152   1.1     rmind 	prop_dictionary_t tldict;
   1153   1.1     rmind 	prop_object_iterator_t it;
   1154   1.1     rmind 
   1155   1.1     rmind 	it = prop_array_iterator(ncf->ncf_table_list);
   1156   1.1     rmind 	while ((tldict = prop_object_iterator_next(it)) != NULL) {
   1157  1.24     rmind 		const char *tname = NULL;
   1158  1.24     rmind 
   1159  1.24     rmind 		if (prop_dictionary_get_cstring_nocopy(tldict, "name", &tname)
   1160  1.24     rmind 		    && strcmp(tname, name) == 0)
   1161   1.1     rmind 			break;
   1162   1.1     rmind 	}
   1163   1.1     rmind 	prop_object_iterator_release(it);
   1164   1.1     rmind 	return tldict ? true : false;
   1165   1.1     rmind }
   1166   1.1     rmind 
   1167   1.1     rmind int
   1168   1.1     rmind npf_table_insert(nl_config_t *ncf, nl_table_t *tl)
   1169   1.1     rmind {
   1170   1.1     rmind 	prop_dictionary_t tldict = tl->ntl_dict;
   1171  1.24     rmind 	const char *name = NULL;
   1172   1.1     rmind 
   1173  1.24     rmind 	if (!prop_dictionary_get_cstring_nocopy(tldict, "name", &name)) {
   1174   1.1     rmind 		return EINVAL;
   1175   1.1     rmind 	}
   1176  1.25     rmind 	if (_npf_table_exists_p(ncf, name)) {
   1177   1.1     rmind 		return EEXIST;
   1178   1.1     rmind 	}
   1179   1.1     rmind 	prop_array_add(ncf->ncf_table_list, tldict);
   1180  1.40  christos 	prop_object_release(tldict);
   1181   1.1     rmind 	return 0;
   1182   1.1     rmind }
   1183   1.1     rmind 
   1184  1.20     rmind nl_table_t *
   1185  1.20     rmind npf_table_iterate(nl_config_t *ncf)
   1186  1.20     rmind {
   1187  1.20     rmind 	prop_dictionary_t tldict;
   1188  1.20     rmind 
   1189  1.20     rmind 	if (!ncf->ncf_table_iter) {
   1190  1.20     rmind 		/* Initialise the iterator. */
   1191  1.20     rmind 		ncf->ncf_table_iter = prop_array_iterator(ncf->ncf_table_list);
   1192  1.20     rmind 	}
   1193  1.20     rmind 	tldict = prop_object_iterator_next(ncf->ncf_table_iter);
   1194  1.20     rmind 	if ((ncf->ncf_cur_table.ntl_dict = tldict) == NULL) {
   1195  1.20     rmind 		prop_object_iterator_release(ncf->ncf_table_iter);
   1196  1.20     rmind 		ncf->ncf_table_iter = NULL;
   1197  1.20     rmind 		return NULL;
   1198  1.20     rmind 	}
   1199  1.20     rmind 	return &ncf->ncf_cur_table;
   1200  1.20     rmind }
   1201  1.20     rmind 
   1202  1.20     rmind unsigned
   1203  1.20     rmind npf_table_getid(nl_table_t *tl)
   1204  1.20     rmind {
   1205  1.20     rmind 	prop_dictionary_t tldict = tl->ntl_dict;
   1206  1.40  christos 	uint64_t id = (uint64_t)-1;
   1207  1.20     rmind 
   1208  1.40  christos 	prop_dictionary_get_uint64(tldict, "id", &id);
   1209  1.40  christos 	return (unsigned)id;
   1210  1.20     rmind }
   1211  1.20     rmind 
   1212  1.23     rmind const char *
   1213  1.23     rmind npf_table_getname(nl_table_t *tl)
   1214  1.23     rmind {
   1215  1.23     rmind 	prop_dictionary_t tldict = tl->ntl_dict;
   1216  1.23     rmind 	const char *tname = NULL;
   1217  1.23     rmind 
   1218  1.23     rmind 	prop_dictionary_get_cstring_nocopy(tldict, "name", &tname);
   1219  1.23     rmind 	return tname;
   1220  1.23     rmind }
   1221  1.23     rmind 
   1222  1.20     rmind int
   1223  1.20     rmind npf_table_gettype(nl_table_t *tl)
   1224  1.20     rmind {
   1225  1.20     rmind 	prop_dictionary_t tldict = tl->ntl_dict;
   1226  1.20     rmind 	int type = 0;
   1227  1.20     rmind 
   1228  1.20     rmind 	prop_dictionary_get_int32(tldict, "type", &type);
   1229  1.20     rmind 	return type;
   1230  1.20     rmind }
   1231  1.20     rmind 
   1232   1.1     rmind void
   1233   1.1     rmind npf_table_destroy(nl_table_t *tl)
   1234   1.1     rmind {
   1235   1.1     rmind 	prop_object_release(tl->ntl_dict);
   1236   1.1     rmind 	free(tl);
   1237   1.1     rmind }
   1238   1.1     rmind 
   1239   1.1     rmind /*
   1240  1.19  christos  * ALG INTERFACE.
   1241  1.19  christos  */
   1242  1.19  christos 
   1243  1.19  christos int
   1244  1.19  christos _npf_alg_load(nl_config_t *ncf, const char *name)
   1245  1.19  christos {
   1246  1.19  christos 	prop_dictionary_t al_dict;
   1247  1.19  christos 
   1248  1.19  christos 	if (_npf_prop_array_lookup(ncf->ncf_alg_list, "name", name))
   1249  1.19  christos 		return EEXIST;
   1250  1.19  christos 
   1251  1.19  christos 	al_dict = prop_dictionary_create();
   1252  1.19  christos 	prop_dictionary_set_cstring(al_dict, "name", name);
   1253  1.19  christos 	prop_array_add(ncf->ncf_alg_list, al_dict);
   1254  1.19  christos 	prop_object_release(al_dict);
   1255  1.19  christos 	return 0;
   1256  1.19  christos }
   1257  1.19  christos 
   1258  1.19  christos int
   1259  1.19  christos _npf_alg_unload(nl_config_t *ncf, const char *name)
   1260  1.19  christos {
   1261  1.19  christos 	if (!_npf_prop_array_lookup(ncf->ncf_alg_list, "name", name))
   1262  1.19  christos 		return ENOENT;
   1263  1.19  christos 
   1264  1.19  christos 	// Not yet: prop_array_add(ncf->ncf_alg_list, al_dict);
   1265  1.19  christos 	return ENOTSUP;
   1266  1.19  christos }
   1267  1.19  christos 
   1268  1.19  christos /*
   1269   1.1     rmind  * MISC.
   1270   1.1     rmind  */
   1271   1.1     rmind 
   1272  1.11     rmind static prop_dictionary_t
   1273  1.11     rmind _npf_debug_initonce(nl_config_t *ncf)
   1274  1.11     rmind {
   1275  1.11     rmind 	if (!ncf->ncf_debug) {
   1276  1.11     rmind 		prop_array_t iflist = prop_array_create();
   1277  1.11     rmind 		ncf->ncf_debug = prop_dictionary_create();
   1278  1.11     rmind 		prop_dictionary_set(ncf->ncf_debug, "interfaces", iflist);
   1279  1.11     rmind 		prop_object_release(iflist);
   1280  1.11     rmind 	}
   1281  1.11     rmind 	return ncf->ncf_debug;
   1282  1.11     rmind }
   1283  1.11     rmind 
   1284  1.11     rmind void
   1285  1.22     rmind _npf_debug_addif(nl_config_t *ncf, const char *ifname)
   1286  1.11     rmind {
   1287  1.11     rmind 	prop_dictionary_t ifdict, dbg = _npf_debug_initonce(ncf);
   1288  1.11     rmind 	prop_array_t iflist = prop_dictionary_get(dbg, "interfaces");
   1289  1.22     rmind 	u_int if_idx = if_nametoindex(ifname);
   1290  1.11     rmind 
   1291  1.22     rmind 	if (_npf_prop_array_lookup(iflist, "name", ifname)) {
   1292  1.11     rmind 		return;
   1293  1.11     rmind 	}
   1294  1.11     rmind 	ifdict = prop_dictionary_create();
   1295  1.22     rmind 	prop_dictionary_set_cstring(ifdict, "name", ifname);
   1296  1.22     rmind 	prop_dictionary_set_uint32(ifdict, "index", if_idx);
   1297  1.11     rmind 	prop_array_add(iflist, ifdict);
   1298  1.11     rmind 	prop_object_release(ifdict);
   1299  1.11     rmind }
   1300  1.36  christos 
   1301  1.36  christos int
   1302  1.39  christos npf_nat_lookup(int fd, int af, npf_addr_t *addr[2], in_port_t port[2],
   1303  1.36  christos     int proto, int dir)
   1304  1.36  christos {
   1305  1.38  christos 	prop_dictionary_t conn_dict, conn_res = NULL;
   1306  1.36  christos 	int error = EINVAL;
   1307  1.36  christos 
   1308  1.36  christos 	conn_dict = prop_dictionary_create();
   1309  1.38  christos 	if (conn_dict == NULL)
   1310  1.36  christos 		return ENOMEM;
   1311  1.38  christos 
   1312  1.38  christos 	if (!prop_dictionary_set_uint16(conn_dict, "direction", dir))
   1313  1.36  christos 		goto out;
   1314  1.36  christos 
   1315  1.38  christos 	conn_res = prop_dictionary_create();
   1316  1.38  christos 	if (conn_res == NULL)
   1317  1.36  christos 		goto out;
   1318  1.36  christos 
   1319  1.38  christos 	if (!_npf_add_addr(conn_res, "saddr", af, addr[0]))
   1320  1.38  christos 		goto out;
   1321  1.38  christos 	if (!_npf_add_addr(conn_res, "daddr", af, addr[1]))
   1322  1.38  christos 		goto out;
   1323  1.38  christos 	if (!prop_dictionary_set_uint16(conn_res, "sport", port[0]))
   1324  1.38  christos 		goto out;
   1325  1.38  christos 	if (!prop_dictionary_set_uint16(conn_res, "dport", port[1]))
   1326  1.38  christos 		goto out;
   1327  1.38  christos 	if (!prop_dictionary_set_uint16(conn_res, "proto", proto))
   1328  1.38  christos 		goto out;
   1329  1.38  christos 	if (!prop_dictionary_set(conn_dict, "key", conn_res))
   1330  1.38  christos 		goto out;
   1331  1.38  christos 
   1332  1.38  christos 	prop_object_release(conn_res);
   1333  1.36  christos 
   1334  1.40  christos #if !defined(_NPF_STANDALONE)
   1335  1.36  christos 	error = prop_dictionary_sendrecv_ioctl(conn_dict, fd,
   1336  1.36  christos 	    IOC_NPF_CONN_LOOKUP, &conn_res);
   1337  1.40  christos #else
   1338  1.40  christos 	error = ENOTSUP;
   1339  1.40  christos #endif
   1340  1.36  christos 	if (error != 0)
   1341  1.36  christos 		goto out;
   1342  1.36  christos 
   1343  1.36  christos 	prop_dictionary_t nat = prop_dictionary_get(conn_res, "nat");
   1344  1.36  christos 	if (nat == NULL) {
   1345  1.36  christos 		errno = ENOENT;
   1346  1.36  christos 		goto out;
   1347  1.36  christos 	}
   1348  1.38  christos 
   1349  1.36  christos 	if (!_npf_get_addr(nat, "oaddr", addr[0])) {
   1350  1.36  christos 		error = EINVAL;
   1351  1.36  christos 		goto out;
   1352  1.36  christos 	}
   1353  1.38  christos 
   1354  1.36  christos 	prop_dictionary_get_uint16(nat, "oport", &port[0]);
   1355  1.36  christos 	prop_dictionary_get_uint16(nat, "tport", &port[1]);
   1356  1.36  christos out:
   1357  1.38  christos 	if (conn_res)
   1358  1.38  christos 		prop_object_release(conn_res);
   1359  1.36  christos 	prop_object_release(conn_dict);
   1360  1.36  christos 	return error;
   1361  1.36  christos }
   1362  1.41  christos 
   1363  1.41  christos struct npf_endpoint {
   1364  1.41  christos 	npf_addr_t addr[2];
   1365  1.41  christos 	in_port_t port[2];
   1366  1.41  christos 	uint16_t alen;
   1367  1.41  christos 	uint16_t proto;
   1368  1.41  christos };
   1369  1.41  christos 
   1370  1.41  christos static bool
   1371  1.41  christos npf_endpoint_load(prop_dictionary_t cdict, const char *name,
   1372  1.41  christos     struct npf_endpoint *ep)
   1373  1.41  christos {
   1374  1.41  christos 	prop_dictionary_t ed = prop_dictionary_get(cdict, name);
   1375  1.41  christos 	if (ed == NULL)
   1376  1.41  christos 		return false;
   1377  1.41  christos 	if (!(ep->alen = _npf_get_addr(ed, "saddr", &ep->addr[0])))
   1378  1.41  christos 		return false;
   1379  1.41  christos 	if (ep->alen != _npf_get_addr(ed, "daddr", &ep->addr[1]))
   1380  1.41  christos 		return false;
   1381  1.41  christos 	if (!prop_dictionary_get_uint16(ed, "sport", &ep->port[0]))
   1382  1.41  christos 		return false;
   1383  1.41  christos 	if (!prop_dictionary_get_uint16(ed, "dport", &ep->port[1]))
   1384  1.41  christos 		return false;
   1385  1.41  christos 	if (!prop_dictionary_get_uint16(ed, "proto", &ep->proto))
   1386  1.41  christos 		return false;
   1387  1.41  christos 	return true;
   1388  1.41  christos }
   1389  1.41  christos 
   1390  1.41  christos static void
   1391  1.41  christos npf_conn_handle(prop_dictionary_t cdict, npf_conn_func_t fun, void *v)
   1392  1.41  christos {
   1393  1.41  christos 	prop_dictionary_t nat;
   1394  1.41  christos 	struct npf_endpoint ep;
   1395  1.41  christos 	uint16_t tport;
   1396  1.41  christos 	const char *ifname;
   1397  1.41  christos 
   1398  1.41  christos 	if (!prop_dictionary_get_cstring_nocopy(cdict, "ifname", &ifname))
   1399  1.41  christos 		goto err;
   1400  1.41  christos 
   1401  1.41  christos 	if ((nat = prop_dictionary_get(cdict, "nat")) != NULL &&
   1402  1.41  christos 	    prop_object_type(nat) == PROP_TYPE_DICTIONARY) {
   1403  1.41  christos 		if (!prop_dictionary_get_uint16(nat, "tport", &tport))
   1404  1.41  christos 			goto err;
   1405  1.41  christos 	} else {
   1406  1.41  christos 		tport = 0;
   1407  1.41  christos 	}
   1408  1.41  christos 	if (!npf_endpoint_load(cdict, "forw-key", &ep))
   1409  1.41  christos 		goto err;
   1410  1.41  christos 
   1411  1.41  christos 	in_port_t p[] = {
   1412  1.41  christos 	    ntohs(ep.port[0]),
   1413  1.41  christos 	    ntohs(ep.port[1]),
   1414  1.41  christos 	    ntohs(tport)
   1415  1.41  christos 	};
   1416  1.41  christos 	(*fun)((unsigned)ep.alen, ep.addr, p, ifname, v);
   1417  1.41  christos err:
   1418  1.41  christos 	return;
   1419  1.41  christos }
   1420  1.41  christos 
   1421  1.41  christos int
   1422  1.41  christos npf_conn_list(int fd, npf_conn_func_t fun, void *v)
   1423  1.41  christos {
   1424  1.41  christos 	nl_config_t *ncf;
   1425  1.41  christos 
   1426  1.41  christos 	ncf = npf_config_retrieve(fd);
   1427  1.41  christos 	if (ncf == NULL) {
   1428  1.41  christos 		return errno;
   1429  1.41  christos 	}
   1430  1.41  christos 
   1431  1.41  christos         /* Connection list - array */
   1432  1.41  christos         if (prop_object_type(ncf->ncf_conn_list) != PROP_TYPE_ARRAY) {
   1433  1.41  christos                 return EINVAL;
   1434  1.41  christos         }
   1435  1.41  christos 
   1436  1.41  christos         prop_object_iterator_t it = prop_array_iterator(ncf->ncf_conn_list);
   1437  1.41  christos         prop_dictionary_t condict;
   1438  1.41  christos         while ((condict = prop_object_iterator_next(it)) != NULL) {
   1439  1.41  christos                 if (prop_object_type(condict) != PROP_TYPE_DICTIONARY) {
   1440  1.41  christos 			return EINVAL;
   1441  1.41  christos                 }
   1442  1.41  christos 		npf_conn_handle(condict, fun, v);
   1443  1.41  christos 	}
   1444  1.41  christos 	return 0;
   1445  1.41  christos }
   1446