NPF checkpoint:

- Add libnpf(3) - a library to control NPF (configuration, ruleset, etc).
- Add NPF support for ftp-proxy(8).
- Add rc.d script for NPF.
- Convert npfctl(8) to use libnpf(3) and thus make it less depressive.
  Note: next clean-up step should be a parser, once dholland@ will finish it.
- Add more documentation.
- Various fixes.
This commit is contained in:
rmind 2011-02-02 02:20:24 +00:00
parent e43028272f
commit 07ac07d35f
43 changed files with 2095 additions and 811 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: filter.c,v 1.2 2008/06/18 09:06:26 yamt Exp $ */
/* $NetBSD: filter.c,v 1.3 2011/02/02 02:20:26 rmind Exp $ */
/* $OpenBSD: filter.c,v 1.6 2007/08/01 09:31:41 henning Exp $ */
/*
@ -36,16 +36,26 @@
#include "filter.h"
#if defined(__NetBSD__) && defined(WITH_IPF)
#include "ipf.h"
#endif /* __NetBSD__ && WITH_IPF */
/* From netinet/in.h, but only _KERNEL_ gets them. */
#define satosin(sa) ((struct sockaddr_in *)(sa))
#define satosin6(sa) ((struct sockaddr_in6 *)(sa))
#define FTP_PROXY_ANCHOR "ftp-proxy"
enum { TRANS_FILTER = 0, TRANS_NAT, TRANS_RDR, TRANS_SIZE };
int add_filter(u_int32_t, u_int8_t, struct sockaddr *, struct sockaddr *,
u_int16_t);
int add_nat(u_int32_t, struct sockaddr *, struct sockaddr *, u_int16_t,
struct sockaddr *, u_int16_t, u_int16_t);
int add_rdr(u_int32_t, struct sockaddr *, struct sockaddr *, u_int16_t,
struct sockaddr *, u_int16_t);
int do_commit(void);
int do_rollback(void);
void init_filter(char *, char *, int);
int prepare_commit(u_int32_t);
int server_lookup(struct sockaddr *, struct sockaddr *, struct sockaddr *);
int prepare_rule(u_int32_t, int, struct sockaddr *, struct sockaddr *,
u_int16_t);
int server_lookup4(struct sockaddr_in *, struct sockaddr_in *,
@ -60,14 +70,21 @@ static struct pfioc_trans_e pfte[TRANS_SIZE];
static int dev, rule_log;
static char *qname, *tagname;
const ftp_proxy_ops_t pf_fprx_ops = {
.init_filter = init_filter,
.add_filter = add_filter,
.add_nat = add_nat,
.add_rdr = add_rdr,
.server_lookup = server_lookup,
.prepare_commit = prepare_commit,
.do_commit = do_commit,
.do_rollback = do_rollback
};
int
add_filter(u_int32_t id, u_int8_t dir, struct sockaddr *src,
struct sockaddr *dst, u_int16_t d_port)
{
#if defined(__NetBSD__) && defined(WITH_IPF)
if (ipf_enabled)
return ipf_add_filter(id, dir, src, dst, d_port);
#endif /* __NetBSD__ && WITH_IPF */
if (!src || !dst || !d_port) {
errno = EINVAL;
@ -89,11 +106,6 @@ add_nat(u_int32_t id, struct sockaddr *src, struct sockaddr *dst,
u_int16_t d_port, struct sockaddr *nat, u_int16_t nat_range_low,
u_int16_t nat_range_high)
{
#if defined(__NetBSD__) && defined(WITH_IPF)
if (ipf_enabled)
return ipf_add_nat(id, src, dst, d_port, nat, nat_range_low,
nat_range_high);
#endif /* __NetBSD__ && WITH_IPF */
if (!src || !dst || !d_port || !nat || !nat_range_low ||
(src->sa_family != nat->sa_family)) {
@ -128,10 +140,6 @@ int
add_rdr(u_int32_t id, struct sockaddr *src, struct sockaddr *dst,
u_int16_t d_port, struct sockaddr *rdr, u_int16_t rdr_port)
{
#if defined(__NetBSD__) && defined(WITH_IPF)
if (ipf_enabled)
return ipf_add_rdr(id, src, dst, d_port, rdr, rdr_port);
#endif /* __NetBSD__ && WITH_IPF */
if (!src || !dst || !d_port || !rdr || !rdr_port ||
(src->sa_family != rdr->sa_family)) {
@ -164,10 +172,6 @@ add_rdr(u_int32_t id, struct sockaddr *src, struct sockaddr *dst,
int
do_commit(void)
{
#if defined(__NetBSD__) && defined(WITH_IPF)
if (ipf_enabled)
return ipf_do_commit();
#endif /* __NetBSD__ && WITH_IPF */
if (ioctl(dev, DIOCXCOMMIT, &pft) == -1)
return (-1);
@ -178,10 +182,6 @@ do_commit(void)
int
do_rollback(void)
{
#if defined(__NetBSD__) && defined(WITH_IPF)
if (ipf_enabled)
return ipf_do_rollback();
#endif /* __NetBSD__ && WITH_IPF */
if (ioctl(dev, DIOCXROLLBACK, &pft) == -1)
return (-1);
@ -194,13 +194,6 @@ init_filter(char *opt_qname, char *opt_tagname, int opt_verbose)
{
struct pf_status status;
#if defined(__NetBSD__) && defined(WITH_IPF)
if (ipf_enabled) {
ipf_init_filter(opt_qname, opt_tagname, opt_verbose);
return;
}
#endif /* __NetBSD__ && WITH_IPF */
qname = opt_qname;
tagname = opt_tagname;
@ -224,11 +217,6 @@ prepare_commit(u_int32_t id)
char an[PF_ANCHOR_NAME_SIZE];
int i;
#if defined(__NetBSD__) && defined(WITH_IPF)
if (ipf_enabled)
return ipf_prepare_commit(id);
#endif /* __NetBSD__ && WITH_IPF */
memset(&pft, 0, sizeof pft);
pft.size = TRANS_SIZE;
pft.esize = sizeof pfte[0];
@ -364,10 +352,6 @@ int
server_lookup(struct sockaddr *client, struct sockaddr *proxy,
struct sockaddr *server)
{
#if defined(__NetBSD__) && defined(WITH_IPF)
if (ipf_enabled)
return ipf_server_lookup(client, proxy, server);
#endif /* __NetBSD__ && WITH_IPF */
if (client->sa_family == AF_INET)
return (server_lookup4(satosin(client), satosin(proxy),

View File

@ -1,5 +1,4 @@
/* $NetBSD: filter.h,v 1.2 2008/06/18 09:06:26 yamt Exp $ */
/* $OpenBSD: filter.h,v 1.4 2007/08/01 09:31:41 henning Exp $ */
/* $NetBSD: filter.h,v 1.3 2011/02/02 02:20:26 rmind Exp $ */
/*
* Copyright (c) 2004, 2005 Camiel Dobbelaar, <cd@sentia.nl>
@ -17,16 +16,34 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#define FTP_PROXY_ANCHOR "ftp-proxy"
#ifndef _FTP_PROXY_FILTER_H_
#define _FTP_PROXY_FILTER_H_
int add_filter(u_int32_t, u_int8_t, struct sockaddr *, struct sockaddr *,
u_int16_t);
int add_nat(u_int32_t, struct sockaddr *, struct sockaddr *, u_int16_t,
struct sockaddr *, u_int16_t, u_int16_t);
int add_rdr(u_int32_t, struct sockaddr *, struct sockaddr *, u_int16_t,
struct sockaddr *, u_int16_t);
int do_commit(void);
int do_rollback(void);
void init_filter(char *, char *, int);
int prepare_commit(u_int32_t);
int server_lookup(struct sockaddr *, struct sockaddr *, struct sockaddr *);
typedef struct {
void (*init_filter)(char *, char *, int);
int (*add_filter)(uint32_t, uint8_t, struct sockaddr *,
struct sockaddr *, uint16_t);
int (*add_nat)(uint32_t, struct sockaddr *, struct sockaddr *,
uint16_t, struct sockaddr *, u_int16_t, u_int16_t);
int (*add_rdr)(uint32_t, struct sockaddr *, struct sockaddr *,
uint16_t, struct sockaddr *, uint16_t);
int (*server_lookup)(struct sockaddr *, struct sockaddr *,
struct sockaddr *);
int (*prepare_commit)(u_int32_t);
int (*do_commit)(void);
int (*do_rollback)(void);
} ftp_proxy_ops_t;
extern const ftp_proxy_ops_t pf_fprx_ops;
#if defined(__NetBSD__) && defined(WITH_NPF)
extern const ftp_proxy_ops_t npf_fprx_ops;
extern const char * netif;
#endif
#if defined(__NetBSD__) && defined(WITH_IPF)
extern const ftp_proxy_ops_t ipf_fprx_ops;
extern char * npfopts;
#endif
#endif

View File

@ -1,4 +1,4 @@
/* $NetBSD: ftp-proxy.c,v 1.3 2009/07/13 19:05:39 roy Exp $ */
/* $NetBSD: ftp-proxy.c,v 1.4 2011/02/02 02:20:26 rmind Exp $ */
/* $OpenBSD: ftp-proxy.c,v 1.15 2007/08/15 15:18:02 camield Exp $ */
/*
@ -45,10 +45,6 @@
#include "filter.h"
#if defined(__NetBSD__) && defined(WITH_IPF)
#include "ipf.h"
#endif /* __NetBSD__ && WITH_IPF */
#define CONNECT_TIMEOUT 30
#define MIN_PORT 1024
#define MAX_LINE 500
@ -134,9 +130,8 @@ int anonymous_only, daemonize, id_count, ipv6_mode, loglevel, max_sessions,
rfc_mode, session_count, timeout, verbose;
extern char *__progname;
#if defined(__NetBSD__) && defined(WITH_IPF)
int ipf_enabled = 0;
#endif /* __NetBSD__ && WITH_IPF */
/* Default: PF operations. */
static const ftp_proxy_ops_t * fops = &pf_fprx_ops;
void
client_error(struct bufferevent *bufev, short what, void *arg)
@ -321,11 +316,11 @@ end_session(struct session *s)
/* Remove rulesets by commiting empty ones. */
error = 0;
if (prepare_commit(s->id) == -1)
if (fops->prepare_commit(s->id) == -1)
error = errno;
else if (do_commit() == -1) {
else if (fops->do_commit() == -1) {
error = errno;
do_rollback();
fops->do_rollback();
}
if (error)
logmsg(LOG_ERR, "#%d pf rule removal failed: %s", s->id,
@ -451,7 +446,7 @@ handle_connection(const int listen_fd, short event, void *ev)
strerror(errno));
goto fail;
}
if (server_lookup(client_sa, client_to_proxy_sa, server_sa) != 0) {
if (fops->server_lookup(client_sa, client_to_proxy_sa, server_sa)) {
logmsg(LOG_CRIT, "#%d server lookup failed (no rdr?)", s->id);
goto fail;
}
@ -643,11 +638,12 @@ main(int argc, char *argv[])
id_count = 1;
session_count = 0;
#if defined(__NetBSD__) && defined(WITH_IPF)
while ((ch = getopt(argc, argv, "6Aa:b:D:di:m:P:p:q:R:rT:t:v")) != -1) {
#else
while ((ch = getopt(argc, argv, "6Aa:b:D:dm:P:p:q:R:rT:t:v")) != -1) {
#endif /* __NetBSD__ && WITH_IPF */
#if defined(__NetBSD__)
/* Note: both for IPFilter and NPF. */
#define NBSD_OPTS "i:N:"
#endif
while ((ch = getopt(argc, argv,
"6Aa:b:D:d" NBSD_OPTS "m:P:p:q:R:rT:t:v")) != -1) {
switch (ch) {
case '6':
ipv6_mode = 1;
@ -670,17 +666,23 @@ main(int argc, char *argv[])
case 'd':
daemonize = 0;
break;
#if defined(__NetBSD__) && defined(WITH_IPF)
case 'i':
ipf_enabled = 1;
#if defined(__NetBSD__) && defined(WITH_IPF)
fops = &ipf_fprx_ops;
netif = optarg;
#endif
break;
#endif /* __NetBSD__ && WITH_IPF */
case 'm':
max_sessions = strtonum(optarg, 1, 500, &errstr);
if (errstr)
errx(1, "max sessions %s", errstr);
break;
case 'N':
#if defined(__NetBSD__) && defined(WITH_NPF)
fops = &npf_fprx_ops;
npfopts = optarg;
#endif
break;
case 'P':
fixed_server_port = optarg;
break;
@ -783,7 +785,7 @@ main(int argc, char *argv[])
freeaddrinfo(res);
/* Initialize pf. */
init_filter(qname, tagname, verbose);
fops->init_filter(qname, tagname, verbose);
if (daemonize) {
if (daemon(0, 0) == -1)
@ -1006,7 +1008,7 @@ allow_data_connection(struct session *s)
logmsg(LOG_INFO, "#%d passive: client to server port %d"
" via port %d", s->id, s->port, s->proxy_port);
if (prepare_commit(s->id) == -1)
if (fops->prepare_commit(s->id) == -1)
goto fail;
prepared = 1;
@ -1015,22 +1017,23 @@ allow_data_connection(struct session *s)
/* rdr from $client to $orig_server port $proxy_port -> $server
port $port */
if (add_rdr(s->id, client_sa, orig_sa, s->proxy_port,
if (fops->add_rdr(s->id, client_sa, orig_sa, s->proxy_port,
server_sa, s->port) == -1)
goto fail;
/* nat from $client to $server port $port -> $proxy */
if (add_nat(s->id, client_sa, server_sa, s->port, proxy_sa,
PF_NAT_PROXY_PORT_LOW, PF_NAT_PROXY_PORT_HIGH) == -1)
if (fops->add_nat(s->id, client_sa, server_sa, s->port,
proxy_sa, PF_NAT_PROXY_PORT_LOW, PF_NAT_PROXY_PORT_HIGH)
== -1)
goto fail;
/* pass in from $client to $server port $port */
if (add_filter(s->id, PF_IN, client_sa, server_sa,
if (fops->add_filter(s->id, PF_IN, client_sa, server_sa,
s->port) == -1)
goto fail;
/* pass out from $proxy to $server port $port */
if (add_filter(s->id, PF_OUT, proxy_sa, server_sa,
if (fops->add_filter(s->id, PF_OUT, proxy_sa, server_sa,
s->port) == -1)
goto fail;
}
@ -1040,49 +1043,49 @@ allow_data_connection(struct session *s)
logmsg(LOG_INFO, "#%d active: server to client port %d"
" via port %d", s->id, s->port, s->proxy_port);
if (prepare_commit(s->id) == -1)
if (fops->prepare_commit(s->id) == -1)
goto fail;
prepared = 1;
/* rdr from $server to $proxy port $proxy_port -> $client port
$port */
if (add_rdr(s->id, server_sa, proxy_sa, s->proxy_port,
client_sa, s->port) == -1)
if (fops->add_rdr(s->id, server_sa, proxy_sa,
s->proxy_port, client_sa, s->port) == -1)
goto fail;
/* nat from $server to $client port $port -> $orig_server port
$natport */
if (rfc_mode && s->cmd == CMD_PORT) {
/* Rewrite sourceport to RFC mandated 20. */
if (add_nat(s->id, server_sa, client_sa, s->port,
orig_sa, 20, 20) == -1)
if (fops->add_nat(s->id, server_sa, client_sa,
s->port, orig_sa, 20, 20) == -1)
goto fail;
} else {
/* Let pf pick a source port from the standard range. */
if (add_nat(s->id, server_sa, client_sa, s->port,
orig_sa, PF_NAT_PROXY_PORT_LOW,
if (fops->add_nat(s->id, server_sa, client_sa,
s->port, orig_sa, PF_NAT_PROXY_PORT_LOW,
PF_NAT_PROXY_PORT_HIGH) == -1)
goto fail;
}
/* pass in from $server to $client port $port */
if (add_filter(s->id, PF_IN, server_sa, client_sa, s->port) ==
-1)
if (fops->add_filter(s->id, PF_IN, server_sa, client_sa,
s->port) == -1)
goto fail;
/* pass out from $orig_server to $client port $port */
if (add_filter(s->id, PF_OUT, orig_sa, client_sa, s->port) ==
-1)
if (fops->add_filter(s->id, PF_OUT, orig_sa, client_sa,
s->port) == -1)
goto fail;
}
/* Commit rules if they were prepared. */
if (prepared && (do_commit() == -1)) {
if (prepared && (fops->do_commit() == -1)) {
if (errno != EBUSY)
goto fail;
/* One more try if busy. */
usleep(5000);
if (do_commit() == -1)
if (fops->do_commit() == -1)
goto fail;
}
@ -1094,7 +1097,7 @@ allow_data_connection(struct session *s)
fail:
logmsg(LOG_CRIT, "#%d pf operation failed: %s", s->id, strerror(errno));
if (prepared)
do_rollback();
fops->do_rollback();
return (0);
}
@ -1162,9 +1165,14 @@ usage(void)
{
fprintf(stderr, "usage: %s [-6Adrv] [-a address] [-b address]"
" [-D level] [-m maxsessions]\n [-P port]"
#if defined(__NetBSD__) && defined(WITH_IPF)
#if defined(__NetBSD__)
#if defined(WITH_IPF)
" [-i netif]"
#endif /* __NetBSD__ && WITH_IPF */
#endif
#if defined(WITH_NPF)
" [-N netif:addr:port]"
#endif
#endif
" [-p port] [-q queue] [-R address] [-T tag] [-t timeout]\n",
__progname);

View File

@ -1,4 +1,4 @@
/* $NetBSD: ipf.c,v 1.2 2008/06/18 09:06:26 yamt Exp $ */
/* $NetBSD: ipf.c,v 1.3 2011/02/02 02:20:26 rmind Exp $ */
/*
* Copyright (c) 2004, 2008 The NetBSD Foundation, Inc.
@ -50,7 +50,30 @@
#include <string.h>
#include <unistd.h>
#include "ipf.h"
#include "filter.h"
void ipf_init_filter(char *, char *, int);
int ipf_add_filter(u_int32_t, u_int8_t, struct sockaddr *, struct sockaddr *,
u_int16_t);
int ipf_add_nat(u_int32_t, struct sockaddr *, struct sockaddr *, u_int16_t,
struct sockaddr *, u_int16_t, u_int16_t);
int ipf_add_rdr(u_int32_t, struct sockaddr *, struct sockaddr *, u_int16_t,
struct sockaddr *, u_int16_t);
int ipf_server_lookup(struct sockaddr *, struct sockaddr *, struct sockaddr *);
int ipf_prepare_commit(u_int32_t);
int ipf_do_commit(void);
int ipf_do_rollback(void);
const ftp_proxy_ops_t ipf_fprx_ops = {
.init_filter = ipf_init_filter,
.add_filter = ipf_add_filter,
.add_nat = ipf_add_nat,
.add_rdr = ipf_add_rdr,
.server_lookup = ipf_server_lookup,
.prepare_commit = ipf_prepare_commit,
.do_commit = ipf_do_commit,
.do_rollback = ipf_do_rollback
};
/* From netinet/in.h, but only _KERNEL_ gets them. */
#define satosin(sa) ((struct sockaddr_in *)(sa))

337
dist/pf/usr.sbin/ftp-proxy/npf.c vendored Normal file
View File

@ -0,0 +1,337 @@
/* $NetBSD: npf.c,v 1.1 2011/02/02 02:20:26 rmind Exp $ */
/*
* Copyright (c) 2011 The NetBSD Foundation, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#include <sys/param.h>
#include <sys/types.h>
#include <sys/queue.h>
#include <netinet/in.h>
#include <netinet/in_systm.h>
#include <arpa/inet.h>
#include <net/if.h>
#include <net/pfvar.h>
#include <net/npf_ncode.h>
#include <npf.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <errno.h>
#include <err.h>
#include <assert.h>
#include "filter.h"
static void npf_init_filter(char *, char *, int);
static int npf_add_filter(uint32_t, uint8_t, struct sockaddr *,
struct sockaddr *, uint16_t);
static int npf_add_nat(uint32_t, struct sockaddr *, struct sockaddr *,
uint16_t, struct sockaddr *, uint16_t, uint16_t);
static int npf_add_rdr(uint32_t, struct sockaddr *, struct sockaddr *,
uint16_t, struct sockaddr *, uint16_t);
static int npf_server_lookup(struct sockaddr *, struct sockaddr *,
struct sockaddr *);
static int npf_prepare_commit(uint32_t);
static int npf_do_commit(void);
static int npf_do_rollback(void);
const ftp_proxy_ops_t npf_fprx_ops = {
.init_filter = npf_init_filter,
.add_filter = npf_add_filter,
.add_nat = npf_add_nat,
.add_rdr = npf_add_rdr,
.server_lookup = npf_server_lookup,
.prepare_commit = npf_prepare_commit,
.do_commit = npf_do_commit,
.do_rollback = npf_do_rollback
};
#define sa_to_32(sa) (((struct sockaddr_in *)sa)->sin_addr.s_addr)
#define NPF_DEV_PATH "/dev/npf"
#define NPF_FP_RULE_TAG "ftp-proxy"
typedef struct fp_ent {
LIST_ENTRY(fp_ent) fpe_list;
uint32_t fpe_id;
nl_rule_t * fpe_rl;
nl_rule_t * fpe_nat;
nl_rule_t * fpe_rdr;
} fp_ent_t;
char * npfopts;
static LIST_HEAD(, fp_ent) fp_ent_list;
static fp_ent_t * fp_ent_hint;
static struct sockaddr_in fp_server_sa;
static u_int fp_if_idx;
static int npf_fd;
static uint32_t ncode[ ] = {
/* from <shost> to <dhost> port <dport> */
NPF_OPCODE_IP4MASK, 0x01, 0xdeadbeef, 0xffffffff,
NPF_OPCODE_BNE, 15,
NPF_OPCODE_IP4MASK, 0x00, 0xdeadbeef, 0xffffffff,
NPF_OPCODE_BNE, 9,
NPF_OPCODE_TCP_PORTS, 0x00, 0xdeadbeef,
NPF_OPCODE_BNE, 4,
/* Success (0x0) and failure (0xff) paths. */
NPF_OPCODE_RET, 0x00,
NPF_OPCODE_RET, 0xff
};
static void
ftp_proxy_modify_nc(in_addr_t shost, in_addr_t dhost, in_port_t dport)
{
/* Source address to match. */
ncode[2] = shost;
/* Destination address to match. */
ncode[8] = shost;
/* Destination port to match. */
ncode[14] = ((uint32_t)dport << 16) | dport;
}
static fp_ent_t *
ftp_proxy_lookup(uint32_t id)
{
fp_ent_t *fpe;
/* Look for FTP proxy entry. First, try hint (last used). */
if (fp_ent_hint && fp_ent_hint->fpe_id == id) {
return fp_ent_hint;
}
LIST_FOREACH(fpe, &fp_ent_list, fpe_list) {
if (fpe->fpe_id == id)
break;
}
return fpe;
}
static void
npf_init_filter(char *opt_qname, char *opt_tagname, int opt_verbose)
{
char *netif = npfopts, *saddr, *port;
/* XXX get rid of this */
saddr = strchr(netif, ':');
if (saddr == NULL) {
errx(EXIT_FAILURE, "invalid -N option string: %s", npfopts);
}
*saddr++ = '\0';
if (saddr == NULL || (port = strchr(saddr, ':')) == NULL) {
errx(EXIT_FAILURE, "invalid -N option string: %s", npfopts);
}
*port++ = '\0';
if (port == NULL) {
errx(EXIT_FAILURE, "invalid -N option string: %s", npfopts);
}
fp_if_idx = if_nametoindex(netif);
if (fp_if_idx == 0) {
errx(EXIT_FAILURE, "invalid network interface '%s'", netif);
}
memset(&fp_server_sa, 0, sizeof(struct sockaddr_in));
fp_server_sa.sin_len = sizeof(struct sockaddr_in);
fp_server_sa.sin_family = AF_INET;
fp_server_sa.sin_addr.s_addr = inet_addr(saddr);
fp_server_sa.sin_port = htons(atoi(port));
npf_fd = open(NPF_DEV_PATH, O_RDONLY);
if (npf_fd == -1) {
err(EXIT_FAILURE, "cannot open '%s'", NPF_DEV_PATH);
}
LIST_INIT(&fp_ent_list);
fp_ent_hint = NULL;
}
static int
npf_prepare_commit(uint32_t id)
{
fp_ent_t *fpe;
/* Check if already exists. */
fpe = ftp_proxy_lookup(id);
if (fpe) {
/* Destroy existing rules and reset the values. */
npf_rule_destroy(fpe->fpe_rl);
npf_rule_destroy(fpe->fpe_nat);
npf_rule_destroy(fpe->fpe_rdr);
goto reset;
}
/* Create a new one, if not found. */
fpe = malloc(sizeof(fp_ent_t));
if (fpe == NULL) {
return -1;
}
LIST_INSERT_HEAD(&fp_ent_list, fpe, fpe_list);
fpe->fpe_id = id;
reset:
fpe->fpe_rl = NULL;
fpe->fpe_nat = NULL;
fpe->fpe_rdr = NULL;
return 0;
}
static int
npf_add_filter(uint32_t id, uint8_t pf_dir, struct sockaddr *src,
struct sockaddr *dst, uint16_t dport)
{
fp_ent_t *fpe;
nl_rule_t *rl;
int di;
if (!src || !dst || !dport) {
errno = EINVAL;
return -1;
}
fpe = ftp_proxy_lookup(id);
assert(fpe != NULL);
di = (pf_dir == PF_OUT) ? NPF_RULE_OUT : NPF_RULE_IN;
rl = npf_rule_create(NULL, di | NPF_RULE_PASS | NPF_RULE_FINAL, 0);
if (rl == NULL) {
errno = ENOMEM;
return -1;
}
ftp_proxy_modify_nc(sa_to_32(src), sa_to_32(dst), htons(dport));
errno = npf_rule_setcode(rl, NPF_CODE_NCODE, ncode, sizeof(ncode));
if (errno) {
npf_rule_destroy(rl);
return -1;
}
assert(fpe->fpe_rl == NULL);
fpe->fpe_rl = rl;
return 0;
}
static int
npf_add_nat(uint32_t id, struct sockaddr *src, struct sockaddr *dst,
uint16_t dport, struct sockaddr *snat, uint16_t plow, uint16_t phigh)
{
fp_ent_t *fpe;
nl_nat_t *nt;
npf_addr_t addr;
if (!src || !dst || !dport || !snat || !plow ||
(src->sa_family != snat->sa_family)) {
errno = EINVAL;
return (-1);
}
fpe = ftp_proxy_lookup(id);
assert(fpe != NULL);
memcpy(&addr, &sa_to_32(snat), sizeof(struct in_addr));
nt = npf_nat_create(NPF_NATOUT, NPF_NAT_PORTS | NPF_NAT_PORTMAP, 0,
&addr, AF_INET, htons(plow));
if (nt == NULL) {
errno = ENOMEM;
return -1;
}
ftp_proxy_modify_nc(sa_to_32(src), sa_to_32(dst), htons(dport));
errno = npf_rule_setcode(nt, NPF_CODE_NCODE, ncode, sizeof(ncode));
if (errno) {
npf_rule_destroy(nt);
return -1;
}
assert(fpe->fpe_nat == NULL);
fpe->fpe_nat = nt;
return 0;
}
static int
npf_add_rdr(uint32_t id, struct sockaddr *src, struct sockaddr *dst,
uint16_t dport, struct sockaddr *rdr, uint16_t rdr_port)
{
fp_ent_t *fpe;
nl_nat_t *nt;
npf_addr_t addr;
if (!src || !dst || !dport || !rdr || !rdr_port ||
(src->sa_family != rdr->sa_family)) {
errno = EINVAL;
return -1;
}
fpe = ftp_proxy_lookup(id);
assert(fpe != NULL);
memcpy(&addr, &sa_to_32(rdr), sizeof(struct in_addr));
nt = npf_nat_create(NPF_NATIN, NPF_NAT_PORTS, 0,
&addr, AF_INET, htons(rdr_port));
if (nt == NULL) {
errno = ENOMEM;
return -1;
}
ftp_proxy_modify_nc(sa_to_32(src), sa_to_32(dst), htons(dport));
errno = npf_rule_setcode(nt, NPF_CODE_NCODE, ncode, sizeof(ncode));
if (errno) {
npf_rule_destroy(nt);
return -1;
}
assert(fpe->fpe_rdr == NULL);
fpe->fpe_rdr = nt;
return 0;
}
static int
npf_server_lookup(struct sockaddr *c, struct sockaddr *proxy,
struct sockaddr *server)
{
memcpy(server, &fp_server_sa, sizeof(struct sockaddr_in));
return 0;
}
static int
npf_do_commit(void)
{
nl_rule_t *group;
fp_ent_t *fpe;
pri_t pri;
group = npf_rule_create(NPF_FP_RULE_TAG, NPF_RULE_PASS | NPF_RULE_IN |
NPF_RULE_OUT | NPF_RULE_FINAL, fp_if_idx);
if (group == NULL) {
return -1;
}
pri = 1;
LIST_FOREACH(fpe, &fp_ent_list, fpe_list) {
npf_rule_insert(NULL, group, fpe->fpe_rl, pri++);
}
npf_update_rule(npf_fd, NPF_FP_RULE_TAG, group);
npf_rule_destroy(group);
return 0;
}
static int
npf_do_rollback(void)
{
/* None. */
return 0;
}

View File

@ -1,4 +1,4 @@
# $NetBSD: ad.mips64eb,v 1.36 2011/01/18 20:09:37 pooka Exp $
# $NetBSD: ad.mips64eb,v 1.37 2011/02/02 02:20:26 rmind Exp $
./libexec/ld.elf_so-64 base-compat-shlib compat,pic
./libexec/ld.elf_so-o32 base-sysutil-bin compat,pic
./usr/lib/64 base-compat-lib
@ -151,6 +151,8 @@
./usr/lib/64/libmj.so.0.0 base-compat-shlib compat,pic,crypto
./usr/lib/64/libnetpgp.so.3 base-compat-shlib compat,pic,crypto
./usr/lib/64/libnetpgp.so.3.0 base-compat-shlib compat,pic,crypto
./usr/lib/64/libnpf.so.0 base-compat-shlib compat,pic,npf
./usr/lib/64/libnpf.so.0.0 base-compat-shlib compat,pic,npf
./usr/lib/64/libobjc.so.3 base-compat-shlib compat,pic
./usr/lib/64/libobjc.so.3.0 base-compat-shlib compat,pic
./usr/lib/64/libopcodes.so.4 base-compat-shlib compat,pic,binutils
@ -408,6 +410,8 @@
./usr/lib/o32/libmj.so.0.0 base-compat-shlib compat,pic,crypto
./usr/lib/o32/libnetpgp.so.3 base-compat-shlib compat,pic,crypto
./usr/lib/o32/libnetpgp.so.3.0 base-compat-shlib compat,pic,crypto
./usr/lib/o32/libnpf.so.0 base-compat-shlib compat,pic,npf
./usr/lib/o32/libnpf.so.0.0 base-compat-shlib compat,pic,npf
./usr/lib/o32/libobjc.so.3 base-compat-shlib compat,pic
./usr/lib/o32/libobjc.so.3.0 base-compat-shlib compat,pic
./usr/lib/o32/libopcodes.so.4 base-compat-shlib compat,pic,binutils

View File

@ -1,4 +1,4 @@
# $NetBSD: ad.mips64el,v 1.34 2011/01/18 20:09:37 pooka Exp $
# $NetBSD: ad.mips64el,v 1.35 2011/02/02 02:20:26 rmind Exp $
./libexec/ld.elf_so-64 base-compat-shlib compat,pic
./libexec/ld.elf_so-o32 base-sysutil-bin compat,pic
./usr/lib/64 base-compat-lib
@ -151,6 +151,8 @@
./usr/lib/64/libmj.so.0.0 base-compat-shlib compat,pic,crypto
./usr/lib/64/libnetpgp.so.3 base-compat-shlib compat,pic,crypto
./usr/lib/64/libnetpgp.so.3.0 base-compat-shlib compat,pic,crypto
./usr/lib/64/libnpf.so.0 base-compat-shlib compat,pic,npf
./usr/lib/64/libnpf.so.0.0 base-compat-shlib compat,pic,npf
./usr/lib/64/libobjc.so.3 base-compat-shlib compat,pic
./usr/lib/64/libobjc.so.3.0 base-compat-shlib compat,pic
./usr/lib/64/libopcodes.so.4 base-compat-shlib compat,pic,binutils
@ -408,6 +410,8 @@
./usr/lib/o32/libmj.so.0.0 base-compat-shlib compat,pic,crypto
./usr/lib/o32/libnetpgp.so.3 base-compat-shlib compat,pic,crypto
./usr/lib/o32/libnetpgp.so.3.0 base-compat-shlib compat,pic,crypto
./usr/lib/o32/libnpf.so.0 base-compat-shlib compat,pic,npf
./usr/lib/o32/libnpf.so.0.0 base-compat-shlib compat,pic,npf
./usr/lib/o32/libobjc.so.3 base-compat-shlib compat,pic
./usr/lib/o32/libobjc.so.3.0 base-compat-shlib compat,pic
./usr/lib/o32/libopcodes.so.4 base-compat-shlib compat,pic,binutils

View File

@ -1,4 +1,4 @@
# $NetBSD: md.amd64,v 1.109 2011/01/18 20:09:37 pooka Exp $
# $NetBSD: md.amd64,v 1.110 2011/02/02 02:20:26 rmind Exp $
./dev/lms0 base-obsolete obsolete
./dev/mms0 base-obsolete obsolete
./libexec/ld.elf_so-i386 base-sys-shlib compat,pic
@ -157,6 +157,8 @@
./usr/lib/i386/libmj.so.0.0 base-compat-shlib compat,pic,crypto
./usr/lib/i386/libnetpgp.so.3 base-compat-shlib compat,pic
./usr/lib/i386/libnetpgp.so.3.0 base-compat-shlib compat,pic
./usr/lib/i386/libnpf.so.0 base-compat-shlib compat,pic,npf
./usr/lib/i386/libnpf.so.0.0 base-compat-shlib compat,pic,npf
./usr/lib/i386/libobjc.so.3 base-compat-shlib compat,pic
./usr/lib/i386/libobjc.so.3.0 base-compat-shlib compat,pic
./usr/lib/i386/libopcodes.so.4 base-compat-shlib compat,pic,binutils

View File

@ -1,4 +1,4 @@
# $NetBSD: md.sparc64,v 1.102 2011/01/18 20:09:38 pooka Exp $
# $NetBSD: md.sparc64,v 1.103 2011/02/02 02:20:26 rmind Exp $
./libexec/ld.elf_so-sparc base-sysutil-bin compat,pic
./sbin/edlabel base-sysutil-root obsolete
./usr/bin/fdformat base-util-bin
@ -154,6 +154,8 @@
./usr/lib/sparc/libmj.so.0.0 base-compat-shlib compat,pic,crypto
./usr/lib/sparc/libnetpgp.so.3 base-compat-shlib compat,pic,crypto
./usr/lib/sparc/libnetpgp.so.3.0 base-compat-shlib compat,pic,crypto
./usr/lib/sparc/libnpf.so.0 base-compat-shlib compat,pic,npf
./usr/lib/sparc/libnpf.so.0.0 base-compat-shlib compat,pic,npf
./usr/lib/sparc/libobjc.so.3 base-compat-shlib compat,pic
./usr/lib/sparc/libobjc.so.3.0 base-compat-shlib compat,pic
./usr/lib/sparc/libopcodes.so.4 base-compat-shlib compat,pic,binutils

View File

@ -1,4 +1,4 @@
# $NetBSD: shl.mi,v 1.570 2011/01/19 21:07:13 he Exp $
# $NetBSD: shl.mi,v 1.571 2011/02/02 02:20:26 rmind Exp $
#
# Note: Don't delete entries from here - mark them as "obsolete" instead,
# unless otherwise stated below.
@ -317,6 +317,9 @@
./usr/lib/libnetpgp.so base-crypto-shlib crypto
./usr/lib/libnetpgp.so.3 base-crypto-shlib crypto
./usr/lib/libnetpgp.so.3.0 base-crypto-shlib crypto
./usr/lib/libnpf.so base-npf-shlib npf
./usr/lib/libnpf.so.0 base-npf-shlib npf
./usr/lib/libnpf.so.0.0 base-npf-shlib npf
./usr/lib/libnvpair.so base-zfs-shlib dynamicroot,zfs
./usr/lib/libnvpair.so.0 base-zfs-shlib dynamicroot,zfs
./usr/lib/libnvpair.so.0.0 base-zfs-shlib zfs,dynamicroot

View File

@ -1,4 +1,4 @@
# $NetBSD: ad.mips64eb,v 1.19 2011/01/31 18:27:53 christos Exp $
# $NetBSD: ad.mips64eb,v 1.20 2011/02/02 02:20:27 rmind Exp $
./usr/bin/elf2aout comp-obsolete obsolete
./usr/bin/elf2ecoff comp-sysutil-bin
./usr/include/mips comp-c-include
@ -392,6 +392,10 @@
./usr/lib/64/libnetpgp.so comp-sys-shlib compat,crypto,pic
./usr/lib/64/libnetpgp_p.a comp-c-proflib compat,crypto,profile
./usr/lib/64/libnetpgp_pic.a comp-c-piclib compat,crypto,pic
./usr/lib/64/libnpf.a comp-c-lib compat,npf
./usr/lib/64/libnpf.so comp-sys-shlib compat,npf,pic
./usr/lib/64/libnpf_p.a comp-c-proflib compat,npf,profile
./usr/lib/64/libnpf_pic.a comp-c-piclib compat,npf,pic
./usr/lib/64/libobjc.a comp-c-lib compat
./usr/lib/64/libobjc.so base-sys-shlib compat,pic
./usr/lib/64/libobjc_p.a comp-c-proflib compat,profile
@ -899,6 +903,10 @@
./usr/lib/o32/libnetpgp.so comp-sys-shlib compat,crypto,pic
./usr/lib/o32/libnetpgp_p.a comp-c-proflib compat,crypto,profile
./usr/lib/o32/libnetpgp_pic.a comp-c-piclib compat,crypto,pic
./usr/lib/o32/libnpf.a comp-c-lib compat,npf
./usr/lib/o32/libnpf.so comp-sys-shlib compat,npf,pic
./usr/lib/o32/libnpf_p.a comp-c-proflib compat,npf,profile
./usr/lib/o32/libnpf_pic.a comp-c-piclib compat,npf,pic
./usr/lib/o32/libobjc.a comp-c-lib compat
./usr/lib/o32/libobjc.so base-sys-shlib compat,pic
./usr/lib/o32/libobjc_p.a comp-c-proflib compat,profile

View File

@ -1,4 +1,4 @@
# $NetBSD: ad.mips64el,v 1.19 2011/01/31 18:27:53 christos Exp $
# $NetBSD: ad.mips64el,v 1.20 2011/02/02 02:20:27 rmind Exp $
./usr/bin/elf2aout comp-obsolete obsolete
./usr/bin/elf2ecoff comp-sysutil-bin
./usr/include/mips comp-c-include
@ -392,6 +392,10 @@
./usr/lib/64/libnetpgp.so comp-sys-shlib compat,crypto,pic
./usr/lib/64/libnetpgp_p.a comp-c-proflib compat,crypto,profile
./usr/lib/64/libnetpgp_pic.a comp-c-piclib compat,crypto,pic
./usr/lib/64/libnpf.a comp-c-lib compat,npf
./usr/lib/64/libnpf.so comp-sys-shlib compat,npf,pic
./usr/lib/64/libnpf_p.a comp-c-proflib compat,npf,profile
./usr/lib/64/libnpf_pic.a comp-c-piclib compat,npf,pic
./usr/lib/64/libobjc.a comp-c-lib compat
./usr/lib/64/libobjc.so base-sys-shlib compat,pic
./usr/lib/64/libobjc_p.a comp-c-proflib compat,profile
@ -899,6 +903,10 @@
./usr/lib/o32/libnetpgp.so comp-sys-shlib compat,crypto,pic
./usr/lib/o32/libnetpgp_p.a comp-c-proflib compat,crypto,profile
./usr/lib/o32/libnetpgp_pic.a comp-c-piclib compat,crypto,pic
./usr/lib/o32/libnpf.a comp-c-lib compat,npf
./usr/lib/o32/libnpf.so comp-sys-shlib compat,npf,pic
./usr/lib/o32/libnpf_p.a comp-c-proflib compat,npf,profile
./usr/lib/o32/libnpf_pic.a comp-c-piclib compat,npf,pic
./usr/lib/o32/libobjc.a comp-c-lib compat
./usr/lib/o32/libobjc.so base-sys-shlib compat,pic
./usr/lib/o32/libobjc_p.a comp-c-proflib compat,profile

View File

@ -1,4 +1,4 @@
# $NetBSD: md.amd64,v 1.93 2011/01/20 14:54:24 njoly Exp $
# $NetBSD: md.amd64,v 1.94 2011/02/02 02:20:27 rmind Exp $
./usr/include/amd64 comp-c-include
./usr/include/amd64/ansi.h comp-c-include
./usr/include/amd64/aout_machdep.h comp-c-include
@ -656,6 +656,11 @@
./usr/lib/i386/libnetpgp_g.a comp-c-proflib compat,debuglib
./usr/lib/i386/libnetpgp_p.a comp-c-proflib compat,profile
./usr/lib/i386/libnetpgp_pic.a comp-c-piclib compat,pic
./usr/lib/i386/libnpf.a comp-c-lib compat,npf
./usr/lib/i386/libnpf.so comp-sys-shlib compat,npf,pic
./usr/lib/i386/libnpf_g.a comp-c-proflib compat,npf,debuglib
./usr/lib/i386/libnpf_p.a comp-c-proflib compat,npf,profile
./usr/lib/i386/libnpf_pic.a comp-c-piclib compat,npf,pic
./usr/lib/i386/libobjc.a comp-c-lib compat
./usr/lib/i386/libobjc.so comp-sys-shlib compat,pic
./usr/lib/i386/libobjc_g.a comp-c-proflib compat,debuglib
@ -952,6 +957,7 @@
./usr/libdata/debug/usr/lib/i386/libmenu.so.6.0.debug comp-compat-shlib compat,pic,debug
./usr/libdata/debug/usr/lib/i386/libmj.so.0.0.debug comp-compat-shlib compat,pic,debug
./usr/libdata/debug/usr/lib/i386/libnetpgp.so.3.0.debug comp-compat-shlib compat,pic,debug
./usr/libdata/debug/usr/lib/i386/libnpf.so.0.0.debug comp-compat-shlib compat,pic,npf,debug
./usr/libdata/debug/usr/lib/i386/libobjc.so.3.0.debug comp-compat-shlib compat,pic,debug
./usr/libdata/debug/usr/lib/i386/libopcodes.so.4.0.debug comp-compat-shlib compat,pic,binutils,debug
./usr/libdata/debug/usr/lib/i386/libossaudio.so.1.0.debug comp-compat-shlib compat,pic,debug

View File

@ -1,4 +1,4 @@
# $NetBSD: md.sparc64,v 1.82 2011/01/31 18:49:43 matt Exp $
# $NetBSD: md.sparc64,v 1.83 2011/02/02 02:20:27 rmind Exp $
./usr/include/ieeefp.h comp-c-include
./usr/include/sparc comp-c-include
./usr/include/sparc/_G_config.h comp-obsolete obsolete
@ -466,6 +466,10 @@
./usr/lib/sparc/libnetpgp.so comp-sys-shlib compat,pic,crypto
./usr/lib/sparc/libnetpgp_p.a comp-c-proflib compat,profile,crypto
./usr/lib/sparc/libnetpgp_pic.a comp-c-piclib compat,pic,crypto
./usr/lib/sparc/libnpf.a comp-c-lib compat,npf
./usr/lib/sparc/libnpf.so comp-sys-shlib compat,pic,npf
./usr/lib/sparc/libnpf_p.a comp-c-proflib compat,profile,npf
./usr/lib/sparc/libnpf_pic.a comp-c-piclib compat,pic,npf
./usr/lib/sparc/libobjc.a comp-c-lib compat
./usr/lib/sparc/libobjc.so base-sys-shlib compat,pic
./usr/lib/sparc/libobjc_p.a comp-c-proflib compat,profile
@ -716,6 +720,7 @@
./usr/libdata/debug/usr/lib/sparc/libmenu.so.6.0.debug comp-compat-shlib compat,pic,debug
./usr/libdata/debug/usr/lib/sparc/libmj.so.0.0.debug comp-compat-shlib compat,pic,debug
./usr/libdata/debug/usr/lib/sparc/libnetpgp.so.3.0.debug comp-compat-shlib compat,pic,debug
./usr/libdata/debug/usr/lib/sparc/libnpf.so.0.0.debug comp-compat-shlib compat,pic,debug,npf
./usr/libdata/debug/usr/lib/sparc/libobjc.so.3.0.debug comp-compat-shlib compat,pic,debug
./usr/libdata/debug/usr/lib/sparc/libopcodes.so.4.0.debug comp-compat-shlib compat,pic,binutils,debug
./usr/libdata/debug/usr/lib/sparc/libossaudio.so.1.0.debug comp-compat-shlib compat,pic,debug

View File

@ -1,4 +1,4 @@
# $NetBSD: mi,v 1.1578 2011/01/28 18:52:48 pooka Exp $
# $NetBSD: mi,v 1.1579 2011/02/02 02:20:27 rmind Exp $
#
# Note: don't delete entries from here - mark them as "obsolete" instead.
#
@ -1703,6 +1703,7 @@
./usr/include/nfs/xdr_subs.h comp-c-include
./usr/include/nl_types.h comp-c-include
./usr/include/nlist.h comp-c-include
./usr/include/npf.h comp-npf-include npf
./usr/include/nsswitch.h comp-c-include
./usr/include/ntfs/ntfs.h comp-c-include
./usr/include/ntfs/ntfs_compr.h comp-obsolete obsolete
@ -2560,6 +2561,9 @@
./usr/lib/libnetpgp.a comp-c-lib crypto
./usr/lib/libnetpgp_g.a -unknown- debuglib
./usr/lib/libnetpgp_p.a comp-c-proflib profile,crypto
./usr/lib/libnpf.a comp-npf-lib npf
./usr/lib/libnpf_g.a -unknown- debuglib
./usr/lib/libnpf_p.a comp-npf-proflib profile,npf
./usr/lib/libntp.a comp-obsolete obsolete
./usr/lib/libntp_p.a comp-obsolete obsolete
./usr/lib/libntp_pic.a comp-obsolete obsolete
@ -3913,6 +3917,7 @@
./usr/libdata/lint/llib-lmilter.ln comp-obsolete obsolete
./usr/libdata/lint/llib-lmj.ln comp-c-lintlib lint,crypto
./usr/libdata/lint/llib-lnetpgp.ln comp-c-lintlib lint,crypto
./usr/libdata/lint/llib-lnpf.ln comp-npf-lintlib lint,npf
./usr/libdata/lint/llib-lntp.ln comp-obsolete obsolete
./usr/libdata/lint/llib-lopenpgpsdk.ln comp-obsolete obsolete
./usr/libdata/lint/llib-lossaudio.ln comp-c-lintlib lint
@ -7442,6 +7447,7 @@
./usr/share/man/cat3/noqiflush.0 comp-c-catman .cat
./usr/share/man/cat3/noraw.0 comp-c-catman .cat
./usr/share/man/cat3/notimeout.0 comp-c-catman .cat
./usr/share/man/cat3/npf.0 comp-npf-catman .cat
./usr/share/man/cat3/nrand48.0 comp-c-catman .cat
./usr/share/man/cat3/ns.0 comp-obsolete obsolete
./usr/share/man/cat3/ns_addr.0 comp-obsolete obsolete
@ -13455,6 +13461,7 @@
./usr/share/man/html3/noqiflush.html comp-c-htmlman html
./usr/share/man/html3/noraw.html comp-c-htmlman html
./usr/share/man/html3/notimeout.html comp-c-htmlman html
./usr/share/man/html3/npf.html comp-npf-htmlman html
./usr/share/man/html3/nrand48.html comp-c-htmlman html
./usr/share/man/html3/nsdispatch.html comp-c-htmlman html
./usr/share/man/html3/ntoa.html comp-c-htmlman html
@ -19454,6 +19461,7 @@
./usr/share/man/man3/noqiflush.3 comp-c-man .man
./usr/share/man/man3/noraw.3 comp-c-man .man
./usr/share/man/man3/notimeout.3 comp-c-man .man
./usr/share/man/man3/npf.3 comp-npf-man .man
./usr/share/man/man3/nrand48.3 comp-c-man .man
./usr/share/man/man3/ns.3 comp-obsolete obsolete
./usr/share/man/man3/ns_addr.3 comp-obsolete obsolete

View File

@ -1,4 +1,4 @@
# $NetBSD: shl.mi,v 1.154 2011/01/24 10:15:39 skrll Exp $
# $NetBSD: shl.mi,v 1.155 2011/02/02 02:20:27 rmind Exp $
#
# Note: don't delete entries from here - mark them as "obsolete" instead.
#
@ -73,6 +73,7 @@
./usr/lib/libmenu_pic.a comp-c-piclib
./usr/lib/libmj_pic.a comp-c-piclib
./usr/lib/libnetpgp_pic.a comp-c-piclib crypto
./usr/lib/libnpf_pic.a comp-npf-piclib npf
./usr/lib/libnvpair_pic.a comp-zfs-piclib zfs
./usr/lib/libobjc_pic.a comp-objc-piclib
./usr/lib/libopcodes.so.4 comp-c-shlib binutils

View File

@ -1,4 +1,4 @@
# $NetBSD: mi,v 1.218 2011/01/13 10:55:19 kefren Exp $
# $NetBSD: mi,v 1.219 2011/02/02 02:20:28 rmind Exp $
#
# Note: end-user configuration files that are moved to another location
# should not be marked "obsolete"; they should just be removed from
@ -236,6 +236,7 @@
./etc/rc.d/newsyslog etc-sys-rc
./etc/rc.d/nfsd etc-nfsserver-rc
./etc/rc.d/nfslocking etc-nfsserver-rc
./etc/rc.d/npf etc-npf-rc
./etc/rc.d/ntpd etc-ntp-rc
./etc/rc.d/ntpdate etc-ntp-rc
./etc/rc.d/perusertmp etc-sys-rc

View File

@ -1,4 +1,4 @@
# $NetBSD: rc.conf,v 1.110 2011/01/13 10:55:20 kefren Exp $
# $NetBSD: rc.conf,v 1.111 2011/02/02 02:20:28 rmind Exp $
#
# /etc/defaults/rc.conf --
# default configuration of /etc/rc.conf
@ -161,6 +161,7 @@ securelevel="" # securelevel to set to
# Networking startup.
#
mdnsd=NO
npf=NO
ipfilter=NO ipfilter_flags="" # uses /etc/ipf.conf
ipnat=NO # uses /etc/ipnat.conf
ipfs=NO ipfs_flags="" # save/load ipnat and ipf states

View File

@ -1,4 +1,4 @@
# $NetBSD: special,v 1.134 2010/12/17 09:54:28 jruoho Exp $
# $NetBSD: special,v 1.135 2011/02/02 02:20:28 rmind Exp $
# @(#)special 8.2 (Berkeley) 1/23/94
#
# This file may be overwritten on upgrades.
@ -240,6 +240,7 @@
./etc/rc.d/newsyslog type=file mode=0555
./etc/rc.d/nfsd type=file mode=0555
./etc/rc.d/nfslocking type=file mode=0555
./etc/rc.d/npf type=file mode=0555
./etc/rc.d/ntpd type=file mode=0555
./etc/rc.d/ntpdate type=file mode=0555
./etc/rc.d/perusertmp type=file mode=0555

View File

@ -1,4 +1,4 @@
# $NetBSD: Makefile,v 1.81 2011/01/13 10:55:20 kefren Exp $
# $NetBSD: Makefile,v 1.82 2011/02/02 02:20:28 rmind Exp $
.include <bsd.own.mk>
@ -28,7 +28,7 @@ CONFIGFILES=\
ldconfig ldpd local lpd lvm \
mdnsd mixerctl mopd motd mountall mountcritlocal \
mountcritremote mountd moused mrouted \
named ndbootd network newsyslog nfsd nfslocking ntpd ntpdate \
named ndbootd network newsyslog nfsd nfslocking npf ntpd ntpdate \
perusertmp pf pf_boot pflogd postfix powerd ppp pwcheck \
quota \
racoon rpcbind raidframe raidframeparity rarpd rbootd rndctl \

61
etc/rc.d/npf Normal file
View File

@ -0,0 +1,61 @@
#!/bin/sh
#
# $NetBSD: npf,v 1.1 2011/02/02 02:20:28 rmind Exp $
#
# Public Domain.
#
# PROVIDE: npf
# REQUIRE: root bootconf mountcritlocal tty network
# BEFORE: NETWORKING
$_rc_subr_loaded . /etc/rc.subr
name="npf"
rcvar=$name
config="/etc/npf.conf"
start_cmd="npf_start"
stop_cmd="npf_stop"
reload_cmd="npf_reload"
status_cmd="npf_status"
extra_commands="reload status"
npf_cfg_check()
{
if [ ! -f ${config} ]; then
warn "${config} is not readable; failed."
exit 1
fi
}
npf_start()
{
echo "Enabling NPF."
npf_cfg_check
/usr/sbin/npfctl reload
/usr/sbin/npfctl start
}
npf_stop()
{
echo "Disabling NPF."
/usr/sbin/npfctl stop
/usr/sbin/npfctl flush
}
npf_reload()
{
echo "Reloading NPF ruleset."
npf_cfg_check
/usr/sbin/npfctl reload
}
npf_status()
{
}
load_rc_config $name
run_rc_command "$1"

View File

@ -1,4 +1,4 @@
# $NetBSD: Makefile,v 1.160 2011/01/18 20:09:37 pooka Exp $
# $NetBSD: Makefile,v 1.161 2011/02/02 02:20:24 rmind Exp $
# from: @(#)Makefile 5.25.1.1 (Berkeley) 5/7/91
.include <bsd.own.mk>
@ -88,6 +88,10 @@ SUBDIR+= libedit # depends on libterminfo
SUBDIR+= librefuse # depends on libpuffs
SUBDIR+= librumpuser # depends on libpthread
.if (${MKNPF} != "no")
SUBDIR+= libnpf # depends on libprop
.endif
.if (${MKCRYPTO} != "no")
SUBDIR+= ../crypto/external/bsd/openssl/lib # depends on libcrypt
.endif

20
lib/libnpf/Makefile Normal file
View File

@ -0,0 +1,20 @@
# $NetBSD: Makefile,v 1.1 2011/02/02 02:20:25 rmind Exp $
.include <bsd.own.mk>
LIB= npf
MAN= npf.3
SRCS= npf.c
INCS= npf.h
INCSDIR= /usr/include
LIBDPLIBS+= prop ${.CURDIR}/../libprop
LDADD+= -lprop
DPADD+= ${LIBPROP}
WARNS?= 4
NOLINT= # defined (note: deliberately)
.include <bsd.lib.mk>

290
lib/libnpf/npf.3 Normal file
View File

@ -0,0 +1,290 @@
.\" $NetBSD: npf.3,v 1.1 2011/02/02 02:20:25 rmind Exp $
.\"
.\" Copyright (c) 2011 The NetBSD Foundation, Inc.
.\" All rights reserved.
.\"
.\" This material is based upon work partially supported by The
.\" NetBSD Foundation under a contract with Mindaugas Rasiukevicius.
.\"
.\" Redistribution and use in source and binary forms, with or without
.\" modification, are permitted provided that the following conditions
.\" are met:
.\" 1. Redistributions of source code must retain the above copyright
.\" notice, this list of conditions and the following disclaimer.
.\" 2. Redistributions in binary form must reproduce the above copyright
.\" notice, this list of conditions and the following disclaimer in the
.\" documentation and/or other materials provided with the distribution.
.\"
.\" THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
.\" ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
.\" TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
.\" PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
.\" BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
.\" CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
.\" SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
.\" INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
.\" CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
.\" POSSIBILITY OF SUCH DAMAGE.
.\"
.Dd February 2, 2011
.Dt NPF 3
.Os
.Sh NAME
.Nm npf
.Nd NPF packet filter library
.Sh LIBRARY
.Lb libnpf
.Sh SYNOPSIS
.In npf.h
.\" ---
.Ft nl_config_t *
.Fn npf_config_create "void"
.Ft int
.Fn npf_config_submit "nl_config_t *ncf" "int fd"
.Ft void
.Fn npf_config_destroy "nl_config_t *ncf"
.\" ---
.Ft nl_rule_t *
.Fn npf_rule_create "char *name" "uint32_t attr" "u_int if_idx"
.Ft int
.Fn npf_rule_setcode "nl_rule_t *rl" "int type" "const void *code" "size_t sz"
.Ft bool
.Fn npf_rule_exists_p "nl_config_t *ncf" "const char *name"
.Ft int
.Fn npf_rule_insert "nl_config_t *ncf" " nl_rule_t *parent" \
"nl_rule_t *rl" "pri_t pri"
.Ft int
.Fn npf_rule_setproc "nl_config_t *ncf" "nl_rule_t *rl" "const char *name"
.Ft void
.Fn npf_rule_destroy "nl_rule_t *rl"
.\" ---
.Ft nl_rproc_t *
.Fn npf_rproc_create "char *name"
.Ft bool
.Fn npf_rproc_exists_p "nl_config_t *ncf" "const char *name"
.Ft int
.Fn npf_rproc_insert "nl_config_t *ncf" "nl_rproc_t *rp"
.\" ---
.Ft nl_nat_t *
.Fn npf_nat_create "int type" "int flags" "u_int if_idx" \
"npf_addr_t *addr" "int af" "in_port_t port"
.Ft int
.Fn npf_nat_insert "nl_config_t *ncf" "nl_nat_t *nt" "pri_t pri"
.\" ---
.Ft nl_table_t *
.Fn npf_table_create "int index" "int type"
.Ft int
.Fn npf_table_add_entry "nl_table_t *tl" "in_addr_t addr" "in_addr_t mask"
.Fa bool
.Fn npf_table_exists_p "nl_config_t *ncf" "u_int tid"
.Ft int
.Fn npf_table_insert "nl_config_t *ncf" "nl_table_t *tl"
.Ft void
.Fn npf_table_destroy "nl_table_t *tl"
.\" ---
.Ft int
.Fn npf_update_rule "int fd" "char *rname" "nl_rule_t *rl"
.Ft int
.Fn npf_sessions_send "int fd" "const char *fpath"
.Ft int
.Fn npf_sessions_recv "int fd" "const char *fpath"
.\" -----
.Sh DESCRIPTION
The
.Nm
library provides an interface to create an NPF configuration having rules,
tables, procedures, or translation policies.
The configuration can be submitted to the kernel.
.\" -----
.Sh CONFIGURATION
.Bl -tag -width 4n
.It Fn npf_config_create
Create a configuration.
.It Fn npf_config_submit
Submit configuration to the kernel.
.It Fn npf_config_destroy
Destroy the configuration.
.El
.\" ---
.Sh RULE INTERFACE
.Bl -tag -width 4n
.It Fn npf_rule_create
Create a rule with a given name, attribute and priorty. Name can be NULL,
in which case rule has no unique identifier. Otherwise, rules shall not
have duplicate names. The following attributes, which can be ORed, are
available:
.Bl -tag -width indent
.It Dv NPF_RULE_PASS
Decision of this rule is "pass". If this attribute is not
specified, then packet "block" (drop) is the default.
.It Dv NPF_RULE_DEFAULT
This a default rule in the ruleset. There can only be a
single rule having this attribute set in the ruleset.
.It Dv NPF_RULE_FINAL
Indicates that on rule match, further processing of the
ruleset should be stopped and this rule applied instantly.
.It Dv NPF_RULE_KEEPSTATE
Create a state (session) on match, track the connection and
therefore pass the backwards stream without inspection.
.It Dv NPF_RULE_RETRST
Return TCP RST packet in a case of packet block.
.It Dv NPF_RULE_RETICMP
Return ICMP destination unreachable in a case of packet block.
.It Dv NPF_RULE_IN
Rule may match only if incoming packet.
.It Dv NPF_RULE_OUT
Rule may match only if outgoing packet.
.El
.Pp
Interface is specified by
.Fa if_idx ,
which is a numeral representation of an
interface, given by
.Xr if_nametoindex 3 .
Zero indicates any interface.
.\" ---
.It Fn npf_rule_setcode
Assign compiled code for the rule specified by
.Fa rl ,
used for filter criteria.
Pointer to the binary code is specified by
.Fa code ,
and size of the memory area by
.Fa sz .
Type of the code is specified by
.Fa type .
Currently, only n-code is supported and
.Dv NPF_CODE_NCODE
should be passed.
.\" ---
.It Fn npf_rule_insert
Insert the rule into the set of parent rule specified by
.Fa parent .
If value of
.Fa parent
is NULL,
then insert into the main ruleset.
.Pp
Priority is the order of the rule in the ruleset. Lower value means first
to process, higher value - last to process. If multiple rules have the same
priority - order is unspecified. A special constant
.Dv NPF_PRI_NEXT
may be passed to use the value of last used priority incremented by 1.
.It npf_rule_setproc
Set procedure for the specified rule.
.It Fn npf_rule_destroy
Destroy the given rule.
.El
.\" -----
.Sh RULE PROCEDURE INTERFACE
.Bl -tag -width 4n
.It Fn npf_rproc_create
Create a rule procedure with a given
.Fa name .
Name must be unique for each procedure.
.It Fn npf_rproc_insert
Insert rule procedure into the specified configuration.
.El
.\" -----
.Sh TRANSLATION INTERFACE
.Bl -tag -width 4n
.It Fn npf_nat_create
Create a NAT translation policy of a specified type.
There are two types:
.Bl -tag -width indent
.It Dv NPF_NATIN
Inbound NAT policy.
.It Dv NPF_NATOUT
Outbound NAT policy.
.El
.Pp
A bi-directional NAT is obtained by combining two policies.
The following flags are supported:
.Bl -tag -width indent
.It Dv NPF_NAT_PORTS
Indicates to perform port translation.
Otherwise, port translation is not performed and
.Fa port
is ignored.
.It Dv NPF_NAT_PORTMAP
Effective only if
.Dv NPF_NAT_PORTS
flag is set.
Indicates to create a port map and select a random port for translation.
Otherwise, port is translated to the value specified by
.Fa port
is used.
.El
.Pp
Translation address is specified by
.Fa addr ,
and its family by
.Fa fa.
Family must be either
.Dv AF_INET
for IPv4 or
.Dv AF_INET6
for IPv6 address.
.It Fn npf_nat_insert
Insert NAT policy, its rule, into the specified configuration.
.El
.\" -----
.Sh TABLE INTERFACE
.Bl -tag -width 4n
.It Fn npf_table_create
Create NPF table of specified type.
The following types are supported:
.Bl -tag -width indent
.It Dv NPF_TABLE_HASH
Indicates to use hash table for storage.
.It Dv NPF_TABLE_RBTREE
Indicates to use red-black tree for storage.
Table is identified by
.Fa index ,
which should be in the range between 1 and
.Dv NPF_MAX_TABLE_ID .
.El
.It Fn npf_table_add_entry
Add an entry of IPv4 address and mask, specified by
.Fa addr
and
.Fa mask ,
to the table specified by
.Fa tl .
.It Fn npf_table_exists_p
Determine whether table with ID
.Fa tid
exists in the configuration
.Fa ncf .
Return
.Dv true
if exists, and
.Dv false
otherwise.
.It Fn npf_table_insert
Insert table into set of configuration.
Routine performs a check for duplicate table ID.
.It Fn npf_table_destroy
Destroy the specified table.
.El
.\" -----
.Sh TABLE INTERFACE
.Bl -tag -width 4n
.It Fn npf_update_rule
.It Fn npf_sessions_send
Read the file specified by
.Fa fpath ,
and send sessions saved in it to the kernel.
.It Fn npf_sessions_recv
Receive currently loaded session from the kernel, and save them to a file
specified by
.Fa fpath .
.El
.\" -----
.Sh SEE ALSO
.Xr npfctl 8 ,
.Xr npf_ncode 9
.Sh HISTORY
NPF library first appeared in
.Nx 6.0 .

544
lib/libnpf/npf.c Normal file
View File

@ -0,0 +1,544 @@
/* $NetBSD: npf.c,v 1.1 2011/02/02 02:20:25 rmind Exp $ */
/*-
* Copyright (c) 2010-2011 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This material is based upon work partially supported by The
* NetBSD Foundation under a contract with Mindaugas Rasiukevicius.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: npf.c,v 1.1 2011/02/02 02:20:25 rmind Exp $");
#include <sys/types.h>
#include <netinet/in_systm.h>
#include <netinet/in.h>
#include <prop/proplib.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <err.h>
#define _NPF_PRIVATE
#include "npf.h"
struct nl_config {
/* Rules, translations, tables, procedures. */
prop_array_t ncf_rules_list;
prop_array_t ncf_rproc_list;
prop_array_t ncf_table_list;
prop_array_t ncf_nat_list;
/* Priority counters. */
pri_t ncf_rule_pri;
pri_t ncf_nat_pri;
};
struct nl_rule {
prop_dictionary_t nrl_dict;
};
struct nl_rproc {
prop_dictionary_t nrp_dict;
};
struct nl_table {
prop_dictionary_t ntl_dict;
};
/*
* CONFIGURATION INTERFACE.
*/
nl_config_t *
npf_config_create(void)
{
nl_config_t *ncf;
ncf = malloc(sizeof(nl_config_t));
if (ncf == NULL) {
return NULL;
}
ncf->ncf_rules_list = prop_array_create();
ncf->ncf_rproc_list = prop_array_create();
ncf->ncf_table_list = prop_array_create();
ncf->ncf_nat_list = prop_array_create();
ncf->ncf_rule_pri = 1;
ncf->ncf_nat_pri = 1;
return ncf;
}
int
npf_config_submit(nl_config_t *ncf, int fd)
{
prop_dictionary_t npf_dict;
int error = 0;
npf_dict = prop_dictionary_create();
if (npf_dict == NULL) {
return ENOMEM;
}
prop_dictionary_set(npf_dict, "rules", ncf->ncf_rules_list);
prop_dictionary_set(npf_dict, "rprocs", ncf->ncf_rproc_list);
prop_dictionary_set(npf_dict, "tables", ncf->ncf_table_list);
prop_dictionary_set(npf_dict, "translation", ncf->ncf_nat_list);
#ifndef _NPF_TESTING
error = prop_dictionary_send_ioctl(npf_dict, fd, IOC_NPF_RELOAD);
#else
if (!prop_dictionary_externalize_to_file(npf_dict, "./npf.plist")) {
error = errno;
}
#endif
prop_object_release(npf_dict);
return error;
}
void
npf_config_destroy(nl_config_t *ncf)
{
prop_object_release(ncf->ncf_rules_list);
prop_object_release(ncf->ncf_rproc_list);
prop_object_release(ncf->ncf_table_list);
prop_object_release(ncf->ncf_nat_list);
free(ncf);
}
static bool
_npf_prop_array_lookup(prop_array_t array, const char *key, const char *name)
{
prop_dictionary_t dict;
prop_object_iterator_t it;
it = prop_array_iterator(array);
while ((dict = prop_object_iterator_next(it)) != NULL) {
const char *lname;
prop_dictionary_get_cstring_nocopy(dict, key, &lname);
if (strcmp(name, lname) == 0)
break;
}
prop_object_iterator_release(it);
return dict ? true : false;
}
/*
* RULE INTERFACE.
*/
nl_rule_t *
npf_rule_create(const char *name, uint32_t attr, u_int if_idx)
{
prop_dictionary_t rldict;
nl_rule_t *rl;
rl = malloc(sizeof(nl_rule_t));
if (rl == NULL) {
return NULL;
}
rldict = prop_dictionary_create();
if (rldict == NULL) {
free(rl);
return NULL;
}
if (name) {
prop_dictionary_set_cstring(rldict, "name", name);
}
prop_dictionary_set_uint32(rldict, "attributes", attr);
if (if_idx) {
prop_dictionary_set_uint32(rldict, "interface", if_idx);
}
rl->nrl_dict = rldict;
return rl;
}
int
npf_rule_setcode(nl_rule_t *rl, int type, const void *code, size_t sz)
{
prop_dictionary_t rldict = rl->nrl_dict;
prop_data_t cdata;
if (type != NPF_CODE_NCODE) {
return ENOTSUP;
}
cdata = prop_data_create_data(code, sz);
if (cdata == NULL) {
return ENOMEM;
}
prop_dictionary_set(rldict, "ncode", cdata);
prop_object_release(cdata);
return 0;
}
int
npf_rule_setproc(nl_config_t *ncf, nl_rule_t *rl, const char *name)
{
prop_dictionary_t rldict = rl->nrl_dict;
if (!npf_rproc_exists_p(ncf, name)) {
return ENOENT;
}
prop_dictionary_set_cstring(rldict, "rproc", name);
return 0;
}
bool
npf_rule_exists_p(nl_config_t *ncf, const char *name)
{
return _npf_prop_array_lookup(ncf->ncf_rules_list, "name", name);
}
int
npf_rule_insert(nl_config_t *ncf, nl_rule_t *parent, nl_rule_t *rl, pri_t pri)
{
prop_dictionary_t rldict = rl->nrl_dict;
prop_array_t rlset;
if (pri == NPF_PRI_NEXT) {
pri = ncf->ncf_rule_pri++;
} else if (ncf) {
ncf->ncf_rule_pri = pri + 1;
}
prop_dictionary_set_int32(rldict, "priority", pri);
if (parent) {
prop_dictionary_t pdict = parent->nrl_dict;
rlset = prop_dictionary_get(pdict, "subrules");
if (rlset == NULL) {
rlset = prop_array_create();
prop_dictionary_set(pdict, "subrules", rlset);
prop_object_release(rlset);
}
} else {
rlset = ncf->ncf_rules_list;
}
prop_array_add(rlset, rldict);
return 0;
}
void
npf_rule_destroy(nl_rule_t *rl)
{
prop_object_release(rl->nrl_dict);
free(rl);
}
/*
* RULE PROCEDURE INTERFACE.
*/
nl_rproc_t *
npf_rproc_create(const char *name)
{
prop_dictionary_t rpdict;
nl_rproc_t *nrp;
nrp = malloc(sizeof(nl_rproc_t));
if (nrp == NULL) {
return NULL;
}
rpdict = prop_dictionary_create();
if (rpdict == NULL) {
free(nrp);
return NULL;
}
prop_dictionary_set_cstring(rpdict, "name", name);
nrp->nrp_dict = rpdict;
return nrp;
}
bool
npf_rproc_exists_p(nl_config_t *ncf, const char *name)
{
return _npf_prop_array_lookup(ncf->ncf_rproc_list, "name", name);
}
int
_npf_rproc_setnorm(nl_rproc_t *rp, bool rnd, bool no_df, int minttl, int maxmss)
{
prop_dictionary_t rpdict = rp->nrp_dict;
uint32_t attr;
prop_dictionary_set_bool(rpdict, "randomize-id", rnd);
prop_dictionary_set_bool(rpdict, "no-df", no_df);
prop_dictionary_set_uint32(rpdict, "min-ttl", minttl);
prop_dictionary_set_uint32(rpdict, "max-mss", maxmss);
prop_dictionary_get_uint32(rpdict, "flags", &attr);
prop_dictionary_set_uint32(rpdict, "flags", attr | NPF_RPROC_NORMALIZE);
return 0;
}
int
_npf_rproc_setlog(nl_rproc_t *rp, u_int if_idx)
{
prop_dictionary_t rpdict = rp->nrp_dict;
uint32_t attr;
prop_dictionary_set_uint32(rpdict, "log-interface", if_idx);
prop_dictionary_get_uint32(rpdict, "flags", &attr);
prop_dictionary_set_uint32(rpdict, "flags", attr | NPF_RPROC_LOG);
return 0;
}
int
npf_rproc_insert(nl_config_t *ncf, nl_rproc_t *rp)
{
prop_dictionary_t rpdict = rp->nrp_dict;
const char *name;
if (!prop_dictionary_get_cstring_nocopy(rpdict, "name", &name)) {
return EINVAL;
}
if (npf_rproc_exists_p(ncf, name)) {
return EEXIST;
}
prop_array_add(ncf->ncf_rproc_list, rpdict);
return 0;
}
/*
* TRANSLATION INTERFACE.
*/
nl_nat_t *
npf_nat_create(int type, int flags, u_int if_idx,
npf_addr_t *addr, int af, in_port_t port)
{
nl_rule_t *rl;
prop_dictionary_t rldict;
prop_data_t addrdat;
uint32_t attr;
size_t sz;
if (af == AF_INET) {
sz = sizeof(struct in_addr);
} else if (af == AF_INET6) {
sz = sizeof(struct in6_addr);
} else {
return NULL;
}
attr = NPF_RULE_PASS | NPF_RULE_FINAL |
(type == NPF_NATOUT) ? NPF_RULE_OUT : NPF_RULE_IN;
/* Create a rule for NAT policy. Next, will add translation data. */
rl = npf_rule_create(NULL, attr, if_idx);
if (rl == NULL) {
return NULL;
}
rldict = rl->nrl_dict;
/* Translation type and flags. */
prop_dictionary_set_int32(rldict, "type", type);
prop_dictionary_set_uint32(rldict, "flags", flags);
/* Translation IP. */
addrdat = prop_data_create_data(addr, sz);
if (addrdat == NULL) {
npf_rule_destroy(rl);
return NULL;
}
prop_dictionary_set(rldict, "translation-ip", addrdat);
prop_object_release(addrdat);
/* Translation port (for redirect case). */
prop_dictionary_set_uint16(rldict, "translation-port", port);
return (nl_nat_t *)rl;
}
int
npf_nat_insert(nl_config_t *ncf, nl_nat_t *nt, pri_t pri)
{
prop_dictionary_t rldict = nt->nrl_dict;
if (pri == NPF_PRI_NEXT) {
pri = ncf->ncf_nat_pri++;
} else {
ncf->ncf_nat_pri = pri + 1;
}
prop_dictionary_set_int32(rldict, "priority", pri);
prop_array_add(ncf->ncf_nat_list, rldict);
return 0;
}
/*
* TABLE INTERFACE.
*/
nl_table_t *
npf_table_create(int id, int type)
{
prop_dictionary_t tldict;
prop_array_t tblents;
nl_table_t *tl;
tl = malloc(sizeof(nl_table_t));
if (tl == NULL) {
return NULL;
}
tldict = prop_dictionary_create();
if (tldict == NULL) {
free(tl);
return NULL;
}
prop_dictionary_set_uint32(tldict, "id", id);
prop_dictionary_set_int32(tldict, "type", type);
tblents = prop_array_create();
if (tblents == NULL) {
prop_object_release(tldict);
free(tl);
return NULL;
}
prop_dictionary_set(tldict, "entries", tblents);
prop_object_release(tblents);
tl->ntl_dict = tldict;
return tl;
}
int
npf_table_add_entry(nl_table_t *tl, in_addr_t addr, in_addr_t mask)
{
prop_dictionary_t tldict = tl->ntl_dict, entdict;
prop_array_t tblents;
/* Create the table entry. */
entdict = prop_dictionary_create();
if (entdict) {
return ENOMEM;
}
prop_dictionary_set_uint32(entdict, "addr", addr);
prop_dictionary_set_uint32(entdict, "mask", mask);
/* Insert the entry. */
tblents = prop_dictionary_get(tldict, "entries");
prop_array_add(tblents, entdict);
prop_object_release(entdict);
return 0;
}
bool
npf_table_exists_p(nl_config_t *ncf, u_int tid)
{
prop_dictionary_t tldict;
prop_object_iterator_t it;
it = prop_array_iterator(ncf->ncf_table_list);
while ((tldict = prop_object_iterator_next(it)) != NULL) {
u_int i;
if (prop_dictionary_get_uint32(tldict, "id", &i) && tid == i)
break;
}
prop_object_iterator_release(it);
return tldict ? true : false;
}
int
npf_table_insert(nl_config_t *ncf, nl_table_t *tl)
{
prop_dictionary_t tldict = tl->ntl_dict;
u_int tid;
if (!prop_dictionary_get_uint32(tldict, "id", &tid)) {
return EINVAL;
}
if (npf_table_exists_p(ncf, tid)) {
return EEXIST;
}
prop_array_add(ncf->ncf_table_list, tldict);
return 0;
}
void
npf_table_destroy(nl_table_t *tl)
{
prop_object_release(tl->ntl_dict);
free(tl);
}
/*
* MISC.
*/
int
npf_update_rule(int fd, char *rname, nl_rule_t *rl)
{
prop_dictionary_t rldict = rl->nrl_dict;
int error;
error = prop_dictionary_send_ioctl(rldict, fd, IOC_NPF_UPDATE_RULE);
return error;
}
int
npf_sessions_recv(int fd, const char *fpath)
{
prop_dictionary_t sdict;
int error;
error = prop_dictionary_recv_ioctl(fd, IOC_NPF_SESSIONS_SAVE, &sdict);
if (error) {
return error;
}
if (!prop_dictionary_externalize_to_file(sdict, fpath)) {
error = errno;
}
prop_object_release(sdict);
return error;
}
int
npf_sessions_send(int fd, const char *fpath)
{
prop_dictionary_t sdict;
int error;
if (fpath) {
sdict = prop_dictionary_internalize_from_file(fpath);
if (sdict == NULL) {
return errno;
}
} else {
/* Empty: will flush the sessions. */
prop_array_t selist = prop_array_create();
sdict = prop_dictionary_create();
prop_dictionary_set(sdict, "session-list", selist);
prop_object_release(selist);
}
error = prop_dictionary_send_ioctl(sdict, fd, IOC_NPF_SESSIONS_LOAD);
prop_object_release(sdict);
return error;
}

98
lib/libnpf/npf.h Normal file
View File

@ -0,0 +1,98 @@
/* $NetBSD: npf.h,v 1.1 2011/02/02 02:20:25 rmind Exp $ */
/*-
* Copyright (c) 2011 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This material is based upon work partially supported by The
* NetBSD Foundation under a contract with Mindaugas Rasiukevicius.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _NPF_LIB_H_
#define _NPF_LIB_H_
#include <sys/types.h>
#include <net/npf.h>
#ifdef _NPF_TESTING
#include "testing.h"
#endif
__BEGIN_DECLS
struct nl_config;
struct nl_rule;
struct nl_rproc;
struct nl_table;
typedef struct nl_config nl_config_t;
typedef struct nl_rule nl_rule_t;
typedef struct nl_rproc nl_rproc_t;
typedef struct nl_table nl_table_t;
typedef struct nl_rule nl_nat_t;
#define NPF_CODE_NCODE 1
#define NPF_CODE_BPF 2
#define NPF_PRI_NEXT (-1)
#define NPF_MAX_TABLE_ID (16)
nl_config_t * npf_config_create(void);
int npf_config_submit(nl_config_t *, int);
void npf_config_destroy(nl_config_t *);
nl_rule_t * npf_rule_create(const char *, uint32_t, u_int);
int npf_rule_setcode(nl_rule_t *, int, const void *, size_t);
int npf_rule_setproc(nl_config_t *, nl_rule_t *, const char *);
bool npf_rule_exists_p(nl_config_t *, const char *);
int npf_rule_insert(nl_config_t *, nl_rule_t *, nl_rule_t *, pri_t);
void npf_rule_destroy(nl_rule_t *);
nl_rproc_t * npf_rproc_create(const char *);
bool npf_rproc_exists_p(nl_config_t *, const char *);
int npf_rproc_insert(nl_config_t *, nl_rproc_t *);
#ifdef _NPF_PRIVATE
int _npf_rproc_setnorm(nl_rproc_t *, bool, bool, int, int);
int _npf_rproc_setlog(nl_rproc_t *, u_int);
#endif
nl_nat_t * npf_nat_create(int, int, u_int, npf_addr_t *, int, in_port_t);
int npf_nat_insert(nl_config_t *, nl_nat_t *, pri_t);
nl_table_t * npf_table_create(int, int);
int npf_table_add_entry(nl_table_t *, in_addr_t, in_addr_t);
bool npf_table_exists_p(nl_config_t *, u_int);
int npf_table_insert(nl_config_t *, nl_table_t *);
void npf_table_destroy(nl_table_t *);
int npf_update_rule(int, char *, nl_rule_t *);
int npf_sessions_send(int, const char *);
int npf_sessions_recv(int, const char *);
__END_DECLS
#endif /* _NPF_LIB_H_ */

5
lib/libnpf/shlib_version Normal file
View File

@ -0,0 +1,5 @@
# $NetBSD: shlib_version,v 1.1 2011/02/02 02:20:25 rmind Exp $
# Remember to update distrib/sets/lists/base/shl.* when changing
#
major=0
minor=0

View File

@ -1,4 +1,4 @@
/* $NetBSD: npf.c,v 1.3 2011/01/18 20:33:45 rmind Exp $ */
/* $NetBSD: npf.c,v 1.4 2011/02/02 02:20:25 rmind Exp $ */
/*-
* Copyright (c) 2009-2010 The NetBSD Foundation, Inc.
@ -34,7 +34,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: npf.c,v 1.3 2011/01/18 20:33:45 rmind Exp $");
__KERNEL_RCSID(0, "$NetBSD: npf.c,v 1.4 2011/02/02 02:20:25 rmind Exp $");
#include <sys/param.h>
#include <sys/types.h>
@ -221,6 +221,9 @@ npf_dev_ioctl(dev_t dev, u_long cmd, void *data, int flag, lwp_t *l)
case IOC_NPF_SESSIONS_LOAD:
error = npfctl_sessions_load(cmd, data);
break;
case IOC_NPF_UPDATE_RULE:
error = npfctl_update_rule(cmd, data);
break;
default:
error = ENOTTY;
break;

View File

@ -1,4 +1,4 @@
/* $NetBSD: npf.h,v 1.6 2011/01/18 20:33:45 rmind Exp $ */
/* $NetBSD: npf.h,v 1.7 2011/02/02 02:20:25 rmind Exp $ */
/*-
* Copyright (c) 2009-2011 The NetBSD Foundation, Inc.
@ -33,8 +33,8 @@
* Public NPF interfaces.
*/
#ifndef _NPF_H_
#define _NPF_H_
#ifndef _NPF_NET_H_
#define _NPF_NET_H_
#include <sys/param.h>
#include <sys/types.h>
@ -42,6 +42,9 @@
#include <sys/ioctl.h>
#include <prop/proplib.h>
#include <netinet/in_systm.h>
#include <netinet/in.h>
#ifdef _NPF_TESTING
#include "testing.h"
#endif
@ -49,43 +52,32 @@
#define NPF_VERSION 1
/*
* Public declarations.
* Public declarations and definitions.
*/
struct npf_ruleset;
struct npf_rule;
struct npf_hook;
typedef struct npf_rproc npf_rproc_t;
typedef struct npf_ruleset npf_ruleset_t;
typedef struct npf_rule npf_rule_t;
typedef struct npf_hook npf_hook_t;
/*
* Public definitions.
*/
typedef void nbuf_t;
/* Storage of address (both for IPv4 and IPv6). */
typedef struct in6_addr npf_addr_t;
#if defined(_KERNEL) || defined(_NPF_TESTING)
#include <netinet/in_systm.h>
#include <netinet/in.h>
/* Network buffer. */
typedef void nbuf_t;
struct npf_rproc;
struct npf_hook;
typedef struct npf_rproc npf_rproc_t;
typedef struct npf_hook npf_hook_t;
/*
* Packet information cache.
*/
#include <netinet/ip.h>
#include <netinet/ip6.h>
#include <netinet/tcp.h>
#include <netinet/udp.h>
#include <netinet/ip_icmp.h>
/*
* Storage of address, both IPv4 and IPv6.
*/
typedef struct in6_addr npf_addr_t;
/*
* Packet information cache.
*/
#define NPC_IP4 0x01 /* Indicates fetched IPv4 header. */
#define NPC_IP6 0x02 /* Indicates IPv6 header. */
#define NPC_IPFRAG 0x04 /* IPv4 fragment. */
@ -146,15 +138,11 @@ int nbuf_store_datum(nbuf_t *, void *, size_t, void *);
int nbuf_add_tag(nbuf_t *, uint32_t, uint32_t);
int nbuf_find_tag(nbuf_t *, uint32_t, void **);
/* Ruleset interface. */
npf_rule_t * npf_rule_alloc(prop_dictionary_t, npf_rproc_t *, void *, size_t);
void npf_rule_free(npf_rule_t *);
void npf_activate_rule(npf_rule_t *);
void npf_deactivate_rule(npf_rule_t *);
#if 0
npf_hook_t * npf_hook_register(npf_rule_t *,
void (*)(npf_cache_t *, nbuf_t *, void *), void *);
void npf_hook_unregister(npf_rule_t *, npf_hook_t *);
#endif
#endif /* _KERNEL */
@ -250,5 +238,6 @@ typedef enum {
#define IOC_NPF_STATS _IOW('N', 104, void *)
#define IOC_NPF_SESSIONS_SAVE _IOR('N', 105, struct plistref)
#define IOC_NPF_SESSIONS_LOAD _IOW('N', 106, struct plistref)
#define IOC_NPF_UPDATE_RULE _IOW('N', 107, struct plistref)
#endif /* _NPF_H_ */
#endif /* _NPF_NET_H_ */

View File

@ -1,4 +1,4 @@
/* $NetBSD: npf_ctl.c,v 1.5 2011/01/18 20:33:45 rmind Exp $ */
/* $NetBSD: npf_ctl.c,v 1.6 2011/02/02 02:20:25 rmind Exp $ */
/*-
* Copyright (c) 2009-2011 The NetBSD Foundation, Inc.
@ -37,7 +37,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: npf_ctl.c,v 1.5 2011/01/18 20:33:45 rmind Exp $");
__KERNEL_RCSID(0, "$NetBSD: npf_ctl.c,v 1.6 2011/02/02 02:20:25 rmind Exp $");
#include <sys/param.h>
#include <sys/conf.h>
@ -68,12 +68,11 @@ npfctl_switch(void *data)
return error;
}
static int
static int __noinline
npf_mk_tables(npf_tableset_t *tblset, prop_array_t tables)
{
prop_object_iterator_t it;
prop_dictionary_t tbldict;
prop_object_t obj;
int error = 0;
/* Tables - array. */
@ -96,10 +95,9 @@ npf_mk_tables(npf_tableset_t *tblset, prop_array_t tables)
}
/* Table ID and type. */
obj = prop_dictionary_get(tbldict, "id");
tid = (u_int)prop_number_integer_value(obj);
obj = prop_dictionary_get(tbldict, "type");
type = (int)prop_number_integer_value(obj);
prop_dictionary_get_uint32(tbldict, "id", &tid);
prop_dictionary_get_int32(tbldict, "type", &type);
/* Validate them. */
error = npf_table_check(tblset, tid, type);
if (error)
@ -124,13 +122,9 @@ npf_mk_tables(npf_tableset_t *tblset, prop_array_t tables)
while ((ent = prop_object_iterator_next(eit)) != NULL) {
in_addr_t addr, mask; /* XXX: IPv6 */
/* Address. */
obj = prop_dictionary_get(ent, "addr");
addr = (in_addr_t)prop_number_integer_value(obj);
/* Mask. */
obj = prop_dictionary_get(ent, "mask");
mask = (in_addr_t)prop_number_integer_value(obj);
/* Add a table entry. */
/* Get address and mask. Add a table entry. */
prop_dictionary_get_uint32(ent, "addr", &addr);
prop_dictionary_get_uint32(ent, "mask", &mask);
error = npf_table_add_v4cidr(tblset, tid, addr, mask);
if (error)
break;
@ -147,41 +141,36 @@ npf_mk_tables(npf_tableset_t *tblset, prop_array_t tables)
}
static npf_rproc_t *
npf_mk_rproc(prop_array_t rprocs, uint64_t rproc_id)
npf_mk_rproc(prop_array_t rprocs, const char *rpname)
{
prop_object_iterator_t it;
prop_dictionary_t rpdict;
prop_object_t obj;
npf_rproc_t *rp;
uint64_t id;
it = prop_array_iterator(rprocs);
while ((rpdict = prop_object_iterator_next(it)) != NULL) {
obj = prop_dictionary_get(rpdict, "id");
id = prop_number_unsigned_integer_value(obj);
if (id == rproc_id)
const char *iname;
prop_dictionary_get_cstring_nocopy(rpdict, "name", &iname);
if (strcmp(rpname, iname) == 0)
break;
}
prop_object_iterator_release(it);
if (rpdict == NULL) {
return NULL;
}
CTASSERT(sizeof(uintptr_t) <= sizeof(uint64_t));
obj = prop_dictionary_get(rpdict, "rproc-ptr");
if (obj == NULL) {
if (!prop_dictionary_get_uint64(rpdict, "rproc-ptr", (uint64_t *)&rp)) {
rp = npf_rproc_create(rpdict);
prop_dictionary_set(rpdict, "rproc-ptr",
prop_number_create_unsigned_integer((uintptr_t)rp));
} else {
rp = (void *)(uintptr_t)prop_number_unsigned_integer_value(obj);
prop_dictionary_set_uint64(rpdict, "rproc-ptr",
(uint64_t)(uintptr_t)rp);
}
return rp;
}
static int
npf_mk_singlerule(prop_dictionary_t rldict, npf_ruleset_t *rlset,
prop_array_t rprocs, npf_rule_t **parent)
static int __noinline
npf_mk_singlerule(prop_dictionary_t rldict, prop_array_t rps, npf_rule_t **rl)
{
npf_rule_t *rl;
const char *rnm;
npf_rproc_t *rp;
prop_object_t obj;
size_t nc_size;
@ -223,10 +212,8 @@ npf_mk_singlerule(prop_dictionary_t rldict, npf_ruleset_t *rlset,
}
/* Check for rule procedure. */
obj = prop_dictionary_get(rldict, "rproc-id");
if (obj && rprocs) {
uint64_t rproc_id = prop_number_unsigned_integer_value(obj);
rp = npf_mk_rproc(rprocs, rproc_id);
if (rps && prop_dictionary_get_cstring_nocopy(rldict, "rproc", &rnm)) {
rp = npf_mk_rproc(rps, rnm);
if (rp == NULL) {
if (nc) {
npf_ncode_free(nc, nc_size); /* XXX */
@ -237,16 +224,35 @@ npf_mk_singlerule(prop_dictionary_t rldict, npf_ruleset_t *rlset,
rp = NULL;
}
/* Allocate and setup NPF rule. */
rl = npf_rule_alloc(rldict, rp, nc, nc_size);
npf_ruleset_insert(rlset, rl);
if (parent) {
*parent = rl;
}
/* Finally, allocate and return the rule. */
*rl = npf_rule_alloc(rldict, rp, nc, nc_size);
return 0;
}
static int
static int __noinline
npf_mk_subrules(npf_ruleset_t *rlset, prop_array_t rules, prop_array_t rprocs)
{
prop_object_iterator_t it;
prop_dictionary_t rldict;
int error = 0;
if (prop_object_type(rules) != PROP_TYPE_ARRAY) {
return EINVAL;
}
it = prop_array_iterator(rules);
while ((rldict = prop_object_iterator_next(it)) != NULL) {
npf_rule_t *rl;
error = npf_mk_singlerule(rldict, rprocs, &rl);
if (error) {
break;
}
npf_ruleset_insert(rlset, rl);
}
prop_object_iterator_release(it);
return error;
}
static int __noinline
npf_mk_rules(npf_ruleset_t *rlset, prop_array_t rules, prop_array_t rprocs)
{
prop_object_iterator_t it;
@ -260,44 +266,35 @@ npf_mk_rules(npf_ruleset_t *rlset, prop_array_t rules, prop_array_t rprocs)
it = prop_array_iterator(rprocs);
while ((rpdict = prop_object_iterator_next(it)) != NULL) {
if (prop_dictionary_get(rpdict, "rproc-ptr"))
if (prop_dictionary_get(rpdict, "rproc-ptr")) {
prop_object_iterator_release(it);
return EINVAL;
}
}
prop_object_iterator_release(it);
error = 0;
it = prop_array_iterator(rules);
while ((rldict = prop_object_iterator_next(it)) != NULL) {
prop_object_iterator_t sit;
prop_array_t subrules;
prop_dictionary_t srldict;
npf_rule_t *myrl;
npf_ruleset_t *rlsetsub;
npf_rule_t *rl;
/* Generate a single rule. */
error = npf_mk_singlerule(rldict, rlset, rprocs, &myrl);
if (error)
error = npf_mk_singlerule(rldict, rprocs, &rl);
if (error) {
break;
}
npf_ruleset_insert(rlset, rl);
/* Check for subrules. */
/* Check for sub-rules and generate, if any. */
subrules = prop_dictionary_get(rldict, "subrules");
if (subrules == NULL) {
/* No subrules, next.. */
continue;
}
/* Generate subrules, if any. */
if (prop_object_type(subrules) != PROP_TYPE_ARRAY) {
error = EINVAL;
break;
}
sit = prop_array_iterator(subrules);
while ((srldict = prop_object_iterator_next(sit)) != NULL) {
/* For subrule, pass ruleset pointer of parent. */
error = npf_mk_singlerule(srldict,
npf_rule_subset(myrl), rprocs, NULL);
if (error)
break;
}
prop_object_iterator_release(sit);
rlsetsub = npf_rule_subset(rl);
error = npf_mk_subrules(rlsetsub, subrules, rprocs);
if (error)
break;
}
@ -308,7 +305,7 @@ npf_mk_rules(npf_ruleset_t *rlset, prop_array_t rules, prop_array_t rprocs)
return error;
}
static int
static int __noinline
npf_mk_natlist(npf_ruleset_t *nset, prop_array_t natlist)
{
prop_object_iterator_t it;
@ -335,9 +332,17 @@ npf_mk_natlist(npf_ruleset_t *nset, prop_array_t natlist)
* NAT policies are standard rules, plus additional
* information for translation. Make a rule.
*/
error = npf_mk_singlerule(natdict, nset, NULL, &rl);
if (error)
error = npf_mk_singlerule(natdict, NULL, &rl);
if (error) {
break;
}
npf_ruleset_insert(nset, rl);
/* If rule is named, it is a group with NAT policies. */
if (prop_dictionary_get(natdict, "name") &&
prop_dictionary_get(natdict, "subrules")) {
continue;
}
/* Allocate a new NAT policy and assign to the rule. */
np = npf_nat_newpolicy(natdict, nset);
@ -414,7 +419,6 @@ npfctl_reload(u_long cmd, void *data)
rlset = NULL;
nset = NULL;
fail:
prop_object_release(dict);
/*
* Note: destroy rulesets first, to drop references to the tableset.
*/
@ -428,6 +432,53 @@ fail:
if (tblset) {
npf_tableset_destroy(tblset);
}
prop_object_release(dict);
return error;
}
/*
* npfctl_update_rule: reload a specific rule identified by the name.
*/
int
npfctl_update_rule(u_long cmd, void *data)
{
const struct plistref *pref = data;
prop_dictionary_t dict;
prop_array_t subrules;
prop_object_t obj;
npf_ruleset_t *rlset;
const char *name;
int error;
#ifdef _KERNEL
/* Retrieve and construct the rule. */
error = prop_dictionary_copyin_ioctl(pref, cmd, &dict);
if (error) {
return error;
}
#else
dict = prop_dictionary_internalize_from_file(data);
if (dict == NULL)
return EINVAL;
#endif
/* Create the ruleset and construct sub-rules. */
rlset = npf_ruleset_create();
subrules = prop_dictionary_get(dict, "subrules");
error = npf_mk_subrules(rlset, subrules, NULL);
if (error) {
goto out;
}
/* Lookup the rule by name, and replace its subset (sub-rules). */
obj = prop_dictionary_get(dict, "name");
name = prop_string_cstring_nocopy(obj);
if (npf_ruleset_replace(name, rlset) == NULL) {
/* Not found. */
error = ENOENT;
out: /* Error path. */
npf_ruleset_destroy(rlset);
}
prop_object_release(dict);
return error;
}
@ -546,6 +597,7 @@ npfctl_table(void *data)
npf_ioctl_table_t *nct = data;
int error;
npf_core_enter(); /* XXXSMP */
switch (nct->nct_action) {
case NPF_IOCTL_TBLENT_ADD:
error = npf_table_add_v4cidr(NULL, nct->nct_tid,
@ -562,5 +614,6 @@ npfctl_table(void *data)
error = EINVAL;
}
}
npf_core_exit(); /* XXXSMP */
return error;
}

View File

@ -1,4 +1,4 @@
/* $NetBSD: npf_handler.c,v 1.6 2011/01/18 20:33:45 rmind Exp $ */
/* $NetBSD: npf_handler.c,v 1.7 2011/02/02 02:20:25 rmind Exp $ */
/*-
* Copyright (c) 2009-2010 The NetBSD Foundation, Inc.
@ -34,7 +34,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: npf_handler.c,v 1.6 2011/01/18 20:33:45 rmind Exp $");
__KERNEL_RCSID(0, "$NetBSD: npf_handler.c,v 1.7 2011/02/02 02:20:25 rmind Exp $");
#include <sys/param.h>
#include <sys/systm.h>
@ -83,6 +83,7 @@ npf_packet_handler(void *arg, struct mbuf **mp, ifnet_t *ifp, int di)
nbuf_t *nbuf = *mp;
npf_cache_t npc;
npf_session_t *se;
npf_ruleset_t *rlset;
npf_rule_t *rl;
npf_rproc_t *rp;
int retfl, error;
@ -125,8 +126,10 @@ npf_packet_handler(void *arg, struct mbuf **mp, ifnet_t *ifp, int di)
goto pass;
}
/* Inspect the ruleset using this packet, acquire the lock. */
rl = npf_ruleset_inspect(&npc, nbuf, ifp, di, NPF_LAYER_3);
/* Acquire the lock, inspect the ruleset using this packet. */
npf_core_enter();
rlset = npf_core_ruleset();
rl = npf_ruleset_inspect(&npc, nbuf, rlset, ifp, di, NPF_LAYER_3);
if (rl == NULL) {
if (default_pass) {
npf_stats_inc(NPF_STAT_PASS_DEFAULT);
@ -169,7 +172,7 @@ block:
* Perform rule procedure, if any.
*/
if (rp) {
npf_rproc_run(&npc, nbuf, rp);
npf_rproc_run(&npc, nbuf, rp, error);
}
out:
/* Release the reference on session, or rule procedure. */

View File

@ -1,4 +1,4 @@
/* $NetBSD: npf_impl.h,v 1.6 2011/01/18 20:33:45 rmind Exp $ */
/* $NetBSD: npf_impl.h,v 1.7 2011/02/02 02:20:25 rmind Exp $ */
/*-
* Copyright (c) 2009-2011 The NetBSD Foundation, Inc.
@ -37,6 +37,10 @@
#ifndef _NPF_IMPL_H_
#define _NPF_IMPL_H_
#if !defined(_KERNEL) && !defined(_NPF_TESTING)
#error "Kernel-level header only"
#endif
#include <sys/types.h>
#include <sys/queue.h>
#include <sys/hash.h>
@ -59,14 +63,15 @@
/*
* STRUCTURE DECLARATIONS.
*
* Note: ruleset interface declarations are public.
*/
struct npf_ruleset;
struct npf_rule;
struct npf_nat;
struct npf_rproc;
struct npf_session;
typedef struct npf_ruleset npf_ruleset_t;
typedef struct npf_rule npf_rule_t;
typedef struct npf_nat npf_nat_t;
typedef struct npf_alg npf_alg_t;
typedef struct npf_natpolicy npf_natpolicy_t;
@ -127,6 +132,7 @@ int npfctl_switch(void *);
int npfctl_reload(u_long, void *);
int npfctl_sessions_save(u_long, void *);
int npfctl_sessions_load(u_long, void *);
int npfctl_update_rule(u_long, void *);
int npfctl_table(void *);
void npf_stats_inc(npf_stats_t);
@ -204,13 +210,15 @@ void npf_ruleset_insert(npf_ruleset_t *, npf_rule_t *);
void npf_ruleset_natreload(npf_ruleset_t *, npf_ruleset_t *);
npf_rule_t * npf_ruleset_matchnat(npf_ruleset_t *, npf_natpolicy_t *);
npf_rule_t * npf_ruleset_sharepm(npf_ruleset_t *, npf_natpolicy_t *);
npf_rule_t * npf_ruleset_replace(const char *, npf_ruleset_t *);
npf_rule_t * npf_ruleset_match(npf_ruleset_t *, npf_cache_t *, nbuf_t *,
ifnet_t *, const int, const int);
npf_rule_t * npf_ruleset_inspect(npf_cache_t *, nbuf_t *,
npf_rule_t * npf_ruleset_inspect(npf_cache_t *, nbuf_t *, npf_ruleset_t *,
ifnet_t *, const int, const int);
int npf_rule_apply(npf_cache_t *, nbuf_t *, npf_rule_t *, int *);
/* Rule interface. */
npf_rule_t * npf_rule_alloc(prop_dictionary_t, npf_rproc_t *, void *, size_t);
void npf_rule_free(npf_rule_t *);
npf_ruleset_t * npf_rule_subset(npf_rule_t *);
npf_natpolicy_t *npf_rule_getnat(const npf_rule_t *);
void npf_rule_setnat(npf_rule_t *, npf_natpolicy_t *);
@ -218,7 +226,7 @@ void npf_rule_setnat(npf_rule_t *, npf_natpolicy_t *);
npf_rproc_t * npf_rproc_create(prop_dictionary_t);
npf_rproc_t * npf_rproc_return(npf_rule_t *);
void npf_rproc_release(npf_rproc_t *);
void npf_rproc_run(npf_cache_t *, nbuf_t *, npf_rproc_t *);
void npf_rproc_run(npf_cache_t *, nbuf_t *, npf_rproc_t *, int);
/* Session handling interface. */
void npf_session_sysinit(void);
@ -282,4 +290,4 @@ void npf_sessions_dump(void);
void npf_state_dump(npf_state_t *);
void npf_nat_dump(npf_nat_t *);
#endif
#endif /* _NPF_IMPL_H_ */

View File

@ -1,4 +1,4 @@
/* $NetBSD: npf_nat.c,v 1.5 2011/01/18 20:33:46 rmind Exp $ */
/* $NetBSD: npf_nat.c,v 1.6 2011/02/02 02:20:25 rmind Exp $ */
/*-
* Copyright (c) 2010-2011 The NetBSD Foundation, Inc.
@ -76,7 +76,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: npf_nat.c,v 1.5 2011/01/18 20:33:46 rmind Exp $");
__KERNEL_RCSID(0, "$NetBSD: npf_nat.c,v 1.6 2011/02/02 02:20:25 rmind Exp $");
#include <sys/param.h>
#include <sys/kernel.h>
@ -117,7 +117,7 @@ struct npf_natpolicy {
kcondvar_t n_cv;
npf_portmap_t * n_portmap;
int n_type;
int n_flags;
u_int n_flags;
size_t n_addr_sz;
npf_addr_t n_taddr;
in_port_t n_tport;
@ -174,7 +174,6 @@ npf_nat_sysfini(void)
npf_natpolicy_t *
npf_nat_newpolicy(prop_dictionary_t natdict, npf_ruleset_t *nrlset)
{
const npf_addr_t *taddr;
npf_natpolicy_t *np;
prop_object_t obj;
npf_portmap_t *pm;
@ -184,26 +183,19 @@ npf_nat_newpolicy(prop_dictionary_t natdict, npf_ruleset_t *nrlset)
cv_init(&np->n_cv, "npfnatcv");
LIST_INIT(&np->n_nat_list);
/* Translation type. */
obj = prop_dictionary_get(natdict, "type");
np->n_type = prop_number_integer_value(obj);
/* Translation type. */
obj = prop_dictionary_get(natdict, "flags");
np->n_flags = prop_number_integer_value(obj);
/* Translation type and flags. */
prop_dictionary_get_int32(natdict, "type", &np->n_type);
prop_dictionary_get_uint32(natdict, "flags", &np->n_flags);
KASSERT(np->n_type == NPF_NATIN || np->n_type == NPF_NATOUT);
/* Translation IP. */
obj = prop_dictionary_get(natdict, "translation-ip");
np->n_addr_sz = prop_data_size(obj);
KASSERT(np->n_addr_sz > 0 && np->n_addr_sz <= sizeof(npf_addr_t));
taddr = (const npf_addr_t *)prop_data_data_nocopy(obj);
memcpy(&np->n_taddr, taddr, np->n_addr_sz);
memcpy(&np->n_taddr, prop_data_data_nocopy(obj), np->n_addr_sz);
/* Translation port (for redirect case). */
obj = prop_dictionary_get(natdict, "translation-port");
np->n_tport = (in_port_t)prop_number_integer_value(obj);
KASSERT(np->n_type == NPF_NATIN || np->n_type == NPF_NATOUT);
prop_dictionary_get_uint16(natdict, "translation-port", &np->n_tport);
/* Determine if port map is needed. */
np->n_portmap = NULL;
@ -401,11 +393,21 @@ static npf_natpolicy_t *
npf_nat_inspect(npf_cache_t *npc, nbuf_t *nbuf, ifnet_t *ifp, const int di)
{
npf_ruleset_t *rlset;
npf_natpolicy_t *np;
npf_rule_t *rl;
npf_core_enter();
rlset = npf_core_natset();
rl = npf_ruleset_match(rlset, npc, nbuf, ifp, di, NPF_LAYER_3);
return rl ? npf_rule_getnat(rl) : NULL;
rl = npf_ruleset_inspect(npc, nbuf, rlset, ifp, di, NPF_LAYER_3);
if (rl == NULL) {
return NULL;
}
np = npf_rule_getnat(rl);
if (np == NULL) {
npf_core_exit();
return NULL;
}
return np;
}
/*
@ -580,12 +582,13 @@ npf_do_nat(npf_cache_t *npc, npf_session_t *se, nbuf_t *nbuf,
goto translate;
}
/* Inspect the packet for a NAT policy, if there is no session. */
npf_core_enter();
/*
* Inspect the packet for a NAT policy, if there is no session.
* Note: acquires the lock (releases, if not found).
*/
np = npf_nat_inspect(npc, nbuf, ifp, di);
if (np == NULL) {
/* If packet does not match - done. */
npf_core_exit();
return 0;
}
forw = true;
@ -728,13 +731,13 @@ npf_nat_save(prop_dictionary_t sedict, prop_array_t natlist, npf_nat_t *nt)
/* Set NAT entry data. */
nd = prop_data_create_data(nt, sizeof(npf_nat_t));
prop_dictionary_set(sedict, "nat-data", nd);
prop_object_release(nd);
/* Find or create a NAT policy. */
it = prop_array_iterator(natlist);
while ((npdict = prop_object_iterator_next(it)) != NULL) {
CTASSERT(sizeof(uintptr_t) <= sizeof(uint64_t));
itnp = (uintptr_t)prop_number_unsigned_integer_value(
prop_dictionary_get(npdict, "id-ptr"));
prop_dictionary_get_uint64(npdict, "id-ptr", (uint64_t *)&itnp);
if (itnp == (uintptr_t)np) {
break;
}
@ -743,16 +746,16 @@ npf_nat_save(prop_dictionary_t sedict, prop_array_t natlist, npf_nat_t *nt)
/* Create NAT policy dictionary and copy the data. */
npdict = prop_dictionary_create();
npd = prop_data_create_data(np, sizeof(npf_natpolicy_t));
/* Set the data, insert into the array. */
CTASSERT(sizeof(uintptr_t) <= sizeof(uint64_t));
prop_dictionary_set(npdict, "id-ptr",
prop_number_create_unsigned_integer((uintptr_t)np));
prop_dictionary_set(npdict, "nat-policy-data", npd);
prop_object_release(npd);
CTASSERT(sizeof(uintptr_t) <= sizeof(uint64_t));
prop_dictionary_set_uint64(npdict, "id-ptr", (uintptr_t)np);
prop_array_add(natlist, npdict);
prop_object_release(npdict);
}
prop_dictionary_set(sedict, "nat-policy",
prop_dictionary_copy(npdict));
prop_dictionary_set(sedict, "nat-policy", npdict);
prop_object_release(npdict);
return 0;
}

View File

@ -1,4 +1,4 @@
/* $NetBSD: npf_ruleset.c,v 1.6 2011/01/18 20:33:46 rmind Exp $ */
/* $NetBSD: npf_ruleset.c,v 1.7 2011/02/02 02:20:25 rmind Exp $ */
/*-
* Copyright (c) 2009-2011 The NetBSD Foundation, Inc.
@ -34,7 +34,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: npf_ruleset.c,v 1.6 2011/01/18 20:33:46 rmind Exp $");
__KERNEL_RCSID(0, "$NetBSD: npf_ruleset.c,v 1.7 2011/02/02 02:20:25 rmind Exp $");
#include <sys/param.h>
#include <sys/kernel.h>
@ -64,8 +64,12 @@ struct npf_hook {
LIST_ENTRY(npf_hook) hk_entry;
};
#define NPF_RNAME_LEN 16
/* Rule procedure structure. */
struct npf_rproc {
/* Name. */
char rp_name[NPF_RNAME_LEN];
/* Reference count. */
u_int rp_refcnt;
uint32_t rp_flags;
@ -80,12 +84,14 @@ struct npf_rproc {
/* Rule structure. */
struct npf_rule {
/* Rule name (optional) and list entry. */
char r_name[NPF_RNAME_LEN];
TAILQ_ENTRY(npf_rule) r_entry;
/* Optional: sub-ruleset, NAT policy. */
npf_ruleset_t r_subset;
npf_natpolicy_t * r_natp;
/* Rule priority: (highest) 0, 1, 2 ... n (lowest). */
u_int r_priority;
pri_t r_priority;
/* N-code to process. */
void * r_ncode;
size_t r_nc_size;
@ -220,34 +226,26 @@ npf_rproc_t *
npf_rproc_create(prop_dictionary_t rpdict)
{
npf_rproc_t *rp;
prop_object_t obj;
const char *rname;
rp = kmem_alloc(sizeof(npf_rproc_t), KM_SLEEP);
rp = kmem_zalloc(sizeof(npf_rproc_t), KM_SLEEP);
rp->rp_refcnt = 1;
/* Flags. */
obj = prop_dictionary_get(rpdict, "flags");
rp->rp_flags = prop_number_integer_value(obj);
/* Name and flags. */
prop_dictionary_get_cstring_nocopy(rpdict, "name", &rname);
strlcpy(rp->rp_name, rname, NPF_RNAME_LEN);
prop_dictionary_get_uint32(rpdict, "flags", &rp->rp_flags);
/* Logging interface ID (integer). */
obj = prop_dictionary_get(rpdict, "log-interface");
rp->rp_log_ifid = prop_number_integer_value(obj);
prop_dictionary_get_uint32(rpdict, "log-interface", &rp->rp_log_ifid);
/* Randomize IP ID (bool). */
obj = prop_dictionary_get(rpdict, "randomize-id");
rp->rp_rnd_ipid = prop_bool_true(obj);
/* IP ID randomization and IP_DF flag cleansing. */
prop_dictionary_get_bool(rpdict, "randomize-id", &rp->rp_rnd_ipid);
prop_dictionary_get_bool(rpdict, "no-df", &rp->rp_no_df);
/* IP_DF flag cleansing (bool). */
obj = prop_dictionary_get(rpdict, "no-df");
rp->rp_no_df = prop_bool_true(obj);
/* Minimum IP TTL (integer). */
obj = prop_dictionary_get(rpdict, "min-ttl");
rp->rp_minttl = prop_number_integer_value(obj);
/* Maximum TCP MSS (integer). */
obj = prop_dictionary_get(rpdict, "max-mss");
rp->rp_maxmss = prop_number_integer_value(obj);
/* Minimum IP TTL and maximum TCP MSS. */
prop_dictionary_get_uint32(rpdict, "min-ttl", &rp->rp_minttl);
prop_dictionary_get_uint32(rpdict, "max-mss", &rp->rp_maxmss);
return rp;
}
@ -276,14 +274,14 @@ npf_rproc_release(npf_rproc_t *rp)
}
void
npf_rproc_run(npf_cache_t *npc, nbuf_t *nbuf, npf_rproc_t *rp)
npf_rproc_run(npf_cache_t *npc, nbuf_t *nbuf, npf_rproc_t *rp, int error)
{
const uint32_t flags = rp->rp_flags;
KASSERT(rp->rp_refcnt > 0);
/* Normalize the packet, if required. */
if (flags & NPF_RPROC_NORMALIZE) {
if ((flags & NPF_RPROC_NORMALIZE) != 0 && !error) {
(void)npf_normalize(npc, nbuf,
rp->rp_rnd_ipid, rp->rp_no_df,
rp->rp_minttl, rp->rp_maxmss);
@ -291,7 +289,7 @@ npf_rproc_run(npf_cache_t *npc, nbuf_t *nbuf, npf_rproc_t *rp)
}
/* Log packet, if required. */
if (flags & NPF_RPROC_LOG) {
if ((flags & NPF_RPROC_LOG) != 0) {
npf_log_packet(npc, nbuf, rp->rp_log_ifid);
npf_stats_inc(NPF_STAT_RPROC_LOG);
}
@ -307,7 +305,7 @@ npf_rule_alloc(prop_dictionary_t rldict, npf_rproc_t *rp,
void *nc, size_t nc_size)
{
npf_rule_t *rl;
prop_object_t obj;
const char *rname;
int errat;
/* Allocate a rule structure. */
@ -323,17 +321,17 @@ npf_rule_alloc(prop_dictionary_t rldict, npf_rproc_t *rp,
rl->r_ncode = nc;
rl->r_nc_size = nc_size;
/* Attributes (integer). */
obj = prop_dictionary_get(rldict, "attributes");
rl->r_attr = prop_number_integer_value(obj);
/* Name (string, optional) */
if (prop_dictionary_get_cstring_nocopy(rldict, "name", &rname)) {
strlcpy(rl->r_name, rname, NPF_RNAME_LEN);
} else {
rl->r_name[0] = '\0';
}
/* Priority (integer). */
obj = prop_dictionary_get(rldict, "priority");
rl->r_priority = prop_number_integer_value(obj);
/* Interface ID (integer). */
obj = prop_dictionary_get(rldict, "interface");
rl->r_ifid = prop_number_integer_value(obj);
/* Attributes, priority and interface ID. */
prop_dictionary_get_uint32(rldict, "attributes", &rl->r_attr);
prop_dictionary_get_int32(rldict, "priority", &rl->r_priority);
prop_dictionary_get_uint32(rldict, "interface", &rl->r_ifid);
/* Rule procedure. */
if (rp) {
@ -398,6 +396,7 @@ npf_rule_setnat(npf_rule_t *rl, npf_natpolicy_t *np)
rl->r_natp = np;
}
#if 0
/*
* npf_hook_register: register action hook in the rule.
*/
@ -432,21 +431,49 @@ npf_hook_unregister(npf_rule_t *rl, npf_hook_t *hk)
mutex_exit(&rl->r_hooks_lock);
kmem_free(hk, sizeof(npf_hook_t));
}
#endif
npf_rule_t *
npf_ruleset_replace(const char *name, npf_ruleset_t *rlset)
{
npf_ruleset_t orlset;
npf_rule_t *rl;
npf_core_enter(); /* XXX */
rlset = npf_core_ruleset();
TAILQ_FOREACH(rl, &rlset->rs_queue, r_entry) {
if (rl->r_name[0] == '\0')
continue;
if (strncmp(rl->r_name, name, NPF_RNAME_LEN))
continue;
memcpy(&orlset, &rl->r_subset, sizeof(npf_ruleset_t));
break;
}
npf_core_exit();
return rl;
}
/*
* npf_ruleset_match: inspect the packet against the given ruleset.
* npf_ruleset_inspect: inspect the packet against the given ruleset.
*
* Loop for each rule in the set and run n-code processor of each rule
* against the packet (nbuf chain).
* Loop through the rules in the set and run n-code processor of each rule
* against the packet (nbuf chain). If sub-ruleset is found, inspect it.
*
* => If not found, core ruleset lock is released.
* => Caller should protect the nbuf chain.
*/
npf_rule_t *
npf_ruleset_match(npf_ruleset_t *rlset, npf_cache_t *npc, nbuf_t *nbuf,
npf_ruleset_inspect(npf_cache_t *npc, nbuf_t *nbuf, npf_ruleset_t *mainrlset,
ifnet_t *ifp, const int di, const int layer)
{
const int di_mask = (di & PFIL_IN) ? NPF_RULE_IN : NPF_RULE_OUT;
npf_ruleset_t *rlset = mainrlset;
npf_rule_t *final_rl = NULL, *rl;
bool defed = false;
KASSERT(npf_core_locked());
KASSERT(((di & PFIL_IN) != 0) ^ ((di & PFIL_OUT) != 0));
again:
TAILQ_FOREACH(rl, &rlset->rs_queue, r_entry) {
KASSERT(!final_rl || rl->r_priority >= final_rl->r_priority);
@ -456,9 +483,6 @@ npf_ruleset_match(npf_ruleset_t *rlset, npf_cache_t *npc, nbuf_t *nbuf,
}
/* Match the direction. */
if ((rl->r_attr & NPF_RULE_DIMASK) != NPF_RULE_DIMASK) {
const int di_mask =
(di & PFIL_IN) ? NPF_RULE_IN : NPF_RULE_OUT;
if ((rl->r_attr & di_mask) == 0)
continue;
}
@ -473,45 +497,22 @@ npf_ruleset_match(npf_ruleset_t *rlset, npf_cache_t *npc, nbuf_t *nbuf,
break;
}
}
return final_rl;
}
/*
* npf_ruleset_inspect: inspection of the main ruleset for filtering.
* If sub-ruleset is found, inspect it.
*
* => If found, ruleset is kept read-locked.
* => Caller should protect the nbuf chain.
*/
npf_rule_t *
npf_ruleset_inspect(npf_cache_t *npc, nbuf_t *nbuf,
ifnet_t *ifp, const int di, const int layer)
{
npf_ruleset_t *rlset;
npf_rule_t *rl;
bool defed;
defed = false;
npf_core_enter();
rlset = npf_core_ruleset();
reinspect:
rl = npf_ruleset_match(rlset, npc, nbuf, ifp, di, layer);
/* If no final rule, then - default. */
if (rl == NULL && !defed) {
npf_ruleset_t *mainrlset = npf_core_ruleset();
rl = mainrlset->rs_default;
if (final_rl == NULL && !defed) {
final_rl = mainrlset->rs_default;
defed = true;
}
/* Inspect the sub-ruleset, if any. */
if (rl && !TAILQ_EMPTY(&rl->r_subset.rs_queue)) {
rlset = &rl->r_subset;
goto reinspect;
if (final_rl && !TAILQ_EMPTY(&final_rl->r_subset.rs_queue)) {
rlset = &final_rl->r_subset;
final_rl = NULL;
goto again;
}
if (rl == NULL) {
if (final_rl == NULL) {
npf_core_exit();
}
return rl;
return final_rl;
}
/*

View File

@ -1,4 +1,4 @@
/* $NetBSD: npf_session.c,v 1.7 2011/01/18 20:33:46 rmind Exp $ */
/* $NetBSD: npf_session.c,v 1.8 2011/02/02 02:20:25 rmind Exp $ */
/*-
* Copyright (c) 2010-2011 The NetBSD Foundation, Inc.
@ -74,7 +74,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: npf_session.c,v 1.7 2011/01/18 20:33:46 rmind Exp $");
__KERNEL_RCSID(0, "$NetBSD: npf_session.c,v 1.8 2011/02/02 02:20:25 rmind Exp $");
#include <sys/param.h>
#include <sys/kernel.h>
@ -952,9 +952,12 @@ npf_session_save(prop_array_t selist, prop_array_t nplist)
sedict = prop_dictionary_create();
sd = prop_data_create_data(se, sizeof(npf_session_t));
prop_dictionary_set(sedict, "data", sd);
prop_object_release(sd);
CTASSERT(sizeof(uintptr_t) <= sizeof(uint64_t));
prop_dictionary_set(sedict, "id-ptr",
prop_number_create_unsigned_integer((uintptr_t)se));
prop_dictionary_set_uint64(
sedict, "id-ptr", (uintptr_t)se);
if (se->s_nat) {
/* Save NAT entry and policy, if any. */
error = npf_nat_save(sedict, nplist, se->s_nat);
@ -964,6 +967,7 @@ npf_session_save(prop_array_t selist, prop_array_t nplist)
}
}
prop_array_add(selist, sedict);
prop_object_release(sedict);
}
rw_exit(&sh->sh_lock);
if (error) {

View File

@ -1,4 +1,4 @@
/* $NetBSD: npf_tableset.c,v 1.4 2010/12/18 01:07:25 rmind Exp $ */
/* $NetBSD: npf_tableset.c,v 1.5 2011/02/02 02:20:25 rmind Exp $ */
/*-
* Copyright (c) 2009-2010 The NetBSD Foundation, Inc.
@ -39,7 +39,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: npf_tableset.c,v 1.4 2010/12/18 01:07:25 rmind Exp $");
__KERNEL_RCSID(0, "$NetBSD: npf_tableset.c,v 1.5 2011/02/02 02:20:25 rmind Exp $");
#include <sys/param.h>
#include <sys/kernel.h>
@ -78,7 +78,7 @@ struct npf_table {
/* Table ID. */
u_int t_id;
/* The storage type can be: 1. Hash 2. RB-tree. */
u_int t_type;
int t_type;
struct npf_hashl * t_hashl;
u_long t_hashmask;
rb_tree_t t_rbtree;
@ -310,19 +310,11 @@ npf_table_get(npf_tableset_t *tset, u_int tid)
if ((u_int)tid >= NPF_TABLE_SLOTS) {
return NULL;
}
if (tset == NULL) {
npf_core_enter();
rtset = npf_core_tableset();
} else {
rtset = tset;
}
rtset = tset ? tset : npf_core_tableset();
t = rtset[tid];
if (t != NULL) {
rw_enter(&t->t_lock, RW_READER);
}
if (tset == NULL) {
npf_core_exit();
}
return t;
}
@ -479,11 +471,9 @@ int
npf_table_match_v4addr(u_int tid, in_addr_t ip4addr)
{
struct npf_hashl *htbl;
npf_tblent_t *e;
npf_tblent_t *e = NULL;
npf_table_t *t;
e = NULL;
/* Locks the table. */
t = npf_table_get(NULL, tid);
if (__predict_false(t == NULL)) {

View File

@ -1,12 +1,12 @@
# $NetBSD: Makefile,v 1.2 2010/08/24 23:55:04 rmind Exp $
# $NetBSD: Makefile,v 1.3 2011/02/02 02:20:25 rmind Exp $
PROG= npfctl
MAN= npfctl.8 npf.conf.5
SRCS= npfctl.c npf_parser.c npf_data.c npf_ncgen.c
LDADD+= -lprop
DPADD+= ${LIBPROP}
LDADD+= -lnpf
DPADD+= ${LIBNPF}
WARNS?= 4
NOLINT= # defined (note: deliberately)

View File

@ -1,4 +1,4 @@
.\" $NetBSD: npf.conf.5,v 1.3 2011/01/18 20:33:45 rmind Exp $
.\" $NetBSD: npf.conf.5,v 1.4 2011/02/02 02:20:25 rmind Exp $
.\"
.\" Copyright (c) 2009-2011 The NetBSD Foundation, Inc.
.\" All rights reserved.
@ -27,7 +27,7 @@
.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
.\" POSSIBILITY OF SUCH DAMAGE.
.\"
.Dd January 18, 2011
.Dd February 2, 2011
.Dt NPF.CONF 5
.Os
.Sh NAME
@ -56,8 +56,8 @@ The default group must always be defined.
Rules, which are the main part of NPF configuration, describe the criteria
used to inspect and make decisions about packets.
Currently, NPF supports filtering on the following criteria: interface,
traffic direction, protocol, IPv4 address or network, and TCP/UDP port
or range.
traffic direction, protocol, IPv4 address or network, TCP/UDP port
or range, TCP flags, and ICMP type/code.
Supported actions are blocking or passing the packet.
.Pp
Each rule has a priority, which is set according to its order in the ruleset.
@ -70,8 +70,47 @@ marked as final.
If there is no matching rule in the custom group, then rules in the default
group will be inspected.
.Pp
Stateful filtering is supported using the "keep state" keyword.
In such cases, state (a session) is created and any further packets
of the connection are tracked.
Packets in backwards stream, after having been confirmed to belong to
the same connection, are passed without ruleset inspection.
Rules may have associated rule procedures (described in a later section),
which are applied for all packets of a connection.
.Pp
Definitions (prefixed with "$") and tables (specified by an ID within
"\*[Lt]\*[Gt]" marks) can be used in the filter options of rules.
.Sh RULE PROCEDURES AND NORMALIZATION
Rule procedures are provided to perform packet transformations and various
additional procedures on the packets.
It should be noted that rule procedures are applied for the connections,
that is, both for packets which match the rule and for further packets
of the connection, which are passed without ruleset inspection.
Currently, two facilities are supported:
traffic normalization and packet logging.
Packet normalization has the following functionality:
IP ID randomization, IP_DF flag cleansing, TCP minimum TTL enforcement,
and maximum MSS enforcement ("MSS clamping").
If a matching rule is going to drop the packet, normalization functions
are not performed.
Packet logging is performed both in packet passing and blocking cases.
.Sh NAT
Rules for address translation can be added.
Translation is performed on the specified interface, assigning the specified
address of said interface.
There are three types of translation:
Network Address Port Translation (NAPT) - a regular NAT,
also known as "outbound NAT";
Port forwarding (redirection) - also known as "inbound NAT";
Bi-directional NAT - a combination of inbound and outbound NAT.
.Pp
Minimal filtering criteria on local network and destination are provided.
Note that address translation implies routing, therefore IP forwarding
is required to be enabled:
net.inet.ip.forwarding = 1.
See
.Xr sysctl 7
for more details.
.Sh TABLES
Certain configurations might use very large sets of IP addresses or change
sets frequently.
@ -85,11 +124,6 @@ Tables can be managed dynamically or loaded from a separate file, which
is useful for large static tables.
There are two types of storage: "tree" (red-black tree is used) and
"hash".
.Sh NAT
Special rules for Network Address Translation (NAT) can be added.
Translation is performed on specified interface, assigning a specified
address of said interface.
Minimal filtering criteria on local network and destination are provided.
.\" -----
.Sh GRAMMAR
.Bd -literal

View File

@ -1,4 +1,4 @@
/* $NetBSD: npf_data.c,v 1.6 2011/01/18 20:33:45 rmind Exp $ */
/* $NetBSD: npf_data.c,v 1.7 2011/02/02 02:20:25 rmind Exp $ */
/*-
* Copyright (c) 2009-2011 The NetBSD Foundation, Inc.
@ -27,13 +27,11 @@
*/
/*
* NPF proplib(9) dictionary producer.
*
* XXX: Needs some clean-up.
* npfctl(8) helper routines.
*/
#include <sys/cdefs.h>
__RCSID("$NetBSD: npf_data.c,v 1.6 2011/01/18 20:33:45 rmind Exp $");
__RCSID("$NetBSD: npf_data.c,v 1.7 2011/02/02 02:20:25 rmind Exp $");
#include <sys/types.h>
#include <sys/socket.h>
@ -42,7 +40,6 @@ __RCSID("$NetBSD: npf_data.c,v 1.6 2011/01/18 20:33:45 rmind Exp $");
#include <netinet/tcp.h>
#include <arpa/inet.h>
#include <prop/proplib.h>
#include <stdlib.h>
#include <string.h>
@ -56,110 +53,27 @@ __RCSID("$NetBSD: npf_data.c,v 1.6 2011/01/18 20:33:45 rmind Exp $");
#include "npfctl.h"
static struct ifaddrs * ifs_list = NULL;
static prop_dictionary_t npf_dict, settings_dict;
static prop_array_t nat_arr, tables_arr, rproc_arr, rules_arr;
static pri_t gr_prio_counter = 1;
static pri_t rl_prio_counter = 1;
static pri_t nat_prio_counter = 1;
static u_int rproc_id_counter = 1;
nl_config_t * npf_conf = NULL;
void
npfctl_init_data(void)
{
if (getifaddrs(&ifs_list) == -1)
npf_conf = npf_config_create();
if (npf_conf == NULL) {
errx(EXIT_FAILURE, "npf_config_create");
}
if (getifaddrs(&ifs_list) == -1) {
err(EXIT_FAILURE, "getifaddrs");
npf_dict = prop_dictionary_create();
nat_arr = prop_array_create();
prop_dictionary_set(npf_dict, "translation", nat_arr);
settings_dict = prop_dictionary_create();
prop_dictionary_set(npf_dict, "settings", settings_dict);
tables_arr = prop_array_create();
prop_dictionary_set(npf_dict, "tables", tables_arr);
rproc_arr = prop_array_create();
prop_dictionary_set(npf_dict, "rprocs", rproc_arr);
rules_arr = prop_array_create();
prop_dictionary_set(npf_dict, "rules", rules_arr);
}
}
int
npfctl_ioctl_send(int fd)
{
int ret = 0, errval;
#ifdef _NPF_TESTING
prop_dictionary_externalize_to_file(npf_dict, "./npf.plist");
#else
errval = prop_dictionary_send_ioctl(npf_dict, fd, IOC_NPF_RELOAD);
if (errval) {
errx(EXIT_FAILURE, "npfctl_ioctl_send: %s\n", strerror(errval));
}
#endif
prop_object_release(npf_dict);
return ret;
}
int
npfctl_ioctl_flushse(int fd)
{
prop_dictionary_t sesdict;
prop_array_t selist;
int errval;
sesdict = prop_dictionary_create();
selist = prop_array_create();
prop_dictionary_set(sesdict, "session-list", selist);
errval = prop_dictionary_send_ioctl(sesdict, fd, IOC_NPF_SESSIONS_LOAD);
if (errval) {
errx(EXIT_FAILURE, "npfctl_ioctl_flushse: %s\n",
strerror(errval));
}
prop_object_release(sesdict);
return errval;
}
int
npfctl_ioctl_sendse(int fd)
{
prop_dictionary_t sesdict;
int error;
sesdict = prop_dictionary_internalize_from_file(NPF_SESSDB_PATH);
if (sesdict == NULL) {
errx(EXIT_FAILURE, "npfctl: no sessions saved "
"('%s' does not exist)", NPF_SESSDB_PATH);
}
error = prop_dictionary_send_ioctl(sesdict, fd, IOC_NPF_SESSIONS_LOAD);
prop_object_release(sesdict);
if (error) {
err(EXIT_FAILURE, "npfctl_ioctl_sendse");
}
return 0;
}
int
npfctl_ioctl_recvse(int fd)
{
prop_dictionary_t sesdict;
int error;
error = prop_dictionary_recv_ioctl(fd, IOC_NPF_SESSIONS_SAVE, &sesdict);
if (error) {
err(EXIT_FAILURE, "prop_array_recv_ioctl");
}
if (!prop_dictionary_externalize_to_file(sesdict, NPF_SESSDB_PATH)) {
errx(EXIT_FAILURE, "could not save to '%s'", NPF_SESSDB_PATH);
}
prop_object_release(sesdict);
return 0;
int error = npf_config_submit(npf_conf, fd);
npf_config_destroy(npf_conf);
return error;
}
/*
@ -211,7 +125,7 @@ npfctl_parse_v4mask(char *ostr, in_addr_t *addr, in_addr_t *mask)
return ret;
}
static bool
bool
npfctl_parse_port(char *ostr, bool *range, in_port_t *fport, in_port_t *tport)
{
char *str = xstrdup(ostr), *sep;
@ -239,7 +153,7 @@ npfctl_parse_port(char *ostr, bool *range, in_port_t *fport, in_port_t *tport)
return true;
}
static void
void
npfctl_parse_cidr(char *str, in_addr_t *addr, in_addr_t *mask)
{
@ -299,55 +213,14 @@ npfctl_parse_tcpfl(char *s, uint8_t *tfl, uint8_t *tfl_mask)
return true;
}
/*
* NPF table creation and construction routines.
*/
prop_dictionary_t
npfctl_lookup_table(char *tidstr)
{
prop_dictionary_t tl;
prop_object_iterator_t it;
prop_object_t obj;
u_int tid;
tid = atoi(tidstr);
it = prop_array_iterator(tables_arr);
while ((tl = prop_object_iterator_next(it)) != NULL) {
obj = prop_dictionary_get(tl, "id");
if (tid == prop_number_integer_value(obj))
break;
}
return tl;
}
prop_dictionary_t
npfctl_construct_table(int id, int type)
{
prop_dictionary_t tl;
tl = prop_dictionary_create();
/* TODO: 1. check ID range 2. check if not a duplicate */
prop_dictionary_set(tl, "id", prop_number_create_integer(id));
prop_dictionary_set(tl, "type", prop_number_create_integer(type));
prop_dictionary_set(tl, "entries", prop_array_create());
prop_array_add(tables_arr, tl);
return tl;
}
void
npfctl_fill_table(prop_dictionary_t tl, char *fname)
npfctl_fill_table(nl_table_t *tl, char *fname)
{
prop_dictionary_t entdict;
prop_array_t tblents;
char *buf;
FILE *fp;
size_t n;
int l;
tblents = prop_dictionary_get(tl, "entries");
assert(tblents != NULL);
fp = fopen(fname, "r");
if (fp == NULL) {
err(EXIT_FAILURE, "open '%s'", fname);
@ -361,16 +234,12 @@ npfctl_fill_table(prop_dictionary_t tl, char *fname)
continue;
/* IPv4 CIDR: a.b.c.d/mask */
if (!npfctl_parse_v4mask(buf, &addr, &mask))
if (!npfctl_parse_v4mask(buf, &addr, &mask)) {
errx(EXIT_FAILURE, "invalid table entry at line %d", l);
}
/* Create and add table entry. */
entdict = prop_dictionary_create();
prop_dictionary_set(entdict, "addr",
prop_number_create_integer(addr));
prop_dictionary_set(entdict, "mask",
prop_number_create_integer(mask));
prop_array_add(tblents, entdict);
npf_table_add_entry(tl, addr, mask);
l++;
}
if (buf != NULL) {
@ -379,54 +248,7 @@ npfctl_fill_table(prop_dictionary_t tl, char *fname)
}
/*
* npfctl_mk_rule: create a rule (or group) dictionary.
*
* Note: group is a rule containing subrules. It has no n-code, however.
*/
prop_dictionary_t
npfctl_mk_rule(bool group, prop_dictionary_t parent)
{
prop_dictionary_t rl;
prop_array_t subrl, rlset;
pri_t pri;
rl = prop_dictionary_create();
if (group) {
subrl = prop_array_create();
prop_dictionary_set(rl, "subrules", subrl);
/* Give new priority, reset rule priority counter. */
pri = gr_prio_counter++;
rl_prio_counter = 1;
} else {
pri = rl_prio_counter++;
}
prop_dictionary_set(rl, "priority", prop_number_create_integer(pri));
if (parent) {
rlset = prop_dictionary_get(parent, "subrules");
assert(rlset != NULL);
} else {
rlset = rules_arr;
}
prop_array_add(rlset, rl);
return rl;
}
void
npfctl_rule_setattr(prop_dictionary_t rl, int attr, u_int iface)
{
prop_number_t attrnum, ifnum;
attrnum = prop_number_create_integer(attr);
prop_dictionary_set(rl, "attributes", attrnum);
if (iface) {
ifnum = prop_number_create_integer(iface);
prop_dictionary_set(rl, "interface", ifnum);
}
}
/*
* Main rule generation routines.
* N-code generation helpers.
*/
static void
@ -497,15 +319,13 @@ npfctl_rulenc_block(void **nc, int nblocks[], var_t *cidr, var_t *ports,
}
void
npfctl_rule_protodata(prop_dictionary_t rl, char *proto, char *tcp_flags,
int icmp_type, int icmp_code,
var_t *from, var_t *fports, var_t *to, var_t *tports)
npfctl_rule_ncode(nl_rule_t *rl, char *proto, char *tcpfl, int icmp_type,
int icmp_code, var_t *from, var_t *fports, var_t *to, var_t *tports)
{
prop_data_t ncdata;
int nblocks[3] = { 0, 0, 0 };
bool icmp, tcpudp, both;
int foff, nblocks[3] = { 0, 0, 0 };
void *ncptr, *nc;
size_t sz;
size_t sz, foff;
/*
* Default: both TCP and UDP.
@ -537,11 +357,11 @@ npfctl_rule_protodata(prop_dictionary_t rl, char *proto, char *tcp_flags,
}
skip_proto:
if (icmp || icmp_type != -1) {
assert(tcp_flags == NULL);
assert(tcpfl == NULL);
icmp = true;
nblocks[2] += 1;
}
if (tcpudp && tcp_flags) {
if (tcpudp && tcpfl) {
assert(icmp_type == -1 && icmp_code == -1);
nblocks[2] += 1;
}
@ -574,8 +394,7 @@ skip_proto:
sz = npfctl_calc_ncsize(nblocks);
ncptr = malloc(sz);
if (ncptr == NULL) {
perror("malloc");
exit(EXIT_FAILURE);
err(EXIT_FAILURE, "malloc");
}
nc = ncptr;
@ -599,7 +418,7 @@ skip_proto:
foff = npfctl_failure_offset(nblocks);
npfctl_gennc_icmp(&nc, foff, icmp_type, icmp_code);
} else if (tcpudp && tcp_flags) {
} else if (tcpudp && tcpfl) {
/*
* TCP case, flags.
*/
@ -607,8 +426,8 @@ skip_proto:
nblocks[2]--;
foff = npfctl_failure_offset(nblocks);
if (!npfctl_parse_tcpfl(tcp_flags, &tfl, &tfl_mask)) {
errx(EXIT_FAILURE, "invalid TCP flags '%s'", tcp_flags);
if (!npfctl_parse_tcpfl(tcpfl, &tfl, &tfl_mask)) {
errx(EXIT_FAILURE, "invalid TCP flags '%s'", tcpfl);
}
npfctl_gennc_tcpfl(&nc, foff, tfl, tfl_mask);
}
@ -630,107 +449,8 @@ skip_proto:
#endif
/* Create a final memory block of data, ready to send. */
ncdata = prop_data_create_data(ncptr, sz);
if (ncdata == NULL) {
perror("prop_data_create_data");
exit(EXIT_FAILURE);
if (npf_rule_setcode(rl, NPF_CODE_NCODE, ncptr, sz) == -1) {
errx(EXIT_FAILURE, "npf_rule_setcode");
}
prop_dictionary_set(rl, "ncode", ncdata);
free(ncptr);
}
/*
* Rule procedure construction routines.
*/
prop_dictionary_t
npfctl_mk_rproc(void)
{
prop_dictionary_t rp;
rp = prop_dictionary_create();
prop_dictionary_set(rp, "id",
prop_number_create_unsigned_integer(rproc_id_counter++));
prop_array_add(rproc_arr, rp);
return rp;
}
bool
npfctl_find_rproc(prop_dictionary_t rl, char *name)
{
prop_dictionary_t rp;
prop_object_iterator_t it;
prop_object_t obj;
it = prop_array_iterator(rproc_arr);
while ((rp = prop_object_iterator_next(it)) != NULL) {
obj = prop_dictionary_get(rp, "name");
if (strcmp(prop_string_cstring(obj), name) == 0)
break;
}
if (rp == NULL) {
return false;
}
prop_dictionary_set(rl, "rproc-id", prop_dictionary_get(rp, "id"));
return true;
}
/*
* NAT policy construction routines.
*/
prop_dictionary_t
npfctl_mk_nat(void)
{
prop_dictionary_t rl;
pri_t pri;
/* NAT policy is rule with extra info. */
rl = prop_dictionary_create();
pri = nat_prio_counter++;
prop_dictionary_set(rl, "priority", prop_number_create_integer(pri));
prop_array_add(nat_arr, rl);
return rl;
}
void
npfctl_nat_setup(prop_dictionary_t rl, int type, int flags,
u_int iface, char *taddr, char *rport)
{
int attr = NPF_RULE_PASS | NPF_RULE_FINAL;
in_addr_t addr, _dummy;
prop_data_t addrdat;
/* Translation type and flags. */
prop_dictionary_set(rl, "type",
prop_number_create_integer(type));
prop_dictionary_set(rl, "flags",
prop_number_create_integer(flags));
/* Interface and attributes. */
attr |= (type == NPF_NATOUT) ? NPF_RULE_OUT : NPF_RULE_IN;
npfctl_rule_setattr(rl, attr, iface);
/* Translation IP. */
npfctl_parse_cidr(taddr, &addr, &_dummy);
addrdat = prop_data_create_data(&addr, sizeof(in_addr_t));
if (addrdat == NULL) {
err(EXIT_FAILURE, "prop_data_create_data");
}
prop_dictionary_set(rl, "translation-ip", addrdat);
/* Translation port (for redirect case). */
if (rport) {
in_port_t port;
bool range;
if (!npfctl_parse_port(rport, &range, &port, &port)) {
errx(EXIT_FAILURE, "invalid service '%s'", rport);
}
if (range) {
errx(EXIT_FAILURE, "range is not supported for 'rdr'");
}
prop_dictionary_set(rl, "translation-port",
prop_number_create_integer(port));
}
}

View File

@ -1,4 +1,4 @@
/* $NetBSD: npf_parser.c,v 1.5 2011/01/18 20:33:45 rmind Exp $ */
/* $NetBSD: npf_parser.c,v 1.6 2011/02/02 02:20:25 rmind Exp $ */
/*-
* Copyright (c) 2009-2011 The NetBSD Foundation, Inc.
@ -31,7 +31,7 @@
*/
#include <sys/cdefs.h>
__RCSID("$NetBSD: npf_parser.c,v 1.5 2011/01/18 20:33:45 rmind Exp $");
__RCSID("$NetBSD: npf_parser.c,v 1.6 2011/02/02 02:20:25 rmind Exp $");
#include <stdio.h>
#include <stdlib.h>
@ -92,7 +92,7 @@ npfctl_parsevalue(char *buf)
/* Definition - lookup. */
vr = npfctl_lookup_varlist(++p);
if (vr == NULL) {
errx(EXIT_FAILURE, "invalid variable '%s'", p);
errx(EXIT_FAILURE, "variable '%s' is not defined", p);
}
break;
case '{':
@ -123,8 +123,8 @@ npfctl_parsevalue(char *buf)
return NULL;
}
*tend = '\0';
if (npfctl_lookup_table(p) == NULL) {
errx(EXIT_FAILURE, "invalid table '%s'", p);
if (!npf_table_exists_p(npf_conf, (u_int)atoi(p))) {
errx(EXIT_FAILURE, "table '%s' is not defined", p);
}
vr = zalloc(sizeof(var_t));
vr->v_type = VAR_TABLE;
@ -149,7 +149,7 @@ npfctl_val_single(var_t *v, char *p)
element_t *el;
if (v->v_type != VAR_SINGLE) {
errx(EXIT_FAILURE, "invalid value '%s'", p);
errx(EXIT_FAILURE, "multiple elements in variable '%s'", p);
}
el = v->v_elements;
return el->e_data;
@ -168,7 +168,7 @@ npfctl_val_interface(var_t *v, char *p, bool reqaddr)
}
static int
npfctl_parsenorm(char *buf, prop_dictionary_t rp)
npfctl_parsenorm(char *buf, nl_rproc_t *rp)
{
char *p = buf, *sptr;
int minttl = 0, maxmss = 0;
@ -194,15 +194,11 @@ npfctl_parsenorm(char *buf, prop_dictionary_t rp)
}
} while ((p = strtok_r(NULL, ", \t", &sptr)) != 0);
prop_dictionary_set(rp, "randomize-id", prop_bool_create(rnd));
prop_dictionary_set(rp, "min-ttl", prop_number_create_integer(minttl));
prop_dictionary_set(rp, "max-mss", prop_number_create_integer(maxmss));
prop_dictionary_set(rp, "no-df", prop_bool_create(no_df));
return 0;
return _npf_rproc_setnorm(rp, rnd, no_df, minttl, maxmss);
}
static int
npfctl_parserproc(char *buf, prop_dictionary_t rp)
npfctl_parserproc(char *buf, nl_rproc_t **rp)
{
char *p = buf, *end;
@ -213,21 +209,20 @@ npfctl_parserproc(char *buf, prop_dictionary_t rp)
if ((end = strchr(++p, '"')) == NULL)
return -1;
*end = '\0';
prop_dictionary_set(rp, "name", prop_string_create_cstring(p));
return 0;
*rp = npf_rproc_create(p);
if (*rp == NULL) {
return -1;
}
return npf_rproc_insert(npf_conf, *rp) ? -1 : 0;
}
static int
npfctl_parserproc_lines(char *buf, prop_dictionary_t rp)
npfctl_parserproc_lines(char *buf, nl_rproc_t *rp)
{
char *p = buf, *sptr;
prop_object_t obj;
uint32_t attr;
DPRINTF(("rproc\t|%s|\n", p));
obj = prop_dictionary_get(rp, "flags");
attr = obj ? prop_number_integer_value(obj) : 0;
PARSE_FIRST_TOKEN();
/* log <interface> */
@ -239,9 +234,7 @@ npfctl_parserproc_lines(char *buf, prop_dictionary_t rp)
if ((ifvar = npfctl_parsevalue(p)) == NULL)
return PARSE_ERR();
if_idx = npfctl_val_interface(ifvar, p, false);
prop_dictionary_set(rp, "log-interface",
prop_number_create_integer(if_idx));
attr |= NPF_RPROC_LOG;
(void)_npf_rproc_setlog(rp, if_idx);
} else if (strcmp(p, "normalize") == 0) {
/* normalize ( .. ) */
@ -252,10 +245,8 @@ npfctl_parserproc_lines(char *buf, prop_dictionary_t rp)
if (npfctl_parsenorm(p, rp)) {
return PARSE_ERR();
}
attr |= NPF_RPROC_NORMALIZE;
PARSE_NEXT_TOKEN_NOCHECK();
}
prop_dictionary_set(rp, "flags", prop_number_create_integer(attr));
return 0;
}
@ -269,15 +260,15 @@ npfctl_parserproc_lines(char *buf, prop_dictionary_t rp)
* [ keep state ] [ apply "<rproc>" ]
*/
static int
npfctl_parserule(char *buf, prop_dictionary_t rl)
npfctl_parserule(char *buf, nl_rule_t *parent)
{
var_t *from_cidr = NULL, *fports = NULL;
var_t *to_cidr = NULL, *tports = NULL;
char *p, *sptr, *proto = NULL, *tcp_flags = NULL;
var_t *from_v = NULL, *fports = NULL, *to_v = NULL, *tports = NULL;
char *p, *sptr, *proto = NULL, *tcp_flags = NULL, *rproc = NULL;
int icmp_type = -1, icmp_code = -1;
bool icmp = false, tcp = false;
u_int iface = 0;
u_int if_idx = 0;
int ret, attr = 0;
nl_rule_t *rl;
DPRINTF(("rule\t|%s|\n", buf));
@ -329,7 +320,7 @@ npfctl_parserule(char *buf, prop_dictionary_t rl)
PARSE_NEXT_TOKEN();
if ((ifvar = npfctl_parsevalue(p)) == NULL)
return PARSE_ERR();
iface = npfctl_val_interface(ifvar, p, true);
if_idx = npfctl_val_interface(ifvar, p, true);
PARSE_NEXT_TOKEN();
}
@ -370,7 +361,7 @@ npfctl_parserule(char *buf, prop_dictionary_t rl)
/* from <addr> port <port | range> */
if (strcmp(p, "from") == 0) {
PARSE_NEXT_TOKEN();
from_cidr = npfctl_parsevalue(p);
from_v = npfctl_parsevalue(p);
PARSE_NEXT_TOKEN_NOCHECK();
if (p && strcmp(p, "port") == 0) {
@ -384,7 +375,7 @@ npfctl_parserule(char *buf, prop_dictionary_t rl)
/* to <addr> port <port | range> */
if (p && strcmp(p, "to") == 0) {
PARSE_NEXT_TOKEN();
to_cidr = npfctl_parsevalue(p);
to_v = npfctl_parsevalue(p);
PARSE_NEXT_TOKEN_NOCHECK();
if (p && strcmp(p, "port") == 0) {
@ -446,9 +437,10 @@ last:
if ((end = strchr(++p, '"')) == NULL)
return PARSE_ERR();
*end = '\0';
if (!npfctl_find_rproc(rl, p)) {
errx(EXIT_FAILURE, "invalid procedure '%s'", p);
if (!npf_rproc_exists_p(npf_conf, p)) {
errx(EXIT_FAILURE, "procedure '%s' is not defined", p);
}
rproc = p;
PARSE_NEXT_TOKEN_NOCHECK();
}
@ -460,9 +452,13 @@ last:
/*
* Set the rule attributes and interface. Generate all protocol data.
*/
npfctl_rule_setattr(rl, attr, iface);
npfctl_rule_protodata(rl, proto, tcp_flags, icmp_type, icmp_code,
from_cidr, fports, to_cidr, tports);
rl = npf_rule_create(NULL, attr, if_idx);
npfctl_rule_ncode(rl, proto, tcp_flags, icmp_type, icmp_code,
from_v, fports, to_v, tports);
if (rproc && npf_rule_setproc(npf_conf, rl, rproc) != 0) {
errx(EXIT_FAILURE, "procedure '%s' is not defined", rproc);
}
npf_rule_insert(npf_conf, parent, rl, NPF_PRI_NEXT);
return 0;
}
@ -476,10 +472,10 @@ last:
#define GROUP_ATTRS (NPF_RULE_PASS | NPF_RULE_FINAL)
static int
npfctl_parsegroup(char *buf, prop_dictionary_t rl)
npfctl_parsegroup(char *buf, nl_rule_t **rl)
{
char *p = buf, *end, *sptr;
u_int iface = 0;
char *p = buf, *end, *sptr, *rname = NULL;
u_int if_idx = 0;
int attr_dir;
DPRINTF(("group\t|%s|\n", buf));
@ -502,8 +498,7 @@ npfctl_parsegroup(char *buf, prop_dictionary_t rl)
*/
if (strcmp(p, "default") == 0) {
attr_dir = NPF_RULE_DEFAULT | (NPF_RULE_IN | NPF_RULE_OUT);
npfctl_rule_setattr(rl, GROUP_ATTRS | attr_dir, 0);
return 0;
goto done;
}
PARSE_FIRST_TOKEN();
@ -513,10 +508,10 @@ npfctl_parsegroup(char *buf, prop_dictionary_t rl)
PARSE_NEXT_TOKEN()
if (*p != '"')
return -1;
if ((end = strchr(++p, '"')) == NULL)
rname = ++p;
if ((p = strchr(rname, '"')) == NULL)
return -1;
*end = '\0';
/* TODO: p == name */
*p = '\0';
PARSE_NEXT_TOKEN_NOCHECK();
}
@ -526,7 +521,7 @@ npfctl_parsegroup(char *buf, prop_dictionary_t rl)
PARSE_NEXT_TOKEN();
if ((ifvar = npfctl_parsevalue(p)) == NULL)
return -1;
iface = npfctl_val_interface(ifvar, p, true);
if_idx = npfctl_val_interface(ifvar, p, true);
PARSE_NEXT_TOKEN_NOCHECK();
}
@ -541,8 +536,12 @@ npfctl_parsegroup(char *buf, prop_dictionary_t rl)
} else {
attr_dir = NPF_RULE_IN | NPF_RULE_OUT;
}
npfctl_rule_setattr(rl, GROUP_ATTRS | attr_dir, iface);
done:
*rl = npf_rule_create(rname, GROUP_ATTRS | attr_dir, if_idx);
if (*rl == NULL) {
return -1;
}
npf_rule_insert(npf_conf, NULL, *rl, NPF_PRI_NEXT);
return 0;
}
@ -554,9 +553,9 @@ npfctl_parsegroup(char *buf, prop_dictionary_t rl)
static int
npfctl_parsetable(char *buf)
{
prop_dictionary_t tl;
char *p, *sptr, *fname;
unsigned int id, type;
nl_table_t *tl;
DPRINTF(("table\t|%s|\n", buf));
@ -583,7 +582,7 @@ npfctl_parsetable(char *buf)
} else if (strcmp(p, "tree")) {
type = NPF_TABLE_RBTREE;
} else {
errx(EXIT_FAILURE, "invalid table type '%s'\n", p);
errx(EXIT_FAILURE, "invalid table type '%s'", p);
}
if ((p = strchr(++p, '"')) == NULL) {
return PARSE_ERR();
@ -593,7 +592,10 @@ npfctl_parsetable(char *buf)
/*
* Setup the table.
*/
tl = npfctl_construct_table(id, type);
tl = npf_table_create(id, type);
if (npf_table_insert(npf_conf, tl)) {
errx(EXIT_FAILURE, "table '%d' is already defined\n", id);
}
PARSE_NEXT_TOKEN();
/* Dynamic. */
@ -621,17 +623,19 @@ npfctl_parsetable(char *buf)
*
* [bi]nat <if> from <net> to <net/addr> -> <ip>
* rdr <if> from <net> to <addr> -> <ip>
* nat <if> dynamic "<name>"
*/
static int
npfctl_parse_nat(char *buf)
{
prop_dictionary_t nat, bn;
var_t *ifvar, *from_cidr, *to_cidr, *ip;
var_t *tports = NULL, *rports = NULL;
element_t *cidr;
char *p, *sptr;
var_t *ifvar, *from_v, *to_v, *raddr_v;
var_t *tports = NULL, *rport_v = NULL;
char *p, *sptr, *raddr_s, *rport_s;
in_addr_t raddr4, _dummy;
npf_addr_t raddr;
bool binat, rdr;
u_int iface;
nl_nat_t *nat;
u_int if_idx;
DPRINTF(("[bi]nat/rdr\t|%s|\n", buf));
binat = (strncmp(buf, "binat", 5) == 0);
@ -646,15 +650,35 @@ npfctl_parse_nat(char *buf)
if ((ifvar = npfctl_parsevalue(p)) == NULL) {
return PARSE_ERR();
}
iface = npfctl_val_interface(ifvar, p, true);
if_idx = npfctl_val_interface(ifvar, p, true);
PARSE_NEXT_TOKEN();
/* dynamic <name> */
if (!binat && !rdr && strcmp(p, "dynamic") == 0) {
char *nname;
/* Parse name. */
PARSE_NEXT_TOKEN()
if (*p != '"')
return PARSE_ERR();
nname = ++p;
if ((p = strchr(nname, '"')) == NULL)
return PARSE_ERR();
*p = '\0';
/* Create a rule and insert into the NAT list. */
nat = npf_rule_create(nname, NPF_RULE_PASS | NPF_RULE_FINAL |
NPF_RULE_OUT | NPF_RULE_IN, if_idx);
(void)npf_nat_insert(npf_conf, nat, NPF_PRI_NEXT);
return 0;
}
/* from <addr> */
if (strcmp(p, "from") != 0) {
return PARSE_ERR();
}
PARSE_NEXT_TOKEN();
from_cidr = npfctl_parsevalue(p);
from_v = npfctl_parsevalue(p);
PARSE_NEXT_TOKEN();
/* to <addr> */
@ -662,7 +686,7 @@ npfctl_parse_nat(char *buf)
return PARSE_ERR();
}
PARSE_NEXT_TOKEN();
to_cidr = npfctl_parsevalue(p);
to_v = npfctl_parsevalue(p);
PARSE_NEXT_TOKEN();
if (rdr && strcmp(p, "port") == 0) {
@ -676,8 +700,10 @@ npfctl_parse_nat(char *buf)
return PARSE_ERR();
}
PARSE_NEXT_TOKEN();
ip = npfctl_parsevalue(p);
cidr = ip->v_elements;
raddr_v = npfctl_parsevalue(p);
raddr_s = npfctl_val_single(raddr_v, p);
npfctl_parse_cidr(raddr_s, &raddr4, &_dummy);
memcpy(&raddr, &raddr4, sizeof(struct in_addr)); /* XXX IPv6 */
if (rdr) {
PARSE_NEXT_TOKEN();
@ -685,7 +711,8 @@ npfctl_parse_nat(char *buf)
return PARSE_ERR();
}
PARSE_NEXT_TOKEN();
rports = npfctl_parsevalue(p);
rport_v = npfctl_parsevalue(p);
rport_s = npfctl_val_single(rport_v, p);
}
/*
@ -695,22 +722,25 @@ npfctl_parse_nat(char *buf)
*
* XXX mess
*/
nat = npfctl_mk_nat();
if (!rdr) {
npfctl_rule_protodata(nat, NULL, NULL, -1, -1, from_cidr,
NULL, to_cidr, NULL);
npfctl_nat_setup(nat, NPF_NATOUT,
nat = npf_nat_create(NPF_NATOUT,
binat ? 0 : (NPF_NAT_PORTS | NPF_NAT_PORTMAP),
iface, cidr->e_data, NULL);
if_idx, &raddr, AF_INET, 0);
} else {
element_t *rp = rports->v_elements;
in_port_t rport;
bool range;
npfctl_rule_protodata(nat, NULL, NULL, -1, -1, from_cidr,
NULL, to_cidr, tports);
npfctl_nat_setup(nat, NPF_NATIN, NPF_NAT_PORTS,
iface, cidr->e_data, rp->e_data);
if (!npfctl_parse_port(rport_s, &range, &rport, &rport)) {
errx(EXIT_FAILURE, "invalid service '%s'", rport_s);
}
if (range) {
errx(EXIT_FAILURE, "range is not supported for 'rdr'");
}
nat = npf_nat_create(NPF_NATIN, NPF_NAT_PORTS,
if_idx, &raddr, AF_INET, rport);
}
npfctl_rule_ncode(nat, NULL, NULL, -1, -1, from_v, NULL, to_v, tports);
(void)npf_nat_insert(npf_conf, nat, NPF_PRI_NEXT);
/*
* For bi-directional NAT case, create and setup additional
@ -720,13 +750,17 @@ npfctl_parse_nat(char *buf)
* XXX mess
*/
if (binat) {
element_t *taddr = from_cidr->v_elements;
char *taddr_s = npfctl_val_single(from_v, NULL);
in_addr_t taddr4;
npf_addr_t taddr;
nl_nat_t *bn;
bn = npfctl_mk_nat();
npfctl_rule_protodata(bn, NULL, NULL, -1, -1,
to_cidr, NULL, ip, NULL);
npfctl_nat_setup(bn, NPF_NATIN, 0, iface,
taddr->e_data, NULL);
npfctl_parse_cidr(taddr_s, &taddr4, &_dummy);
memcpy(&taddr, &taddr4, sizeof(struct in_addr)); /* XXX IPv6 */
bn = npf_nat_create(NPF_NATIN, 0, if_idx, &taddr, AF_INET, 0);
npfctl_rule_ncode(bn, NULL, NULL, -1, -1,
to_v, NULL, raddr_v, NULL);
(void)npf_nat_insert(npf_conf, bn, NPF_PRI_NEXT);
}
return 0;
}
@ -784,8 +818,8 @@ npfctl_parsevar(char *buf)
int
npf_parseline(char *buf)
{
static prop_dictionary_t curgr = NULL;
static prop_dictionary_t currp = NULL;
static nl_rule_t *curgr = NULL;
static nl_rproc_t *currp = NULL;
char *p = buf;
int ret;
@ -797,16 +831,13 @@ npf_parseline(char *buf)
/* At first, check if inside the group or rproc. */
if (curgr) {
prop_dictionary_t rl;
/* End of the group. */
if (*p == '}') {
curgr = NULL;
return 0;
}
/* Rule. */
rl = npfctl_mk_rule(false, curgr);
ret = npfctl_parserule(p, rl);
ret = npfctl_parserule(p, curgr);
} else if (currp) {
/* End of the procedure. */
@ -819,13 +850,11 @@ npf_parseline(char *buf)
} else if (strncmp(p, "group", 5) == 0) {
/* Group. */
curgr = npfctl_mk_rule(true, NULL);
ret = npfctl_parsegroup(p, curgr);
ret = npfctl_parsegroup(p, &curgr);
} else if (strncmp(p, "procedure", 9) == 0) {
/* Rule procedure. */
currp = npfctl_mk_rproc();
ret = npfctl_parserproc(p, currp);
ret = npfctl_parserproc(p, &currp);
} else if (strncmp(p, "table", 5) == 0) {
/* Table. */

View File

@ -1,4 +1,4 @@
/* $NetBSD: npfctl.c,v 1.4 2011/01/18 20:33:45 rmind Exp $ */
/* $NetBSD: npfctl.c,v 1.5 2011/02/02 02:20:25 rmind Exp $ */
/*-
* Copyright (c) 2009-2011 The NetBSD Foundation, Inc.
@ -30,7 +30,7 @@
*/
#include <sys/cdefs.h>
__RCSID("$NetBSD: npfctl.c,v 1.4 2011/01/18 20:33:45 rmind Exp $");
__RCSID("$NetBSD: npfctl.c,v 1.5 2011/02/02 02:20:25 rmind Exp $");
#include <sys/ioctl.h>
#include <sys/stat.h>
@ -232,7 +232,7 @@ npfctl(int action, int argc, char **argv)
if (ret) {
break;
}
ret = npfctl_ioctl_flushse(fd);
ret = npf_sessions_send(fd, NULL);
break;
case NPFCTL_TABLE:
if (argc < 5) {
@ -262,10 +262,18 @@ npfctl(int action, int argc, char **argv)
ret = npfctl_print_stats(fd);
break;
case NPFCTL_SESSIONS_SAVE:
ret = npfctl_ioctl_recvse(fd);
ret = npf_sessions_recv(fd, NPF_SESSDB_PATH);
if (ret) {
errx(EXIT_FAILURE, "could not save sessions to '%s'",
NPF_SESSDB_PATH);
}
break;
case NPFCTL_SESSIONS_LOAD:
ret = npfctl_ioctl_sendse(fd);
ret = npf_sessions_send(fd, NPF_SESSDB_PATH);
if (ret) {
errx(EXIT_FAILURE, "no sessions loaded from '%s'",
NPF_SESSDB_PATH);
}
break;
}
if (ret == -1) {

View File

@ -1,4 +1,4 @@
/* $NetBSD: npfctl.h,v 1.5 2011/01/18 20:33:45 rmind Exp $ */
/* $NetBSD: npfctl.h,v 1.6 2011/02/02 02:20:25 rmind Exp $ */
/*-
* Copyright (c) 2009-2011 The NetBSD Foundation, Inc.
@ -33,13 +33,11 @@
#include <stdio.h>
#include <stdbool.h>
#ifndef _NPF_TESTING
#include <net/npf.h>
#include <net/npf_ncode.h>
#else
#include "npf.h"
#include "npf_ncode.h"
#endif
#include <net/npf.h>
#define _NPF_PRIVATE
#include <npf.h>
#ifdef DEBUG
#define DPRINTF(x) printf x
@ -68,34 +66,23 @@ typedef struct {
void * v_next;
} var_t;
extern nl_config_t * npf_conf;
void * zalloc(size_t);
char * xstrdup(const char *);
void npfctl_init_data(void);
int npfctl_ioctl_send(int);
int npfctl_ioctl_recvse(int);
int npfctl_ioctl_sendse(int);
int npfctl_ioctl_flushse(int);
struct ifaddrs *npfctl_getif(char *, unsigned int *, bool);
bool npfctl_parse_v4mask(char *, in_addr_t *, in_addr_t *);
void npfctl_parse_cidr(char *, in_addr_t *, in_addr_t *);
bool npfctl_parse_port(char *, bool *, in_port_t *, in_port_t *);
prop_dictionary_t npfctl_mk_rule(bool, prop_dictionary_t);
void npfctl_rule_setattr(prop_dictionary_t, int, u_int);
void npfctl_rule_protodata(prop_dictionary_t, char *, char *,
void npfctl_fill_table(nl_table_t *, char *);
void npfctl_rule_ncode(nl_rule_t *, char *, char *,
int, int, var_t *, var_t *, var_t *, var_t *);
void npfctl_rule_icmpdata(prop_dictionary_t, var_t *, var_t *);
prop_dictionary_t npfctl_lookup_table(char *);
prop_dictionary_t npfctl_construct_table(int, int);
void npfctl_fill_table(prop_dictionary_t, char *);
prop_dictionary_t npfctl_mk_rproc(void);
bool npfctl_find_rproc(prop_dictionary_t, char *);
prop_dictionary_t npfctl_mk_nat(void);
void npfctl_nat_setup(prop_dictionary_t, int, int,
u_int, char *, char *);
size_t npfctl_calc_ncsize(int []);
size_t npfctl_failure_offset(int []);

View File

@ -1,4 +1,4 @@
# $NetBSD: Makefile,v 1.4 2009/04/22 15:23:06 lukem Exp $
# $NetBSD: Makefile,v 1.5 2011/02/02 02:20:26 rmind Exp $
# $OpenBSD: Makefile,v 1.3 2006/11/26 11:31:13 deraadt Exp $
PROG= ftp-proxy
@ -13,6 +13,13 @@ CPPFLAGS+=-I${NETBSDSRCDIR}/sys
.include <bsd.own.mk>
# NPF support
.if (${MKNPF} != "no")
SRCS+= npf.c
CPPFLAGS+= -DWITH_NPF
LDADD+= -lnpf
.endif
# IP Filter support
.if (${MKIPFILTER} != "no")
SRCS+= ipf.c