Add IPv6 support for NPF.
This commit is contained in:
parent
766dd565c7
commit
5a5d868dc5
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: npf.c,v 1.2 2011/02/02 15:17:37 rmind Exp $ */
|
||||
/* $NetBSD: npf.c,v 1.3 2011/11/04 01:00:28 zoltan Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2010-2011 The NetBSD Foundation, Inc.
|
||||
|
@ -30,7 +30,7 @@
|
|||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: npf.c,v 1.2 2011/02/02 15:17:37 rmind Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: npf.c,v 1.3 2011/11/04 01:00:28 zoltan Exp $");
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <netinet/in_systm.h>
|
||||
|
@ -429,18 +429,21 @@ npf_table_create(int id, int type)
|
|||
}
|
||||
|
||||
int
|
||||
npf_table_add_entry(nl_table_t *tl, in_addr_t addr, in_addr_t mask)
|
||||
npf_table_add_entry(nl_table_t *tl, npf_addr_t *addr, npf_netmask_t mask)
|
||||
{
|
||||
prop_dictionary_t tldict = tl->ntl_dict, entdict;
|
||||
prop_array_t tblents;
|
||||
prop_data_t addrdata;
|
||||
|
||||
/* 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);
|
||||
addrdata = prop_data_create_data(addr, sizeof(npf_addr_t));
|
||||
prop_dictionary_set(entdict, "addr", addrdata);
|
||||
prop_dictionary_set_uint8(entdict, "mask", mask);
|
||||
prop_object_release(addrdata);
|
||||
|
||||
/* Insert the entry. */
|
||||
tblents = prop_dictionary_get(tldict, "entries");
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: npf.h,v 1.1 2011/02/02 02:20:25 rmind Exp $ */
|
||||
/* $NetBSD: npf.h,v 1.2 2011/11/04 01:00:28 zoltan Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2011 The NetBSD Foundation, Inc.
|
||||
|
@ -84,7 +84,7 @@ 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);
|
||||
int npf_table_add_entry(nl_table_t *, npf_addr_t *, npf_netmask_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 *);
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: npf.h,v 1.8 2011/02/02 23:01:34 rmind Exp $ */
|
||||
/* $NetBSD: npf.h,v 1.9 2011/11/04 01:00:27 zoltan Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2009-2011 The NetBSD Foundation, Inc.
|
||||
|
@ -55,8 +55,11 @@
|
|||
* Public declarations and definitions.
|
||||
*/
|
||||
|
||||
/* Storage of address (both for IPv4 and IPv6). */
|
||||
/* Storage of address (both for IPv4 and IPv6) and netmask */
|
||||
typedef struct in6_addr npf_addr_t;
|
||||
typedef uint_fast8_t npf_netmask_t;
|
||||
|
||||
#define NPF_NO_NETMASK (npf_netmask_t)~0
|
||||
|
||||
#if defined(_KERNEL) || defined(_NPF_TESTING)
|
||||
|
||||
|
@ -80,7 +83,7 @@ typedef struct npf_hook npf_hook_t;
|
|||
|
||||
#define NPC_IP4 0x01 /* Indicates fetched IPv4 header. */
|
||||
#define NPC_IP6 0x02 /* Indicates IPv6 header. */
|
||||
#define NPC_IPFRAG 0x04 /* IPv4 fragment. */
|
||||
#define NPC_IPFRAG 0x04 /* IPv4/IPv6 fragment. */
|
||||
#define NPC_LAYER4 0x08 /* Layer 4 has been fetched. */
|
||||
|
||||
#define NPC_TCP 0x10 /* TCP header. */
|
||||
|
@ -98,6 +101,8 @@ typedef struct {
|
|||
npf_addr_t * npc_dstip;
|
||||
/* Size (v4 or v6) of IP addresses. */
|
||||
int npc_ipsz;
|
||||
size_t npc_hlen;
|
||||
int npc_next_proto;
|
||||
/* IPv4, IPv6. */
|
||||
union {
|
||||
struct ip v4;
|
||||
|
@ -111,6 +116,71 @@ typedef struct {
|
|||
} npc_l4;
|
||||
} npf_cache_t;
|
||||
|
||||
/* Max length is 32 for IPv4 and 128 for IPv6 */
|
||||
static inline void
|
||||
npf_generate_mask(npf_addr_t *dst, const npf_netmask_t omask)
|
||||
{
|
||||
uint_fast8_t length = omask;
|
||||
|
||||
KASSERT(length <= 128);
|
||||
memset(dst, 0, sizeof(npf_addr_t));
|
||||
for (int i = 0; i < 4; i++) {
|
||||
if (length >= 32) {
|
||||
dst->s6_addr32[i] = htonl(0xffffffff);
|
||||
length -= 32;
|
||||
} else {
|
||||
dst->s6_addr32[i] = htonl(0xffffffff << (32 - length));
|
||||
length = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static inline void
|
||||
npf_calculate_masked_addr(npf_addr_t *dst, const npf_addr_t *src, const npf_netmask_t omask)
|
||||
{
|
||||
npf_addr_t mask;
|
||||
|
||||
npf_generate_mask(&mask, omask);
|
||||
for (int i = 0; i < 4; i++) {
|
||||
dst->s6_addr32[i] =
|
||||
src->s6_addr32[i] & mask.s6_addr32[i];
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* compare two addresses, either v4 or v6
|
||||
* if the mask is NULL, ignore it
|
||||
*/
|
||||
static inline int
|
||||
npf_compare_cidr(const npf_addr_t *addr1, const npf_netmask_t mask1,
|
||||
const npf_addr_t *addr2, const npf_netmask_t mask2)
|
||||
{
|
||||
npf_addr_t realmask1, realmask2;
|
||||
|
||||
if (mask1 != NPF_NO_NETMASK) {
|
||||
npf_generate_mask(&realmask1, mask1);
|
||||
}
|
||||
if (mask2 != NPF_NO_NETMASK) {
|
||||
npf_generate_mask(&realmask2, mask2);
|
||||
}
|
||||
for (int i = 0; i < 4; i++) {
|
||||
const uint32_t x = mask1 != NPF_NO_NETMASK ?
|
||||
addr1->s6_addr32[i] & realmask1.s6_addr32[i] :
|
||||
addr1->s6_addr32[i];
|
||||
const uint32_t y = mask2 != NPF_NO_NETMASK ?
|
||||
addr2->s6_addr32[i] & realmask2.s6_addr32[i] :
|
||||
addr2->s6_addr32[i];
|
||||
if (x < y) {
|
||||
return -1;
|
||||
}
|
||||
if (x > y) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline bool
|
||||
npf_iscached(const npf_cache_t *npc, const int inf)
|
||||
{
|
||||
|
@ -121,10 +191,15 @@ npf_iscached(const npf_cache_t *npc, const int inf)
|
|||
static inline int
|
||||
npf_cache_ipproto(const npf_cache_t *npc)
|
||||
{
|
||||
const struct ip *ip = &npc->npc_ip.v4;
|
||||
|
||||
KASSERT(npf_iscached(npc, NPC_IP46));
|
||||
return ip->ip_p;
|
||||
return npc->npc_next_proto;
|
||||
}
|
||||
|
||||
static inline int
|
||||
npf_cache_hlen(const npf_cache_t *npc, nbuf_t *nbuf)
|
||||
{
|
||||
KASSERT(npf_iscached(npc, NPC_IP46));
|
||||
return npc->npc_hlen;
|
||||
}
|
||||
|
||||
/* Network buffer interface. */
|
||||
|
@ -190,8 +265,8 @@ void npf_hook_unregister(npf_rule_t *, npf_hook_t *);
|
|||
typedef struct npf_ioctl_table {
|
||||
int nct_action;
|
||||
u_int nct_tid;
|
||||
in_addr_t nct_addr;
|
||||
in_addr_t nct_mask;
|
||||
npf_addr_t nct_addr;
|
||||
npf_netmask_t nct_mask;
|
||||
int _reserved;
|
||||
} npf_ioctl_table_t;
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: npf_alg_icmp.c,v 1.6 2011/01/18 20:33:45 rmind Exp $ */
|
||||
/* $NetBSD: npf_alg_icmp.c,v 1.7 2011/11/04 01:00:27 zoltan Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2010 The NetBSD Foundation, Inc.
|
||||
|
@ -34,7 +34,7 @@
|
|||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: npf_alg_icmp.c,v 1.6 2011/01/18 20:33:45 rmind Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: npf_alg_icmp.c,v 1.7 2011/11/04 01:00:27 zoltan Exp $");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/kernel.h>
|
||||
|
@ -119,7 +119,8 @@ npfa_icmp_match(npf_cache_t *npc, nbuf_t *nbuf, void *ntptr)
|
|||
struct ip *ip = &npc->npc_ip.v4;
|
||||
in_port_t dport;
|
||||
|
||||
KASSERT(npf_iscached(npc, NPC_IP46 | NPC_LAYER4));
|
||||
KASSERT(npf_iscached(npc, NPC_IP46));
|
||||
KASSERT(npf_iscached(npc, NPC_LAYER4));
|
||||
|
||||
/* Check for low TTL. */
|
||||
if (ip->ip_ttl > TR_MAX_TTL) {
|
||||
|
@ -247,10 +248,10 @@ npfa_icmp_session(npf_cache_t *npc, nbuf_t *nbuf, void *keyptr)
|
|||
KASSERT(npf_iscached(npc, NPC_ICMP));
|
||||
|
||||
/* Advance to ICMP header. */
|
||||
struct ip *ip = &npc->npc_ip.v4;
|
||||
void *n_ptr = nbuf_dataptr(nbuf);
|
||||
const size_t hlen = npf_cache_hlen(npc, nbuf);
|
||||
|
||||
if ((n_ptr = nbuf_advance(&nbuf, n_ptr, ip->ip_hl << 2)) == NULL) {
|
||||
if ((n_ptr = nbuf_advance(&nbuf, n_ptr, hlen)) == NULL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -297,7 +298,8 @@ npfa_icmp_natin(npf_cache_t *npc, nbuf_t *nbuf, void *ntptr)
|
|||
return false;
|
||||
}
|
||||
/* XXX: Restore inversion (inefficient). */
|
||||
KASSERT(npf_iscached(&enpc, NPC_IP46 | NPC_LAYER4));
|
||||
KASSERT(npf_iscached(&enpc, NPC_IP46));
|
||||
KASSERT(npf_iscached(&enpc, NPC_LAYER4));
|
||||
npfa_srcdst_invert(&enpc);
|
||||
|
||||
/*
|
||||
|
@ -306,7 +308,7 @@ npfa_icmp_natin(npf_cache_t *npc, nbuf_t *nbuf, void *ntptr)
|
|||
* embedded packet changes, while data is not rewritten in the cache.
|
||||
*/
|
||||
const int proto = npf_cache_ipproto(&enpc);
|
||||
const struct ip * const ip = &npc->npc_ip.v4, *eip = &enpc.npc_ip.v4;
|
||||
const struct ip *eip = &enpc.npc_ip.v4;
|
||||
const struct icmp * const ic = &npc->npc_l4.icmp;
|
||||
uint16_t cksum = ic->icmp_cksum, ecksum = eip->ip_sum, l4cksum;
|
||||
npf_nat_t *nt = ntptr;
|
||||
|
@ -331,7 +333,7 @@ npfa_icmp_natin(npf_cache_t *npc, nbuf_t *nbuf, void *ntptr)
|
|||
* to the embedded IP header after ICMP header.
|
||||
*/
|
||||
void *n_ptr = nbuf_dataptr(nbuf), *cnbuf = nbuf, *cnptr = n_ptr;
|
||||
u_int offby = (ip->ip_hl << 2) + offsetof(struct icmp, icmp_ip);
|
||||
u_int offby = npf_cache_hlen(npc, nbuf) + offsetof(struct icmp, icmp_ip);
|
||||
|
||||
if ((n_ptr = nbuf_advance(&nbuf, n_ptr, offby)) == NULL) {
|
||||
return false;
|
||||
|
@ -365,7 +367,7 @@ npfa_icmp_natin(npf_cache_t *npc, nbuf_t *nbuf, void *ntptr)
|
|||
}
|
||||
cksum = npf_fixup16_cksum(cksum, ecksum, eip->ip_sum);
|
||||
|
||||
offby = (ip->ip_hl << 2) + offsetof(struct icmp, icmp_cksum);
|
||||
offby = npf_cache_hlen(npc, nbuf) + offsetof(struct icmp, icmp_cksum);
|
||||
if (nbuf_advstore(&cnbuf, &cnptr, offby, sizeof(uint16_t), &cksum)) {
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: npf_ctl.c,v 1.6 2011/02/02 02:20:25 rmind Exp $ */
|
||||
/* $NetBSD: npf_ctl.c,v 1.7 2011/11/04 01:00:27 zoltan 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.6 2011/02/02 02:20:25 rmind Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: npf_ctl.c,v 1.7 2011/11/04 01:00:27 zoltan Exp $");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/conf.h>
|
||||
|
@ -120,12 +120,13 @@ npf_mk_tables(npf_tableset_t *tblset, prop_array_t tables)
|
|||
}
|
||||
eit = prop_array_iterator(entries);
|
||||
while ((ent = prop_object_iterator_next(eit)) != NULL) {
|
||||
in_addr_t addr, mask; /* XXX: IPv6 */
|
||||
const npf_addr_t *addr;
|
||||
npf_netmask_t mask;
|
||||
|
||||
/* 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);
|
||||
addr = (const npf_addr_t *)prop_data_data_nocopy(prop_dictionary_get(ent, "addr"));
|
||||
prop_dictionary_get_uint8(ent, "mask", &mask);
|
||||
error = npf_table_add_cidr(tblset, tid, addr, mask);
|
||||
if (error)
|
||||
break;
|
||||
}
|
||||
|
@ -600,16 +601,16 @@ npfctl_table(void *data)
|
|||
npf_core_enter(); /* XXXSMP */
|
||||
switch (nct->nct_action) {
|
||||
case NPF_IOCTL_TBLENT_ADD:
|
||||
error = npf_table_add_v4cidr(NULL, nct->nct_tid,
|
||||
nct->nct_addr, nct->nct_mask);
|
||||
error = npf_table_add_cidr(NULL, nct->nct_tid,
|
||||
&nct->nct_addr, nct->nct_mask);
|
||||
break;
|
||||
case NPF_IOCTL_TBLENT_REM:
|
||||
error = npf_table_rem_v4cidr(NULL, nct->nct_tid,
|
||||
nct->nct_addr, nct->nct_mask);
|
||||
error = npf_table_rem_cidr(NULL, nct->nct_tid,
|
||||
&nct->nct_addr, nct->nct_mask);
|
||||
break;
|
||||
default:
|
||||
/* XXX */
|
||||
error = npf_table_match_v4addr(nct->nct_tid, nct->nct_addr);
|
||||
error = npf_table_match_addr(nct->nct_tid, &nct->nct_addr);
|
||||
if (error) {
|
||||
error = EINVAL;
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: npf_handler.c,v 1.7 2011/02/02 02:20:25 rmind Exp $ */
|
||||
/* $NetBSD: npf_handler.c,v 1.8 2011/11/04 01:00:27 zoltan 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.7 2011/02/02 02:20:25 rmind Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: npf_handler.c,v 1.8 2011/11/04 01:00:27 zoltan Exp $");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
|
@ -48,6 +48,8 @@ __KERNEL_RCSID(0, "$NetBSD: npf_handler.c,v 1.7 2011/02/02 02:20:25 rmind Exp $"
|
|||
#include <netinet/in_systm.h>
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/ip_var.h>
|
||||
#include <netinet/ip6.h>
|
||||
#include <netinet6/ip6_var.h>
|
||||
|
||||
#include "npf_impl.h"
|
||||
|
||||
|
@ -57,6 +59,7 @@ __KERNEL_RCSID(0, "$NetBSD: npf_handler.c,v 1.7 2011/02/02 02:20:25 rmind Exp $"
|
|||
*/
|
||||
static struct pfil_head * npf_ph_if = NULL;
|
||||
static struct pfil_head * npf_ph_inet = NULL;
|
||||
static struct pfil_head * npf_ph_inet6 = NULL;
|
||||
|
||||
static bool default_pass = true;
|
||||
|
||||
|
@ -86,7 +89,7 @@ npf_packet_handler(void *arg, struct mbuf **mp, ifnet_t *ifp, int di)
|
|||
npf_ruleset_t *rlset;
|
||||
npf_rule_t *rl;
|
||||
npf_rproc_t *rp;
|
||||
int retfl, error;
|
||||
int retfl, error, ret;
|
||||
|
||||
/*
|
||||
* Initialise packet information cache.
|
||||
|
@ -96,15 +99,28 @@ npf_packet_handler(void *arg, struct mbuf **mp, ifnet_t *ifp, int di)
|
|||
error = 0;
|
||||
retfl = 0;
|
||||
rp = NULL;
|
||||
ret = 0;
|
||||
|
||||
/* Cache everything. Determine whether it is an IPv4 fragment. */
|
||||
if (npf_cache_all(&npc, nbuf) && npf_iscached(&npc, NPC_IPFRAG)) {
|
||||
struct ip *ip = nbuf_dataptr(*mp);
|
||||
/*
|
||||
* Pass to IPv4 reassembly mechanism.
|
||||
*/
|
||||
if (ip_reass_packet(mp, ip) != 0) {
|
||||
/* Failed; invalid fragment(s) or packet. */
|
||||
/* Cache IP information */
|
||||
npf_cache_all(&npc, nbuf);
|
||||
|
||||
if (npf_iscached(&npc, NPC_IPFRAG)) {
|
||||
if (npf_iscached(&npc, NPC_IP4)) {
|
||||
struct ip *ip = nbuf_dataptr(*mp);
|
||||
/* Pass to IPv4 reassembly mechanism. */
|
||||
ret = ip_reass_packet(mp, ip);
|
||||
} else if (npf_iscached(&npc, NPC_IP6)) {
|
||||
/* frag6_input's offset is the start of the fragment header */
|
||||
size_t hlen = npf_cache_hlen(&npc, nbuf);
|
||||
|
||||
/* Pass to IPv6 reassembly mechanism. */
|
||||
ret = ip6_reass_packet(mp, hlen);
|
||||
} else {
|
||||
KASSERT(false);
|
||||
}
|
||||
|
||||
if (ret != 0) {
|
||||
error = EINVAL;
|
||||
se = NULL;
|
||||
goto out;
|
||||
|
@ -115,6 +131,13 @@ npf_packet_handler(void *arg, struct mbuf **mp, ifnet_t *ifp, int di)
|
|||
}
|
||||
/* Reassembly is complete, we have the final packet. */
|
||||
nbuf = (nbuf_t *)*mp;
|
||||
|
||||
/*
|
||||
* Before reassembly, we can't cache anything above layer3,
|
||||
* but at this point, it's reassembled - let's cache it again
|
||||
*/
|
||||
npc.npc_info = 0;
|
||||
npf_cache_all(&npc, nbuf);
|
||||
}
|
||||
|
||||
/* Inspect the list of sessions. */
|
||||
|
@ -230,6 +253,7 @@ npf_register_pfil(void)
|
|||
/* Capture point of any activity in interfaces and IP layer. */
|
||||
npf_ph_if = pfil_head_get(PFIL_TYPE_IFNET, 0);
|
||||
npf_ph_inet = pfil_head_get(PFIL_TYPE_AF, AF_INET);
|
||||
npf_ph_inet6 = pfil_head_get(PFIL_TYPE_AF, AF_INET6);
|
||||
if (npf_ph_if == NULL || npf_ph_inet == NULL) {
|
||||
npf_ph_if = NULL;
|
||||
error = ENOENT;
|
||||
|
@ -246,6 +270,9 @@ npf_register_pfil(void)
|
|||
PFIL_WAITOK | PFIL_ALL, npf_ph_inet);
|
||||
KASSERT(error == 0);
|
||||
|
||||
error = pfil_add_hook(npf_packet_handler, NULL,
|
||||
PFIL_WAITOK | PFIL_ALL, npf_ph_inet6);
|
||||
KASSERT(error == 0);
|
||||
fail:
|
||||
KERNEL_UNLOCK_ONE(NULL);
|
||||
mutex_exit(softnet_lock);
|
||||
|
@ -264,6 +291,8 @@ npf_unregister_pfil(void)
|
|||
KERNEL_LOCK(1, NULL);
|
||||
|
||||
if (npf_ph_if) {
|
||||
(void)pfil_remove_hook(npf_packet_handler, NULL,
|
||||
PFIL_ALL, npf_ph_inet6);
|
||||
(void)pfil_remove_hook(npf_packet_handler, NULL,
|
||||
PFIL_ALL, npf_ph_inet);
|
||||
(void)pfil_remove_hook(npf_ifhook, NULL,
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: npf_impl.h,v 1.7 2011/02/02 02:20:25 rmind Exp $ */
|
||||
/* $NetBSD: npf_impl.h,v 1.8 2011/11/04 01:00:27 zoltan Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2009-2011 The NetBSD Foundation, Inc.
|
||||
|
@ -161,7 +161,7 @@ uint16_t npf_fixup16_cksum(uint16_t, uint16_t, uint16_t);
|
|||
uint16_t npf_fixup32_cksum(uint16_t, uint32_t, uint32_t);
|
||||
uint16_t npf_addr_cksum(uint16_t, int, npf_addr_t *, npf_addr_t *);
|
||||
uint32_t npf_addr_sum(const int, const npf_addr_t *, const npf_addr_t *);
|
||||
int npf_tcpsaw(npf_cache_t *, tcp_seq *, tcp_seq *, uint32_t *);
|
||||
int npf_tcpsaw(npf_cache_t *, nbuf_t *, tcp_seq *, tcp_seq *, uint32_t *);
|
||||
bool npf_fetch_tcpopts(const npf_cache_t *, nbuf_t *,
|
||||
uint16_t *, int *);
|
||||
bool npf_normalize(npf_cache_t *, nbuf_t *, bool, bool, u_int, u_int);
|
||||
|
@ -169,10 +169,10 @@ void npf_return_block(npf_cache_t *, nbuf_t *, const int);
|
|||
|
||||
/* Complex instructions. */
|
||||
int npf_match_ether(nbuf_t *, int, int, uint16_t, uint32_t *);
|
||||
int npf_match_ip4table(npf_cache_t *, nbuf_t *, void *,
|
||||
int npf_match_table(npf_cache_t *, nbuf_t *, void *,
|
||||
const int, const u_int);
|
||||
int npf_match_ip4mask(npf_cache_t *, nbuf_t *, void *,
|
||||
const int, in_addr_t, in_addr_t);
|
||||
int npf_match_ipmask(npf_cache_t *, nbuf_t *, void *,
|
||||
const int, const npf_addr_t *, const npf_netmask_t);
|
||||
int npf_match_tcp_ports(npf_cache_t *, nbuf_t *, void *,
|
||||
const int, const uint32_t);
|
||||
int npf_match_udp_ports(npf_cache_t *, nbuf_t *, void *,
|
||||
|
@ -197,11 +197,11 @@ void npf_table_unref(npf_table_t *);
|
|||
npf_table_t * npf_table_get(npf_tableset_t *, u_int);
|
||||
void npf_table_put(npf_table_t *);
|
||||
int npf_table_check(npf_tableset_t *, u_int, int);
|
||||
int npf_table_add_v4cidr(npf_tableset_t *, u_int,
|
||||
in_addr_t, in_addr_t);
|
||||
int npf_table_rem_v4cidr(npf_tableset_t *, u_int,
|
||||
in_addr_t, in_addr_t);
|
||||
int npf_table_match_v4addr(u_int, in_addr_t);
|
||||
int npf_table_add_cidr(npf_tableset_t *, u_int,
|
||||
const npf_addr_t *, const npf_netmask_t);
|
||||
int npf_table_rem_cidr(npf_tableset_t *, u_int,
|
||||
const npf_addr_t *, const npf_netmask_t);
|
||||
int npf_table_match_addr(u_int, const npf_addr_t *);
|
||||
|
||||
/* Ruleset interface. */
|
||||
npf_ruleset_t * npf_ruleset_create(void);
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: npf_inet.c,v 1.6 2011/01/18 20:33:45 rmind Exp $ */
|
||||
/* $NetBSD: npf_inet.c,v 1.7 2011/11/04 01:00:27 zoltan Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2009-2011 The NetBSD Foundation, Inc.
|
||||
|
@ -34,7 +34,7 @@
|
|||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: npf_inet.c,v 1.6 2011/01/18 20:33:45 rmind Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: npf_inet.c,v 1.7 2011/11/04 01:00:27 zoltan Exp $");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/kernel.h>
|
||||
|
@ -126,18 +126,29 @@ npf_addr_sum(const int sz, const npf_addr_t *a1, const npf_addr_t *a2)
|
|||
* Returns all values in host byte-order.
|
||||
*/
|
||||
int
|
||||
npf_tcpsaw(npf_cache_t *npc, tcp_seq *seq, tcp_seq *ack, uint32_t *win)
|
||||
npf_tcpsaw(npf_cache_t *npc, nbuf_t *nbuf, tcp_seq *seq, tcp_seq *ack, uint32_t *win)
|
||||
{
|
||||
struct ip *ip = &npc->npc_ip.v4;
|
||||
struct tcphdr *th = &npc->npc_l4.tcp;
|
||||
|
||||
KASSERT(npf_iscached(npc, NPC_IP46 | NPC_TCP));
|
||||
KASSERT(npf_iscached(npc, NPC_TCP));
|
||||
|
||||
*seq = ntohl(th->th_seq);
|
||||
*ack = ntohl(th->th_ack);
|
||||
*win = (uint32_t)ntohs(th->th_win);
|
||||
|
||||
return ntohs(ip->ip_len) - (ip->ip_hl << 2) - (th->th_off << 2);
|
||||
/*
|
||||
* total length of packet - header length - tcp header length
|
||||
*/
|
||||
if (npf_iscached(npc, NPC_IP4)) {
|
||||
struct ip *ip = &npc->npc_ip.v4;
|
||||
return ntohs(ip->ip_len) - npf_cache_hlen(npc, nbuf) - (th->th_off << 2);
|
||||
} else {
|
||||
KASSERT(npf_iscached(npc, NPC_IP6));
|
||||
struct ip6_hdr *ip6 = &npc->npc_ip.v6;
|
||||
return ntohs(ip6->ip6_plen) - (th->th_off << 2);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -148,14 +159,13 @@ npf_fetch_tcpopts(const npf_cache_t *npc, nbuf_t *nbuf,
|
|||
uint16_t *mss, int *wscale)
|
||||
{
|
||||
void *n_ptr = nbuf_dataptr(nbuf);
|
||||
const struct ip *ip = &npc->npc_ip.v4;
|
||||
const struct tcphdr *th = &npc->npc_l4.tcp;
|
||||
int topts_len, step;
|
||||
uint16_t val16;
|
||||
uint8_t val;
|
||||
|
||||
KASSERT(npf_iscached(npc, NPC_IP46 | NPC_TCP));
|
||||
|
||||
KASSERT(npf_iscached(npc, NPC_IP46));
|
||||
KASSERT(npf_iscached(npc, NPC_TCP));
|
||||
/* Determine if there are any TCP options, get their length. */
|
||||
topts_len = (th->th_off << 2) - sizeof(struct tcphdr);
|
||||
if (topts_len <= 0) {
|
||||
|
@ -165,7 +175,7 @@ npf_fetch_tcpopts(const npf_cache_t *npc, nbuf_t *nbuf,
|
|||
KASSERT(topts_len <= MAX_TCPOPTLEN);
|
||||
|
||||
/* First step: IP and TCP header up to options. */
|
||||
step = (ip->ip_hl << 2) + sizeof(struct tcphdr);
|
||||
step = npf_cache_hlen(npc, nbuf) + sizeof(struct tcphdr);
|
||||
next:
|
||||
if (nbuf_advfetch(&nbuf, &n_ptr, step, sizeof(val), &val)) {
|
||||
return false;
|
||||
|
@ -229,6 +239,7 @@ bool
|
|||
npf_fetch_ip(npf_cache_t *npc, nbuf_t *nbuf, void *n_ptr)
|
||||
{
|
||||
struct ip *ip;
|
||||
struct ip6_hdr *ip6;
|
||||
uint8_t ver;
|
||||
|
||||
if (nbuf_fetch_datum(nbuf, n_ptr, sizeof(uint8_t), &ver)) {
|
||||
|
@ -255,10 +266,59 @@ npf_fetch_ip(npf_cache_t *npc, nbuf_t *nbuf, void *n_ptr)
|
|||
npc->npc_srcip = (npf_addr_t *)&ip->ip_src;
|
||||
npc->npc_dstip = (npf_addr_t *)&ip->ip_dst;
|
||||
npc->npc_info |= NPC_IP4;
|
||||
npc->npc_hlen = ip->ip_hl << 2;
|
||||
npc->npc_next_proto = npc->npc_ip.v4.ip_p;
|
||||
break;
|
||||
|
||||
case (IPV6_VERSION >> 4):
|
||||
/* TODO */
|
||||
ip6 = &npc->npc_ip.v6;
|
||||
if (nbuf_fetch_datum(nbuf, n_ptr, sizeof(struct ip6_hdr), ip6)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
struct ip6_ext ip6e;
|
||||
size_t toskip = sizeof(struct ip6_hdr);
|
||||
bool processing_ends = false;
|
||||
npc->npc_next_proto = ip6->ip6_nxt;
|
||||
npc->npc_hlen = 0;
|
||||
|
||||
do {
|
||||
/* advance the length of the previous known header,
|
||||
and fetch the next extension header's length */
|
||||
if (nbuf_advfetch(&nbuf, &n_ptr, toskip, sizeof(struct ip6_ext), &ip6e)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
switch (npc->npc_next_proto) {
|
||||
case IPPROTO_DSTOPTS:
|
||||
case IPPROTO_ROUTING:
|
||||
toskip = (ip6e.ip6e_len + 1) << 3;
|
||||
break;
|
||||
case IPPROTO_FRAGMENT:
|
||||
npc->npc_info |= NPC_IPFRAG;
|
||||
toskip = sizeof(struct ip6_frag);
|
||||
break;
|
||||
case IPPROTO_AH:
|
||||
toskip = (ip6e.ip6e_len + 2) << 2;
|
||||
break;
|
||||
default:
|
||||
processing_ends = true;
|
||||
break;
|
||||
}
|
||||
|
||||
npc->npc_hlen += toskip;
|
||||
|
||||
if (!processing_ends) {
|
||||
npc->npc_next_proto = ip6e.ip6e_nxt;
|
||||
}
|
||||
} while (!processing_ends);
|
||||
|
||||
npc->npc_ipsz = sizeof(struct in6_addr);
|
||||
npc->npc_srcip = (npf_addr_t *)&ip6->ip6_src;
|
||||
npc->npc_dstip = (npf_addr_t *)&ip6->ip6_dst;
|
||||
npc->npc_info |= NPC_IP6;
|
||||
break;
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
@ -268,22 +328,19 @@ npf_fetch_ip(npf_cache_t *npc, nbuf_t *nbuf, void *n_ptr)
|
|||
bool
|
||||
npf_fetch_tcp(npf_cache_t *npc, nbuf_t *nbuf, void *n_ptr)
|
||||
{
|
||||
struct ip *ip = &npc->npc_ip.v4;
|
||||
struct tcphdr *th;
|
||||
u_int hlen;
|
||||
|
||||
/* Must have IP header processed for its length and protocol. */
|
||||
if (!npf_iscached(npc, NPC_IP46) && !npf_fetch_ip(npc, nbuf, n_ptr)) {
|
||||
return false;
|
||||
}
|
||||
if (ip->ip_p != IPPROTO_TCP) {
|
||||
if (npf_cache_ipproto(npc) != IPPROTO_TCP) {
|
||||
return false;
|
||||
}
|
||||
hlen = ip->ip_hl << 2;
|
||||
th = &npc->npc_l4.tcp;
|
||||
|
||||
/* Fetch TCP header. */
|
||||
if (nbuf_advfetch(&nbuf, &n_ptr, hlen, sizeof(struct tcphdr), th)) {
|
||||
if (nbuf_advfetch(&nbuf, &n_ptr, npf_cache_hlen(npc, nbuf), sizeof(struct tcphdr), th)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -297,7 +354,7 @@ npf_fetch_udp(npf_cache_t *npc, nbuf_t *nbuf, void *n_ptr)
|
|||
{
|
||||
struct ip *ip = &npc->npc_ip.v4;
|
||||
struct udphdr *uh;
|
||||
u_int hlen;
|
||||
size_t hlen;
|
||||
|
||||
/* Must have IP header processed for its length and protocol. */
|
||||
if (!npf_iscached(npc, NPC_IP46) && !npf_fetch_ip(npc, nbuf, n_ptr)) {
|
||||
|
@ -306,8 +363,8 @@ npf_fetch_udp(npf_cache_t *npc, nbuf_t *nbuf, void *n_ptr)
|
|||
if (ip->ip_p != IPPROTO_UDP) {
|
||||
return false;
|
||||
}
|
||||
hlen = ip->ip_hl << 2;
|
||||
uh = &npc->npc_l4.udp;
|
||||
hlen = npf_cache_hlen(npc, nbuf);
|
||||
|
||||
/* Fetch ICMP header. */
|
||||
if (nbuf_advfetch(&nbuf, &n_ptr, hlen, sizeof(struct udphdr), uh)) {
|
||||
|
@ -329,7 +386,8 @@ npf_fetch_icmp(npf_cache_t *npc, nbuf_t *nbuf, void *n_ptr)
|
|||
{
|
||||
struct ip *ip = &npc->npc_ip.v4;
|
||||
struct icmp *ic;
|
||||
u_int hlen, iclen;
|
||||
u_int iclen;
|
||||
size_t hlen;
|
||||
|
||||
/* Must have IP header processed for its length and protocol. */
|
||||
if (!npf_iscached(npc, NPC_IP46) && !npf_fetch_ip(npc, nbuf, n_ptr)) {
|
||||
|
@ -338,8 +396,8 @@ npf_fetch_icmp(npf_cache_t *npc, nbuf_t *nbuf, void *n_ptr)
|
|||
if (ip->ip_p != IPPROTO_ICMP) {
|
||||
return false;
|
||||
}
|
||||
hlen = ip->ip_hl << 2;
|
||||
ic = &npc->npc_l4.icmp;
|
||||
hlen = npf_cache_hlen(npc, nbuf);
|
||||
|
||||
/* Fetch basic ICMP header, up to the "data" point. */
|
||||
iclen = offsetof(struct icmp, icmp_data);
|
||||
|
@ -417,8 +475,7 @@ npf_rwrport(npf_cache_t *npc, nbuf_t *nbuf, void *n_ptr, const int di,
|
|||
in_port_t port)
|
||||
{
|
||||
const int proto = npf_cache_ipproto(npc);
|
||||
struct ip *ip = &npc->npc_ip.v4;
|
||||
u_int offby = ip->ip_hl << 2;
|
||||
u_int offby = npf_cache_hlen(npc, nbuf);
|
||||
in_port_t *oport;
|
||||
|
||||
KASSERT(npf_iscached(npc, NPC_TCP) || npf_iscached(npc, NPC_UDP));
|
||||
|
@ -481,7 +538,7 @@ npf_rwrcksum(npf_cache_t *npc, nbuf_t *nbuf, void *n_ptr, const int di,
|
|||
return false;
|
||||
|
||||
ip->ip_sum = ipsum;
|
||||
offby = (ip->ip_hl << 2) - offby;
|
||||
offby = npf_cache_hlen(npc, nbuf) - offby;
|
||||
} else {
|
||||
/* No checksum for IPv6. */
|
||||
KASSERT(npf_iscached(npc, NPC_IP6));
|
||||
|
@ -494,7 +551,7 @@ npf_rwrcksum(npf_cache_t *npc, nbuf_t *nbuf, void *n_ptr, const int di,
|
|||
if (proto == IPPROTO_ICMP || port == 0) {
|
||||
return true;
|
||||
}
|
||||
KASSERT(npf_iscached(npc, NPC_TCP | NPC_UDP));
|
||||
KASSERT(npf_iscached(npc, NPC_TCP) || npf_iscached(npc, NPC_UDP));
|
||||
|
||||
/* Calculate TCP/UDP checksum. */
|
||||
if (proto == IPPROTO_TCP) {
|
||||
|
@ -591,7 +648,6 @@ npf_normalize(npf_cache_t *npc, nbuf_t *nbuf,
|
|||
bool no_df, bool rnd, u_int minttl, u_int maxmss)
|
||||
{
|
||||
void *n_ptr = nbuf_dataptr(nbuf);
|
||||
struct ip *ip = &npc->npc_ip.v4;
|
||||
struct tcphdr *th = &npc->npc_l4.tcp;
|
||||
uint16_t cksum, mss;
|
||||
int offby, wscale;
|
||||
|
@ -631,7 +687,7 @@ npf_normalize(npf_cache_t *npc, nbuf_t *nbuf,
|
|||
if (!npf_fetch_tcpopts(npc, nbuf, &mss, &wscale)) {
|
||||
return false;
|
||||
}
|
||||
offby = (ip->ip_hl << 2) + offsetof(struct tcphdr, th_sum);
|
||||
offby = npf_cache_hlen(npc, nbuf) + offsetof(struct tcphdr, th_sum);
|
||||
if (nbuf_advstore(&nbuf, &n_ptr, offby, sizeof(cksum), &cksum)) {
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: npf_instr.c,v 1.5 2011/01/18 20:33:45 rmind Exp $ */
|
||||
/* $NetBSD: npf_instr.c,v 1.6 2011/11/04 01:00:27 zoltan Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2009-2010 The NetBSD Foundation, Inc.
|
||||
|
@ -34,7 +34,7 @@
|
|||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: npf_instr.c,v 1.5 2011/01/18 20:33:45 rmind Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: npf_instr.c,v 1.6 2011/11/04 01:00:27 zoltan Exp $");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/kernel.h>
|
||||
|
@ -93,11 +93,10 @@ again:
|
|||
* npf_match_ip4table: match IPv4 address against NPF table.
|
||||
*/
|
||||
int
|
||||
npf_match_ip4table(npf_cache_t *npc, nbuf_t *nbuf, void *n_ptr,
|
||||
npf_match_table(npf_cache_t *npc, nbuf_t *nbuf, void *n_ptr,
|
||||
const int sd, const u_int tid)
|
||||
{
|
||||
struct ip *ip = &npc->npc_ip.v4;
|
||||
in_addr_t ip4addr;
|
||||
npf_addr_t *addr;
|
||||
|
||||
if (!npf_iscached(npc, NPC_IP46)) {
|
||||
if (!npf_fetch_ip(npc, nbuf, n_ptr)) {
|
||||
|
@ -105,21 +104,20 @@ npf_match_ip4table(npf_cache_t *npc, nbuf_t *nbuf, void *n_ptr,
|
|||
}
|
||||
KASSERT(npf_iscached(npc, NPC_IP46));
|
||||
}
|
||||
ip4addr = sd ? ip->ip_src.s_addr : ip->ip_dst.s_addr;
|
||||
addr = sd ? npc->npc_srcip : npc->npc_dstip;
|
||||
|
||||
/* Match address against NPF table. */
|
||||
return npf_table_match_v4addr(tid, ip4addr);
|
||||
return npf_table_match_addr(tid, addr);
|
||||
}
|
||||
|
||||
/*
|
||||
* npf_match_ip4mask: match IPv4 address against netaddr/subnet.
|
||||
* npf_match_ipmask: match an address against netaddr/mask.
|
||||
*/
|
||||
int
|
||||
npf_match_ip4mask(npf_cache_t *npc, nbuf_t *nbuf, void *n_ptr,
|
||||
const int sd, in_addr_t netaddr, in_addr_t subnet)
|
||||
npf_match_ipmask(npf_cache_t *npc, nbuf_t *nbuf, void *n_ptr,
|
||||
const int sd, const npf_addr_t *netaddr, npf_netmask_t omask)
|
||||
{
|
||||
struct ip *ip = &npc->npc_ip.v4;
|
||||
in_addr_t ip4addr;
|
||||
npf_addr_t *addr1, addr2;
|
||||
|
||||
if (!npf_iscached(npc, NPC_IP46)) {
|
||||
if (!npf_fetch_ip(npc, nbuf, n_ptr)) {
|
||||
|
@ -127,9 +125,15 @@ npf_match_ip4mask(npf_cache_t *npc, nbuf_t *nbuf, void *n_ptr,
|
|||
}
|
||||
KASSERT(npf_iscached(npc, NPC_IP46));
|
||||
}
|
||||
ip4addr = sd ? ip->ip_src.s_addr : ip->ip_dst.s_addr;
|
||||
if (omask == 0)
|
||||
return 0;
|
||||
|
||||
return (ip4addr & subnet) == netaddr ? 0 : -1;
|
||||
addr1 = sd ? npc->npc_srcip : npc->npc_dstip;
|
||||
npf_calculate_masked_addr(&addr2, netaddr, omask);
|
||||
if (memcmp(addr1, &addr2, npc->npc_ipsz)) {
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: npf_nat.c,v 1.6 2011/02/02 02:20:25 rmind Exp $ */
|
||||
/* $NetBSD: npf_nat.c,v 1.7 2011/11/04 01:00:27 zoltan 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.6 2011/02/02 02:20:25 rmind Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: npf_nat.c,v 1.7 2011/11/04 01:00:27 zoltan Exp $");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/kernel.h>
|
||||
|
@ -419,7 +419,8 @@ npf_nat_create(npf_cache_t *npc, npf_natpolicy_t *np)
|
|||
const int proto = npf_cache_ipproto(npc);
|
||||
npf_nat_t *nt;
|
||||
|
||||
KASSERT(npf_iscached(npc, NPC_IP46 | NPC_LAYER4));
|
||||
KASSERT(npf_iscached(npc, NPC_IP46));
|
||||
KASSERT(npf_iscached(npc, NPC_LAYER4));
|
||||
|
||||
/* New NAT association. */
|
||||
nt = pool_cache_get(nat_cache, PR_NOWAIT);
|
||||
|
@ -531,7 +532,7 @@ npf_nat_translate(npf_cache_t *npc, nbuf_t *nbuf, npf_nat_t *nt,
|
|||
switch (npf_cache_ipproto(npc)) {
|
||||
case IPPROTO_TCP:
|
||||
case IPPROTO_UDP:
|
||||
KASSERT(npf_iscached(npc, NPC_TCP | NPC_UDP));
|
||||
KASSERT(npf_iscached(npc, NPC_TCP) || npf_iscached(npc, NPC_UDP));
|
||||
/* Rewrite source/destination port. */
|
||||
if (!npf_rwrport(npc, nbuf, n_ptr, di, port)) {
|
||||
return EINVAL;
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: npf_ncode.h,v 1.4 2010/12/18 01:07:25 rmind Exp $ */
|
||||
/* $NetBSD: npf_ncode.h,v 1.5 2011/11/04 01:00:27 zoltan Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2009-2010 The NetBSD Foundation, Inc.
|
||||
|
@ -114,8 +114,9 @@ int npf_ncode_validate(const void *, size_t, int *);
|
|||
#define NPF_OPCODE_ETHER 0x80
|
||||
|
||||
#define NPF_OPCODE_IP4MASK 0x90
|
||||
#define NPF_OPCODE_IP4TABLE 0x91
|
||||
#define NPF_OPCODE_TABLE 0x91
|
||||
#define NPF_OPCODE_ICMP4 0x92
|
||||
#define NPF_OPCODE_IP6MASK 0x93
|
||||
|
||||
#define NPF_OPCODE_TCP_PORTS 0xa0
|
||||
#define NPF_OPCODE_UDP_PORTS 0xa1
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: npf_processor.c,v 1.4 2010/12/18 01:07:25 rmind Exp $ */
|
||||
/* $NetBSD: npf_processor.c,v 1.5 2011/11/04 01:00:27 zoltan Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2009-2010 The NetBSD Foundation, Inc.
|
||||
|
@ -54,7 +54,7 @@
|
|||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: npf_processor.c,v 1.4 2010/12/18 01:07:25 rmind Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: npf_processor.c,v 1.5 2011/11/04 01:00:27 zoltan Exp $");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/kernel.h>
|
||||
|
@ -146,6 +146,8 @@ npf_ncode_process(npf_cache_t *npc, const void *ncode,
|
|||
uint32_t regs[NPF_NREGS];
|
||||
/* Local, state variables. */
|
||||
uint32_t d, i, n;
|
||||
npf_addr_t addr;
|
||||
uint32_t mask;
|
||||
u_int lcount;
|
||||
int cmpval;
|
||||
|
||||
|
@ -284,13 +286,20 @@ cisc_like:
|
|||
case NPF_OPCODE_IP4MASK:
|
||||
/* Source/destination, network address, subnet mask. */
|
||||
i_ptr = nc_fetch_word(i_ptr, &d);
|
||||
i_ptr = nc_fetch_double(i_ptr, &n, &i);
|
||||
cmpval = npf_match_ip4mask(npc, nbuf, n_ptr, d, n, i);
|
||||
i_ptr = nc_fetch_double(i_ptr, &addr.s6_addr32[0], &mask);
|
||||
cmpval = npf_match_ipmask(npc, nbuf, n_ptr, d, &addr, (npf_netmask_t)mask);
|
||||
break;
|
||||
case NPF_OPCODE_IP4TABLE:
|
||||
case NPF_OPCODE_IP6MASK:
|
||||
i_ptr = nc_fetch_word(i_ptr, &d);
|
||||
i_ptr = nc_fetch_double(i_ptr, &addr.s6_addr32[0], &addr.s6_addr32[1]);
|
||||
i_ptr = nc_fetch_double(i_ptr, &addr.s6_addr32[2], &addr.s6_addr32[3]);
|
||||
i_ptr = nc_fetch_word(i_ptr, &mask);
|
||||
cmpval = npf_match_ipmask(npc, nbuf, n_ptr, d, &addr, (npf_netmask_t)mask);
|
||||
break;
|
||||
case NPF_OPCODE_TABLE:
|
||||
/* Source/destination, NPF table ID. */
|
||||
i_ptr = nc_fetch_double(i_ptr, &n, &i);
|
||||
cmpval = npf_match_ip4table(npc, nbuf, n_ptr, n, i);
|
||||
cmpval = npf_match_table(npc, nbuf, n_ptr, n, i);
|
||||
break;
|
||||
case NPF_OPCODE_TCP_PORTS:
|
||||
/* Source/destination, port range. */
|
||||
|
@ -441,7 +450,10 @@ jmp_check:
|
|||
case NPF_OPCODE_IP4MASK:
|
||||
error = nc_ptr_check(&iptr, nc, sz, 3, NULL, 0);
|
||||
break;
|
||||
case NPF_OPCODE_IP4TABLE:
|
||||
case NPF_OPCODE_IP6MASK:
|
||||
error = nc_ptr_check(&iptr, nc, sz, 6, NULL, 0);
|
||||
break;
|
||||
case NPF_OPCODE_TABLE:
|
||||
error = nc_ptr_check(&iptr, nc, sz, 2, NULL, 0);
|
||||
break;
|
||||
case NPF_OPCODE_TCP_PORTS:
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: npf_sendpkt.c,v 1.4 2011/01/18 20:33:46 rmind Exp $ */
|
||||
/* $NetBSD: npf_sendpkt.c,v 1.5 2011/11/04 01:00:27 zoltan Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2010 The NetBSD Foundation, Inc.
|
||||
|
@ -34,7 +34,7 @@
|
|||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: npf_sendpkt.c,v 1.4 2011/01/18 20:33:46 rmind Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: npf_sendpkt.c,v 1.5 2011/11/04 01:00:27 zoltan Exp $");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/kernel.h>
|
||||
|
@ -45,6 +45,9 @@ __KERNEL_RCSID(0, "$NetBSD: npf_sendpkt.c,v 1.4 2011/01/18 20:33:46 rmind Exp $"
|
|||
#include <netinet/ip_icmp.h>
|
||||
#include <netinet/ip_var.h>
|
||||
#include <netinet/tcp.h>
|
||||
#include <netinet/ip6.h>
|
||||
#include <netinet/icmp6.h>
|
||||
#include <netinet6/ip6_var.h>
|
||||
#include <sys/mbuf.h>
|
||||
|
||||
#include "npf_impl.h"
|
||||
|
@ -58,16 +61,17 @@ static int
|
|||
npf_return_tcp(npf_cache_t *npc, nbuf_t *nbuf)
|
||||
{
|
||||
struct mbuf *m;
|
||||
struct ip *oip, *ip;
|
||||
struct ip *ip = NULL;
|
||||
struct ip6_hdr *ip6 = NULL;
|
||||
struct tcphdr *oth, *th;
|
||||
tcp_seq seq, ack;
|
||||
int tcpdlen, len;
|
||||
uint32_t win;
|
||||
|
||||
/* Fetch relevant data. */
|
||||
KASSERT(npf_iscached(npc, NPC_IP46 | NPC_LAYER4));
|
||||
tcpdlen = npf_tcpsaw(npc, &seq, &ack, &win);
|
||||
oip = &npc->npc_ip.v4;
|
||||
KASSERT(npf_iscached(npc, NPC_IP46));
|
||||
KASSERT(npf_iscached(npc, NPC_LAYER4));
|
||||
tcpdlen = npf_tcpsaw(npc, nbuf, &seq, &ack, &win);
|
||||
oth = &npc->npc_l4.tcp;
|
||||
|
||||
if (oth->th_flags & TH_RST) {
|
||||
|
@ -75,7 +79,11 @@ npf_return_tcp(npf_cache_t *npc, nbuf_t *nbuf)
|
|||
}
|
||||
|
||||
/* Create and setup a network buffer. */
|
||||
len = sizeof(struct ip) + sizeof(struct tcphdr);
|
||||
if (npc->npc_info & NPC_IP4)
|
||||
len = sizeof(struct ip) + sizeof(struct tcphdr);
|
||||
else
|
||||
len = sizeof(struct ip6_hdr) + sizeof(struct tcphdr);
|
||||
|
||||
m = m_gethdr(M_DONTWAIT, MT_HEADER);
|
||||
if (m == NULL) {
|
||||
return ENOMEM;
|
||||
|
@ -84,20 +92,37 @@ npf_return_tcp(npf_cache_t *npc, nbuf_t *nbuf)
|
|||
m->m_len = len;
|
||||
m->m_pkthdr.len = len;
|
||||
|
||||
ip = mtod(m, struct ip *);
|
||||
memset(ip, 0, len);
|
||||
if (npc->npc_info & NPC_IP4) {
|
||||
struct ip *oip = &npc->npc_ip.v4;
|
||||
ip = mtod(m, struct ip *);
|
||||
memset(ip, 0, len);
|
||||
|
||||
/*
|
||||
* First fill of IPv4 header, for TCP checksum.
|
||||
* Note: IP length contains TCP header length.
|
||||
*/
|
||||
ip->ip_p = IPPROTO_TCP;
|
||||
ip->ip_src.s_addr = oip->ip_dst.s_addr;
|
||||
ip->ip_dst.s_addr = oip->ip_src.s_addr;
|
||||
ip->ip_len = htons(sizeof(struct tcphdr));
|
||||
/*
|
||||
* First fill of IPv4 header, for TCP checksum.
|
||||
* Note: IP length contains TCP header length.
|
||||
*/
|
||||
ip->ip_p = IPPROTO_TCP;
|
||||
ip->ip_src.s_addr = oip->ip_dst.s_addr;
|
||||
ip->ip_dst.s_addr = oip->ip_src.s_addr;
|
||||
ip->ip_len = htons(sizeof(struct tcphdr));
|
||||
|
||||
th = (struct tcphdr *)(ip + 1);
|
||||
} else {
|
||||
struct ip6_hdr *oip = &npc->npc_ip.v6;
|
||||
ip6 = mtod(m, struct ip6_hdr *);
|
||||
memset(ip6, 0, len);
|
||||
|
||||
ip6->ip6_nxt = IPPROTO_TCP;
|
||||
ip6->ip6_hlim = IPV6_DEFHLIM;
|
||||
memcpy(&ip6->ip6_src, &oip->ip6_dst, sizeof(struct in6_addr));
|
||||
memcpy(&ip6->ip6_dst, &oip->ip6_src, sizeof(struct in6_addr));
|
||||
ip6->ip6_plen = htons(len);
|
||||
ip6->ip6_vfc = IPV6_VERSION;
|
||||
|
||||
th = (struct tcphdr *)(ip6 + 1);
|
||||
}
|
||||
|
||||
/* Construct TCP header and compute the checksum. */
|
||||
th = (struct tcphdr *)(ip + 1);
|
||||
th->th_sport = oth->th_dport;
|
||||
th->th_dport = oth->th_sport;
|
||||
th->th_seq = htonl(ack);
|
||||
|
@ -107,33 +132,48 @@ npf_return_tcp(npf_cache_t *npc, nbuf_t *nbuf)
|
|||
th->th_ack = htonl(seq + tcpdlen);
|
||||
th->th_off = sizeof(struct tcphdr) >> 2;
|
||||
th->th_flags = TH_ACK | TH_RST;
|
||||
th->th_sum = in_cksum(m, len);
|
||||
|
||||
/* Second fill of IPv4 header, fill correct IP length. */
|
||||
ip->ip_v = IPVERSION;
|
||||
ip->ip_hl = sizeof(struct ip) >> 2;
|
||||
ip->ip_tos = IPTOS_LOWDELAY;
|
||||
ip->ip_len = htons(len);
|
||||
ip->ip_ttl = DEFAULT_IP_TTL;
|
||||
if (npc->npc_info & NPC_IP4) {
|
||||
th->th_sum = in_cksum(m, len);
|
||||
|
||||
/* Second fill of IPv4 header, fill correct IP length. */
|
||||
ip->ip_v = IPVERSION;
|
||||
ip->ip_hl = sizeof(struct ip) >> 2;
|
||||
ip->ip_tos = IPTOS_LOWDELAY;
|
||||
ip->ip_len = htons(len);
|
||||
ip->ip_ttl = DEFAULT_IP_TTL;
|
||||
} else {
|
||||
th->th_sum = in6_cksum(m, IPPROTO_TCP, sizeof(struct ip6_hdr), sizeof(struct tcphdr));
|
||||
}
|
||||
|
||||
/* Pass to IP layer. */
|
||||
return ip_output(m, NULL, NULL, IP_FORWARDING, NULL, NULL);
|
||||
if (npc->npc_info & NPC_IP4) {
|
||||
return ip_output(m, NULL, NULL, IP_FORWARDING, NULL, NULL);
|
||||
} else {
|
||||
return ip6_output(m, NULL, NULL, IPV6_FORWARDING, NULL, NULL, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* npf_return_icmp: return an ICMP error.
|
||||
*/
|
||||
static int
|
||||
npf_return_icmp(nbuf_t *nbuf)
|
||||
npf_return_icmp(npf_cache_t *npc, nbuf_t *nbuf)
|
||||
{
|
||||
struct mbuf *m = nbuf;
|
||||
|
||||
icmp_error(m, ICMP_UNREACH, ICMP_UNREACH_ADMIN_PROHIBIT, 0, 0);
|
||||
if (npf_iscached(npc, NPC_IP4)) {
|
||||
icmp_error(m, ICMP_UNREACH, ICMP_UNREACH_ADMIN_PROHIBIT, 0, 0);
|
||||
} else {
|
||||
KASSERT(npf_iscached(npc, NPC_IP6));
|
||||
icmp6_error(m, ICMP6_DST_UNREACH, ICMP6_DST_UNREACH_ADMIN, 0);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* npf_return_block: return TCP reset or ICMP host unreachable packet.
|
||||
* TODO: user should be able to specify exact ICMP error codes in config
|
||||
*/
|
||||
void
|
||||
npf_return_block(npf_cache_t *npc, nbuf_t *nbuf, const int retfl)
|
||||
|
@ -154,7 +194,7 @@ npf_return_block(npf_cache_t *npc, nbuf_t *nbuf, const int retfl)
|
|||
break;
|
||||
case IPPROTO_UDP:
|
||||
if (retfl & NPF_RULE_RETICMP) {
|
||||
(void)npf_return_icmp(nbuf);
|
||||
(void)npf_return_icmp(npc, nbuf);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: npf_session.c,v 1.8 2011/02/02 02:20:25 rmind Exp $ */
|
||||
/* $NetBSD: npf_session.c,v 1.9 2011/11/04 01:00:27 zoltan 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.8 2011/02/02 02:20:25 rmind Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: npf_session.c,v 1.9 2011/11/04 01:00:27 zoltan Exp $");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/kernel.h>
|
||||
|
@ -506,7 +506,8 @@ npf_session_establish(const npf_cache_t *npc, nbuf_t *nbuf, const int di)
|
|||
if (!sess_tracking) {
|
||||
return NULL;
|
||||
}
|
||||
KASSERT(npf_iscached(npc, NPC_IP46 | NPC_LAYER4));
|
||||
KASSERT(npf_iscached(npc, NPC_IP46));
|
||||
KASSERT(npf_iscached(npc, NPC_LAYER4));
|
||||
|
||||
/* Allocate and initialise new state. */
|
||||
se = pool_cache_get(sess_cache, PR_NOWAIT);
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: npf_state.c,v 1.4 2011/04/25 22:16:21 yamt Exp $ */
|
||||
/* $NetBSD: npf_state.c,v 1.5 2011/11/04 01:00:27 zoltan Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2010 The NetBSD Foundation, Inc.
|
||||
|
@ -34,7 +34,7 @@
|
|||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: npf_state.c,v 1.4 2011/04/25 22:16:21 yamt Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: npf_state.c,v 1.5 2011/11/04 01:00:27 zoltan Exp $");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
|
@ -85,7 +85,7 @@ npf_tcp_inwindow(const npf_cache_t *npc, nbuf_t *nbuf, npf_state_t *nst,
|
|||
uint32_t win;
|
||||
|
||||
KASSERT(npf_iscached(npc, NPC_TCP));
|
||||
tcpdlen = npf_tcpsaw(__UNCONST(npc), &seq, &ack, &win);
|
||||
tcpdlen = npf_tcpsaw(__UNCONST(npc), nbuf, &seq, &ack, &win);
|
||||
end = seq + tcpdlen;
|
||||
if (tcpfl & TH_SYN) {
|
||||
end++;
|
||||
|
@ -326,7 +326,8 @@ npf_state_init(const npf_cache_t *npc, nbuf_t *nbuf, npf_state_t *nst)
|
|||
{
|
||||
const int proto = npf_cache_ipproto(npc);
|
||||
|
||||
KASSERT(npf_iscached(npc, NPC_IP46 | NPC_LAYER4));
|
||||
KASSERT(npf_iscached(npc, NPC_IP46));
|
||||
KASSERT(npf_iscached(npc, NPC_LAYER4));
|
||||
|
||||
mutex_init(&nst->nst_lock, MUTEX_DEFAULT, IPL_SOFTNET);
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: npf_tableset.c,v 1.5 2011/02/02 02:20:25 rmind Exp $ */
|
||||
/* $NetBSD: npf_tableset.c,v 1.6 2011/11/04 01:00:27 zoltan 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.5 2011/02/02 02:20:25 rmind Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: npf_tableset.c,v 1.6 2011/11/04 01:00:27 zoltan Exp $");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/kernel.h>
|
||||
|
@ -63,8 +63,8 @@ struct npf_tblent {
|
|||
rb_node_t rbnode;
|
||||
} te_entry;
|
||||
/* IPv4 CIDR block. */
|
||||
in_addr_t te_addr;
|
||||
in_addr_t te_mask;
|
||||
npf_addr_t te_addr;
|
||||
npf_netmask_t te_mask;
|
||||
};
|
||||
|
||||
LIST_HEAD(npf_hashl, npf_tblent);
|
||||
|
@ -163,28 +163,18 @@ table_rbtree_cmp_nodes(void *ctx, const void *n1, const void *n2)
|
|||
{
|
||||
const npf_tblent_t * const te1 = n1;
|
||||
const npf_tblent_t * const te2 = n2;
|
||||
const in_addr_t x = te1->te_addr & te1->te_mask;
|
||||
const in_addr_t y = te2->te_addr & te2->te_mask;
|
||||
|
||||
if (x < y)
|
||||
return -1;
|
||||
if (x > y)
|
||||
return 1;
|
||||
return 0;
|
||||
return npf_compare_cidr(&te1->te_addr, te1->te_mask,
|
||||
&te2->te_addr, te2->te_mask);
|
||||
}
|
||||
|
||||
static signed int
|
||||
table_rbtree_cmp_key(void *ctx, const void *n1, const void *key)
|
||||
{
|
||||
const npf_tblent_t * const te = n1;
|
||||
const in_addr_t x = te->te_addr & te->te_mask;
|
||||
const in_addr_t y = *(const in_addr_t *)key;
|
||||
const npf_addr_t *t2 = key;
|
||||
|
||||
if (x < y)
|
||||
return -1;
|
||||
if (x > y)
|
||||
return 1;
|
||||
return 0;
|
||||
return npf_compare_cidr(&te->te_addr, te->te_mask, t2, NPF_NO_NETMASK);
|
||||
}
|
||||
|
||||
static const rb_tree_ops_t table_rbtree_ops = {
|
||||
|
@ -199,7 +189,7 @@ static const rb_tree_ops_t table_rbtree_ops = {
|
|||
*/
|
||||
|
||||
static inline struct npf_hashl *
|
||||
table_hash_bucket(npf_table_t *t, void *buf, size_t sz)
|
||||
table_hash_bucket(npf_table_t *t, const void *buf, size_t sz)
|
||||
{
|
||||
const uint32_t hidx = hash32_buf(buf, sz, HASH32_BUF_INIT);
|
||||
|
||||
|
@ -348,21 +338,21 @@ npf_table_check(npf_tableset_t *tset, u_int tid, int type)
|
|||
}
|
||||
|
||||
/*
|
||||
* npf_table_add_v4cidr: add an IPv4 CIDR into the table.
|
||||
* npf_table_add_cidr: add an IPv4 or IPv6 CIDR into the table.
|
||||
*/
|
||||
int
|
||||
npf_table_add_v4cidr(npf_tableset_t *tset, u_int tid,
|
||||
in_addr_t addr, in_addr_t mask)
|
||||
npf_table_add_cidr(npf_tableset_t *tset, u_int tid,
|
||||
const npf_addr_t *addr, const npf_netmask_t mask)
|
||||
{
|
||||
struct npf_hashl *htbl;
|
||||
npf_tblent_t *e, *it;
|
||||
npf_table_t *t;
|
||||
in_addr_t val;
|
||||
npf_addr_t val;
|
||||
int error = 0;
|
||||
|
||||
/* Allocate and setup entry. */
|
||||
e = pool_cache_get(tblent_cache, PR_WAITOK);
|
||||
e->te_addr = addr;
|
||||
memcpy(&e->te_addr, addr, sizeof(npf_addr_t));
|
||||
e->te_mask = mask;
|
||||
|
||||
/* Locks the table. */
|
||||
|
@ -374,12 +364,19 @@ npf_table_add_v4cidr(npf_tableset_t *tset, u_int tid,
|
|||
switch (t->t_type) {
|
||||
case NPF_TABLE_HASH:
|
||||
/* Generate hash value from: address & mask. */
|
||||
val = addr & mask;
|
||||
htbl = table_hash_bucket(t, &val, sizeof(in_addr_t));
|
||||
npf_calculate_masked_addr(&val, addr, mask);
|
||||
htbl = table_hash_bucket(t, &val, sizeof(npf_addr_t));
|
||||
/* Lookup to check for duplicates. */
|
||||
LIST_FOREACH(it, htbl, te_entry.hashq) {
|
||||
if (it->te_addr == addr && it->te_mask == mask)
|
||||
break;
|
||||
if (it->te_mask == mask) {
|
||||
const uint32_t *addr1 = it->te_addr.s6_addr32;
|
||||
const uint32_t *addr2 = addr->s6_addr32;
|
||||
const size_t len = sizeof(npf_addr_t);
|
||||
|
||||
if (memcmp(addr1, addr2, len) == 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
/* If no duplicate - insert entry. */
|
||||
if (__predict_true(it == NULL)) {
|
||||
|
@ -409,13 +406,13 @@ npf_table_add_v4cidr(npf_tableset_t *tset, u_int tid,
|
|||
* npf_table_rem_v4cidr: remove an IPv4 CIDR from the table.
|
||||
*/
|
||||
int
|
||||
npf_table_rem_v4cidr(npf_tableset_t *tset, u_int tid,
|
||||
in_addr_t addr, in_addr_t mask)
|
||||
npf_table_rem_cidr(npf_tableset_t *tset, u_int tid,
|
||||
const npf_addr_t *addr, const npf_netmask_t mask)
|
||||
{
|
||||
struct npf_hashl *htbl;
|
||||
npf_tblent_t *e;
|
||||
npf_table_t *t;
|
||||
in_addr_t val;
|
||||
npf_addr_t val;
|
||||
int error;
|
||||
|
||||
e = NULL;
|
||||
|
@ -429,11 +426,18 @@ npf_table_rem_v4cidr(npf_tableset_t *tset, u_int tid,
|
|||
switch (t->t_type) {
|
||||
case NPF_TABLE_HASH:
|
||||
/* Generate hash value from: (address & mask). */
|
||||
val = addr & mask;
|
||||
htbl = table_hash_bucket(t, &val, sizeof(in_addr_t));
|
||||
npf_calculate_masked_addr(&val, addr, mask);
|
||||
htbl = table_hash_bucket(t, &val, sizeof(npf_addr_t));
|
||||
LIST_FOREACH(e, htbl, te_entry.hashq) {
|
||||
if (e->te_addr == addr && e->te_mask == mask)
|
||||
break;
|
||||
if (e->te_mask == mask) {
|
||||
const uint32_t *addr1 = e->te_addr.s6_addr32;
|
||||
const uint32_t *addr2 = addr->s6_addr32;
|
||||
const size_t len = sizeof(npf_addr_t);
|
||||
|
||||
if (memcmp(addr1, addr2, len) == 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (__predict_true(e != NULL)) {
|
||||
LIST_REMOVE(e, te_entry.hashq);
|
||||
|
@ -443,7 +447,7 @@ npf_table_rem_v4cidr(npf_tableset_t *tset, u_int tid,
|
|||
break;
|
||||
case NPF_TABLE_RBTREE:
|
||||
/* Key: (address & mask). */
|
||||
val = addr & mask;
|
||||
npf_calculate_masked_addr(&val, addr, mask);
|
||||
e = rb_tree_find_node(&t->t_rbtree, &val);
|
||||
if (__predict_true(e != NULL)) {
|
||||
rb_tree_remove_node(&t->t_rbtree, e);
|
||||
|
@ -464,11 +468,11 @@ npf_table_rem_v4cidr(npf_tableset_t *tset, u_int tid,
|
|||
}
|
||||
|
||||
/*
|
||||
* npf_table_match_v4addr: find the table according to ID, lookup and
|
||||
* npf_table_match_addr: find the table according to ID, lookup and
|
||||
* match the contents with specified IPv4 address.
|
||||
*/
|
||||
int
|
||||
npf_table_match_v4addr(u_int tid, in_addr_t ip4addr)
|
||||
npf_table_match_addr(u_int tid, const npf_addr_t *addr)
|
||||
{
|
||||
struct npf_hashl *htbl;
|
||||
npf_tblent_t *e = NULL;
|
||||
|
@ -481,16 +485,17 @@ npf_table_match_v4addr(u_int tid, in_addr_t ip4addr)
|
|||
}
|
||||
switch (t->t_type) {
|
||||
case NPF_TABLE_HASH:
|
||||
htbl = table_hash_bucket(t, &ip4addr, sizeof(in_addr_t));
|
||||
htbl = table_hash_bucket(t, addr, sizeof(npf_addr_t));
|
||||
LIST_FOREACH(e, htbl, te_entry.hashq) {
|
||||
if ((ip4addr & e->te_mask) == e->te_addr) {
|
||||
break;
|
||||
}
|
||||
if (npf_compare_cidr(addr, e->te_mask, &e->te_addr, NPF_NO_NETMASK) == 0)
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case NPF_TABLE_RBTREE:
|
||||
e = rb_tree_find_node(&t->t_rbtree, &ip4addr);
|
||||
KASSERT((ip4addr & e->te_mask) == e->te_addr);
|
||||
e = rb_tree_find_node(&t->t_rbtree, addr);
|
||||
if (e != NULL) {
|
||||
KASSERT(npf_compare_cidr(addr, e->te_mask, &e->te_addr, NPF_NO_NETMASK) == 0);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
KASSERT(false);
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: npf_data.c,v 1.7 2011/02/02 02:20:25 rmind Exp $ */
|
||||
/* $NetBSD: npf_data.c,v 1.8 2011/11/04 01:00:28 zoltan Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2009-2011 The NetBSD Foundation, Inc.
|
||||
|
@ -31,7 +31,7 @@
|
|||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__RCSID("$NetBSD: npf_data.c,v 1.7 2011/02/02 02:20:25 rmind Exp $");
|
||||
__RCSID("$NetBSD: npf_data.c,v 1.8 2011/11/04 01:00:28 zoltan Exp $");
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
|
@ -86,14 +86,14 @@ npfctl_ioctl_send(int fd)
|
|||
*/
|
||||
|
||||
struct ifaddrs *
|
||||
npfctl_getif(char *ifname, unsigned int *if_idx, bool reqaddr)
|
||||
npfctl_getif(char *ifname, unsigned int *if_idx, bool reqaddr, sa_family_t addrtype)
|
||||
{
|
||||
struct ifaddrs *ifent;
|
||||
struct sockaddr_in *sin;
|
||||
|
||||
for (ifent = ifs_list; ifent != NULL; ifent = ifent->ifa_next) {
|
||||
sin = (struct sockaddr_in *)ifent->ifa_addr;
|
||||
if (sin->sin_family != AF_INET && reqaddr)
|
||||
if (sin->sin_family != addrtype && reqaddr)
|
||||
continue;
|
||||
if (strcmp(ifent->ifa_name, ifname) == 0)
|
||||
break;
|
||||
|
@ -104,27 +104,6 @@ npfctl_getif(char *ifname, unsigned int *if_idx, bool reqaddr)
|
|||
return ifent;
|
||||
}
|
||||
|
||||
bool
|
||||
npfctl_parse_v4mask(char *ostr, in_addr_t *addr, in_addr_t *mask)
|
||||
{
|
||||
char *str = xstrdup(ostr);
|
||||
char *p = strchr(str, '/');
|
||||
u_int bits;
|
||||
bool ret;
|
||||
|
||||
/* In network byte order. */
|
||||
if (p) {
|
||||
*p++ = '\0';
|
||||
bits = (u_int)atoi(p);
|
||||
*mask = bits ? htonl(0xffffffff << (32 - bits)) : 0;
|
||||
} else {
|
||||
*mask = 0xffffffff;
|
||||
}
|
||||
ret = inet_aton(str, (struct in_addr *)addr) != 0;
|
||||
free(str);
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool
|
||||
npfctl_parse_port(char *ostr, bool *range, in_port_t *fport, in_port_t *tport)
|
||||
{
|
||||
|
@ -154,29 +133,90 @@ npfctl_parse_port(char *ostr, bool *range, in_port_t *fport, in_port_t *tport)
|
|||
}
|
||||
|
||||
void
|
||||
npfctl_parse_cidr(char *str, in_addr_t *addr, in_addr_t *mask)
|
||||
npfctl_create_mask(sa_family_t family, u_int length, npf_addr_t *omask)
|
||||
{
|
||||
uint32_t part;
|
||||
uint32_t *mask = (uint32_t*)omask;
|
||||
|
||||
memset(omask, 0, sizeof(npf_addr_t));
|
||||
if (family == AF_INET) {
|
||||
part = htonl(0xffffffff << (32 - length));
|
||||
memcpy(mask, &part, 4);
|
||||
} else if (family == AF_INET6) {
|
||||
while (length > 32) {
|
||||
part = htonl(0xffffffff);
|
||||
memcpy(mask, &part, 4);
|
||||
mask += 1;
|
||||
length -= 32;
|
||||
}
|
||||
part = htonl(0xffffffff << (32 - length));
|
||||
memcpy(mask, &part, 4);
|
||||
}
|
||||
}
|
||||
|
||||
sa_family_t
|
||||
npfctl_get_addrfamily(const char *ostr)
|
||||
{
|
||||
struct addrinfo hint, *res = NULL;
|
||||
int ret;
|
||||
char *str = xstrdup(ostr);
|
||||
char *p = strchr(str, '/');
|
||||
sa_family_t family;
|
||||
|
||||
if (p)
|
||||
*p = '\0';
|
||||
memset(&hint, '\0', sizeof(hint));
|
||||
hint.ai_family = PF_UNSPEC;
|
||||
hint.ai_flags = AI_NUMERICHOST;
|
||||
ret = getaddrinfo(str, NULL, &hint, &res);
|
||||
if (ret) {
|
||||
family = AF_UNSPEC;
|
||||
} else {
|
||||
family = res->ai_family;
|
||||
}
|
||||
freeaddrinfo(res);
|
||||
free(str);
|
||||
return family;
|
||||
}
|
||||
|
||||
sa_family_t
|
||||
npfctl_parse_cidr(char *str, sa_family_t addrfamily, npf_addr_t *addr, npf_netmask_t *mask)
|
||||
{
|
||||
|
||||
if (strcmp(str, "any") == 0) {
|
||||
*addr = 0x0;
|
||||
*mask = 0x0;
|
||||
|
||||
memset(addr, 0, sizeof(npf_addr_t));
|
||||
memset(mask, 0, sizeof(npf_netmask_t));
|
||||
} else if (isalpha((unsigned char)*str)) {
|
||||
/* TODO: handle multiple addresses per interface */
|
||||
struct ifaddrs *ifa;
|
||||
struct sockaddr_in *sin;
|
||||
u_int idx;
|
||||
|
||||
if ((ifa = npfctl_getif(str, &idx, true)) == NULL) {
|
||||
if ((ifa = npfctl_getif(str, &idx, true, AF_INET)) == NULL) {
|
||||
errx(EXIT_FAILURE, "invalid interface '%s'", str);
|
||||
}
|
||||
/* Interface address. */
|
||||
sin = (struct sockaddr_in *)ifa->ifa_addr;
|
||||
*addr = sin->sin_addr.s_addr;
|
||||
*mask = 0xffffffff;
|
||||
|
||||
} else if (!npfctl_parse_v4mask(str, addr, mask)) {
|
||||
errx(EXIT_FAILURE, "invalid CIDR '%s'\n", str);
|
||||
memcpy(addr, &(sin->sin_addr.s_addr), sizeof(struct in_addr));
|
||||
//v4mask = 0xffffffff; - TODO!
|
||||
} else {
|
||||
char *p = strchr(str, '/');
|
||||
if (p != NULL) {
|
||||
*p++ = '\0';
|
||||
*mask = atoi(p);
|
||||
} else {
|
||||
if (addrfamily == AF_INET)
|
||||
*mask = 32;
|
||||
else
|
||||
*mask = 128;
|
||||
}
|
||||
memset(addr, 0, sizeof(npf_addr_t));
|
||||
int ret = inet_pton(addrfamily, str, addr);
|
||||
if (ret != 1) {
|
||||
printf("TODO: error");
|
||||
}
|
||||
}
|
||||
|
||||
return addrfamily;
|
||||
}
|
||||
|
||||
static bool
|
||||
|
@ -228,18 +268,18 @@ npfctl_fill_table(nl_table_t *tl, char *fname)
|
|||
l = 1;
|
||||
buf = NULL;
|
||||
while (getline(&buf, &n, fp) != -1) {
|
||||
in_addr_t addr, mask;
|
||||
npf_addr_t addr;
|
||||
npf_netmask_t mask;
|
||||
|
||||
if (*buf == '\n' || *buf == '#')
|
||||
continue;
|
||||
|
||||
/* IPv4 CIDR: a.b.c.d/mask */
|
||||
if (!npfctl_parse_v4mask(buf, &addr, &mask)) {
|
||||
if (!npfctl_parse_cidr(buf, npfctl_get_addrfamily(buf), &addr, &mask)) {
|
||||
errx(EXIT_FAILURE, "invalid table entry at line %d", l);
|
||||
}
|
||||
|
||||
/* Create and add table entry. */
|
||||
npf_table_add_entry(tl, addr, mask);
|
||||
npf_table_add_entry(tl, &addr, mask);
|
||||
l++;
|
||||
}
|
||||
if (buf != NULL) {
|
||||
|
@ -252,7 +292,7 @@ npfctl_fill_table(nl_table_t *tl, char *fname)
|
|||
*/
|
||||
|
||||
static void
|
||||
npfctl_rulenc_v4cidr(void **nc, int nblocks[], var_t *dat, bool sd)
|
||||
npfctl_rulenc_cidr(void **nc, int nblocks[], var_t *dat, bool sd, sa_family_t addrfamily)
|
||||
{
|
||||
element_t *el = dat->v_elements;
|
||||
int foff;
|
||||
|
@ -267,15 +307,21 @@ npfctl_rulenc_v4cidr(void **nc, int nblocks[], var_t *dat, bool sd)
|
|||
return;
|
||||
}
|
||||
|
||||
/* Generate v4 CIDR matching blocks. */
|
||||
/* Generate v4/v6 CIDR matching blocks. */
|
||||
for (el = dat->v_elements; el != NULL; el = el->e_next) {
|
||||
in_addr_t addr, mask;
|
||||
npf_addr_t addr;
|
||||
npf_netmask_t mask;
|
||||
|
||||
npfctl_parse_cidr(el->e_data, &addr, &mask);
|
||||
|
||||
nblocks[1]--;
|
||||
npfctl_parse_cidr(el->e_data, addrfamily, &addr, &mask);
|
||||
if (addrfamily == AF_INET)
|
||||
nblocks[1]--;
|
||||
else if (addrfamily == AF_INET6)
|
||||
nblocks[3]--;
|
||||
foff = npfctl_failure_offset(nblocks);
|
||||
npfctl_gennc_v4cidr(nc, foff, addr, mask, sd);
|
||||
if (addrfamily == AF_INET)
|
||||
npfctl_gennc_v4cidr(nc, foff, &addr, mask, sd);
|
||||
else if (addrfamily == AF_INET6)
|
||||
npfctl_gennc_v6cidr(nc, foff, &addr, mask, sd);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -304,10 +350,10 @@ npfctl_rulenc_ports(void **nc, int nblocks[], var_t *dat, bool tcpudp,
|
|||
|
||||
static void
|
||||
npfctl_rulenc_block(void **nc, int nblocks[], var_t *cidr, var_t *ports,
|
||||
bool both, bool tcpudp, bool sd)
|
||||
bool both, bool tcpudp, bool sd, sa_family_t addrfamily)
|
||||
{
|
||||
|
||||
npfctl_rulenc_v4cidr(nc, nblocks, cidr, sd);
|
||||
npfctl_rulenc_cidr(nc, nblocks, cidr, sd, addrfamily);
|
||||
if (ports == NULL) {
|
||||
return;
|
||||
}
|
||||
|
@ -320,9 +366,9 @@ npfctl_rulenc_block(void **nc, int nblocks[], var_t *cidr, var_t *ports,
|
|||
|
||||
void
|
||||
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)
|
||||
int icmp_code, var_t *from, sa_family_t addrfamily, var_t *fports, var_t *to, var_t *tports)
|
||||
{
|
||||
int nblocks[3] = { 0, 0, 0 };
|
||||
int nblocks[4] = { 0, 0, 0, 0 };
|
||||
bool icmp, tcpudp, both;
|
||||
void *ncptr, *nc;
|
||||
size_t sz, foff;
|
||||
|
@ -370,22 +416,30 @@ skip_proto:
|
|||
if (from && from->v_count) {
|
||||
if (from->v_type == VAR_TABLE)
|
||||
nblocks[0] += 1;
|
||||
else
|
||||
nblocks[1] += from->v_count;
|
||||
else {
|
||||
if (addrfamily == AF_INET)
|
||||
nblocks[1] += from->v_count;
|
||||
else
|
||||
nblocks[3] += from->v_count;
|
||||
}
|
||||
if (fports && fports->v_count)
|
||||
nblocks[0] += fports->v_count * (both ? 2 : 1);
|
||||
}
|
||||
if (to && to->v_count) {
|
||||
if (to->v_type == VAR_TABLE)
|
||||
nblocks[0] += 1;
|
||||
else
|
||||
nblocks[1] += to->v_count;
|
||||
else {
|
||||
if (addrfamily == AF_INET)
|
||||
nblocks[1] += to->v_count;
|
||||
else
|
||||
nblocks[3] += to->v_count;
|
||||
}
|
||||
if (tports && tports->v_count)
|
||||
nblocks[0] += tports->v_count * (both ? 2 : 1);
|
||||
}
|
||||
|
||||
/* Any n-code to generate? */
|
||||
if (!icmp && (nblocks[0] + nblocks[1] + nblocks[2]) == 0) {
|
||||
if (!icmp && (nblocks[0] + nblocks[1] + nblocks[2] + nblocks[3]) == 0) {
|
||||
/* Done, if none. */
|
||||
return;
|
||||
}
|
||||
|
@ -399,15 +453,15 @@ skip_proto:
|
|||
nc = ncptr;
|
||||
|
||||
/*
|
||||
* Generate v4 CIDR matching blocks and TCP/UDP port matching.
|
||||
* Generate v4/v6 CIDR matching blocks and TCP/UDP port matching.
|
||||
*/
|
||||
if (from) {
|
||||
npfctl_rulenc_block(&nc, nblocks, from, fports,
|
||||
both, tcpudp, true);
|
||||
both, tcpudp, true, addrfamily);
|
||||
}
|
||||
if (to) {
|
||||
npfctl_rulenc_block(&nc, nblocks, to, tports,
|
||||
both, tcpudp, false);
|
||||
both, tcpudp, false, addrfamily);
|
||||
}
|
||||
|
||||
if (icmp) {
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: npf_ncgen.c,v 1.4 2010/12/18 01:07:26 rmind Exp $ */
|
||||
/* $NetBSD: npf_ncgen.c,v 1.5 2011/11/04 01:00:28 zoltan Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2009-2010 The NetBSD Foundation, Inc.
|
||||
|
@ -37,9 +37,10 @@
|
|||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__RCSID("$NetBSD: npf_ncgen.c,v 1.4 2010/12/18 01:07:26 rmind Exp $");
|
||||
__RCSID("$NetBSD: npf_ncgen.c,v 1.5 2011/11/04 01:00:28 zoltan Exp $");
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "npfctl.h"
|
||||
|
||||
|
@ -54,11 +55,13 @@ npfctl_calc_ncsize(int nblocks[])
|
|||
* - 5 words each by npfctl_gennc_ports/tbl(), stored in nblocks[0].
|
||||
* - 6 words each by npfctl_gennc_v4cidr(), stored in nblocks[1].
|
||||
* - 4 words by npfctl_gennc_{icmp,tcpfl}(), stored in nblocks[2].
|
||||
* - 9 words each by npfctl_gennc_v6cidr(), stored in nblocks[3].
|
||||
* - 4 words by npfctl_gennc_complete(), single last fragment.
|
||||
*/
|
||||
return nblocks[0] * 5 * sizeof(uint32_t) +
|
||||
nblocks[1] * 6 * sizeof(uint32_t) +
|
||||
nblocks[2] * 4 * sizeof(uint32_t) +
|
||||
nblocks[3] * 9 * sizeof(uint32_t) +
|
||||
4 * sizeof(uint32_t);
|
||||
}
|
||||
|
||||
|
@ -68,7 +71,7 @@ npfctl_calc_ncsize(int nblocks[])
|
|||
size_t
|
||||
npfctl_failure_offset(int nblocks[])
|
||||
{
|
||||
size_t tblport_blocks, v4cidr_blocks, icmp_tcpfl;
|
||||
size_t tblport_blocks, v4cidr_blocks, v6cidr_blocks, icmp_tcpfl;
|
||||
/*
|
||||
* Take into account all blocks (plus 2 words for comparison each),
|
||||
* and additional 4 words to skip the last comparison and success path.
|
||||
|
@ -76,7 +79,8 @@ npfctl_failure_offset(int nblocks[])
|
|||
tblport_blocks = (3 + 2) * nblocks[0];
|
||||
v4cidr_blocks = (4 + 2) * nblocks[1];
|
||||
icmp_tcpfl = (2 + 2) * nblocks[2];
|
||||
return tblport_blocks + v4cidr_blocks + icmp_tcpfl + 4;
|
||||
v6cidr_blocks = (7 + 2) * nblocks[3];
|
||||
return tblport_blocks + v4cidr_blocks + v6cidr_blocks + icmp_tcpfl + 4;
|
||||
}
|
||||
|
||||
#if 0
|
||||
|
@ -115,20 +119,46 @@ npfctl_gennc_ether(void **ncptr, int foff, uint16_t ethertype)
|
|||
}
|
||||
#endif
|
||||
|
||||
void
|
||||
npfctl_gennc_v6cidr(void **ncptr, int foff,
|
||||
const npf_addr_t *netaddr, const npf_netmask_t mask, bool sd)
|
||||
{
|
||||
uint32_t *nc = *ncptr;
|
||||
const uint32_t *addr = (const uint32_t *)netaddr;
|
||||
|
||||
/* OP, direction, netaddr/subnet (10 words) */
|
||||
*nc++ = NPF_OPCODE_IP6MASK;
|
||||
*nc++ = (sd ? 0x01 : 0x00);
|
||||
*nc++ = addr[0];
|
||||
*nc++ = addr[1];
|
||||
*nc++ = addr[2];
|
||||
*nc++ = addr[3];
|
||||
*nc++ = mask;
|
||||
|
||||
/* If not equal, jump to failure block, continue otherwise (2 words). */
|
||||
*nc++ = NPF_OPCODE_BNE;
|
||||
*nc++ = foff;
|
||||
|
||||
/* + 9 words. */
|
||||
*ncptr = (void *)nc;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* npfctl_gennc_v4cidr: fragment to match IPv4 CIDR.
|
||||
*/
|
||||
void
|
||||
npfctl_gennc_v4cidr(void **ncptr, int foff,
|
||||
in_addr_t netaddr, in_addr_t subnet, bool sd)
|
||||
const npf_addr_t *netaddr, const npf_netmask_t mask, bool sd)
|
||||
{
|
||||
uint32_t *nc = *ncptr;
|
||||
const uint32_t *addr = (const uint32_t *)netaddr;
|
||||
|
||||
/* OP, direction, netaddr/subnet (4 words) */
|
||||
*nc++ = NPF_OPCODE_IP4MASK;
|
||||
*nc++ = (sd ? 0x01 : 0x00);
|
||||
*nc++ = netaddr;
|
||||
*nc++ = subnet;
|
||||
*nc++ = addr[0];
|
||||
*nc++ = mask;
|
||||
|
||||
/* If not equal, jump to failure block, continue otherwise (2 words). */
|
||||
*nc++ = NPF_OPCODE_BNE;
|
||||
|
@ -200,7 +230,7 @@ npfctl_gennc_tbl(void **ncptr, int foff, u_int tid, bool sd)
|
|||
uint32_t *nc = *ncptr;
|
||||
|
||||
/* OP, direction, table ID (3 words). */
|
||||
*nc++ = NPF_OPCODE_IP4TABLE;
|
||||
*nc++ = NPF_OPCODE_TABLE;
|
||||
*nc++ = (sd ? 0x01 : 0x00);
|
||||
*nc++ = tid;
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: npf_parser.c,v 1.6 2011/02/02 02:20:25 rmind Exp $ */
|
||||
/* $NetBSD: npf_parser.c,v 1.7 2011/11/04 01:00:28 zoltan Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2009-2011 The NetBSD Foundation, Inc.
|
||||
|
@ -31,7 +31,7 @@
|
|||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__RCSID("$NetBSD: npf_parser.c,v 1.6 2011/02/02 02:20:25 rmind Exp $");
|
||||
__RCSID("$NetBSD: npf_parser.c,v 1.7 2011/11/04 01:00:28 zoltan Exp $");
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
@ -161,7 +161,9 @@ npfctl_val_interface(var_t *v, char *p, bool reqaddr)
|
|||
char *iface = npfctl_val_single(v, p);
|
||||
u_int if_idx;
|
||||
|
||||
if (iface == NULL || npfctl_getif(iface, &if_idx, reqaddr) == NULL) {
|
||||
if (iface == NULL ||
|
||||
((npfctl_getif(iface, &if_idx, reqaddr, AF_INET) == NULL) &&
|
||||
(npfctl_getif(iface, &if_idx, reqaddr, AF_INET6) == NULL))) {
|
||||
errx(EXIT_FAILURE, "invalid interface '%s'", iface);
|
||||
}
|
||||
return if_idx;
|
||||
|
@ -269,6 +271,7 @@ npfctl_parserule(char *buf, nl_rule_t *parent)
|
|||
u_int if_idx = 0;
|
||||
int ret, attr = 0;
|
||||
nl_rule_t *rl;
|
||||
sa_family_t addrfamily = AF_UNSPEC;
|
||||
|
||||
DPRINTF(("rule\t|%s|\n", buf));
|
||||
|
||||
|
@ -324,10 +327,11 @@ npfctl_parserule(char *buf, nl_rule_t *parent)
|
|||
PARSE_NEXT_TOKEN();
|
||||
}
|
||||
|
||||
/* inet, inet6 (TODO) */
|
||||
if (strcmp(p, "inet") == 0) {
|
||||
addrfamily = AF_INET;
|
||||
PARSE_NEXT_TOKEN();
|
||||
} else if (strcmp(p, "inet6") == 0) {
|
||||
addrfamily = AF_INET6;
|
||||
PARSE_NEXT_TOKEN();
|
||||
}
|
||||
|
||||
|
@ -361,6 +365,8 @@ npfctl_parserule(char *buf, nl_rule_t *parent)
|
|||
/* from <addr> port <port | range> */
|
||||
if (strcmp(p, "from") == 0) {
|
||||
PARSE_NEXT_TOKEN();
|
||||
if (addrfamily == AF_UNSPEC)
|
||||
addrfamily = npfctl_get_addrfamily(p);
|
||||
from_v = npfctl_parsevalue(p);
|
||||
|
||||
PARSE_NEXT_TOKEN_NOCHECK();
|
||||
|
@ -375,6 +381,8 @@ npfctl_parserule(char *buf, nl_rule_t *parent)
|
|||
/* to <addr> port <port | range> */
|
||||
if (p && strcmp(p, "to") == 0) {
|
||||
PARSE_NEXT_TOKEN();
|
||||
if (addrfamily == AF_UNSPEC)
|
||||
addrfamily = npfctl_get_addrfamily(p);
|
||||
to_v = npfctl_parsevalue(p);
|
||||
|
||||
PARSE_NEXT_TOKEN_NOCHECK();
|
||||
|
@ -454,7 +462,7 @@ last:
|
|||
*/
|
||||
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);
|
||||
from_v, addrfamily, fports, to_v, tports);
|
||||
if (rproc && npf_rule_setproc(npf_conf, rl, rproc) != 0) {
|
||||
errx(EXIT_FAILURE, "procedure '%s' is not defined", rproc);
|
||||
}
|
||||
|
@ -574,19 +582,16 @@ npfctl_parsetable(char *buf)
|
|||
return PARSE_ERR();
|
||||
}
|
||||
PARSE_NEXT_TOKEN_NOCHECK();
|
||||
if (p == NULL || *p != '"') {
|
||||
if (p == NULL) {
|
||||
return PARSE_ERR();
|
||||
}
|
||||
if (strcmp(p, "hash")) {
|
||||
if (strcmp(p, "hash") == 0) {
|
||||
type = NPF_TABLE_HASH;
|
||||
} else if (strcmp(p, "tree")) {
|
||||
} else if (strcmp(p, "tree") == 0) {
|
||||
type = NPF_TABLE_RBTREE;
|
||||
} else {
|
||||
errx(EXIT_FAILURE, "invalid table type '%s'", p);
|
||||
}
|
||||
if ((p = strchr(++p, '"')) == NULL) {
|
||||
return PARSE_ERR();
|
||||
}
|
||||
*p = '\0';
|
||||
|
||||
/*
|
||||
|
@ -631,8 +636,8 @@ npfctl_parse_nat(char *buf)
|
|||
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;
|
||||
npf_netmask_t dummy;
|
||||
bool binat, rdr;
|
||||
nl_nat_t *nat;
|
||||
u_int if_idx;
|
||||
|
@ -702,8 +707,7 @@ npfctl_parse_nat(char *buf)
|
|||
PARSE_NEXT_TOKEN();
|
||||
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 */
|
||||
npfctl_parse_cidr(raddr_s, npfctl_get_addrfamily(raddr_s), &raddr, &dummy);
|
||||
|
||||
if (rdr) {
|
||||
PARSE_NEXT_TOKEN();
|
||||
|
@ -739,7 +743,7 @@ npfctl_parse_nat(char *buf)
|
|||
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);
|
||||
npfctl_rule_ncode(nat, NULL, NULL, -1, -1, from_v, AF_INET, NULL, to_v, tports);
|
||||
(void)npf_nat_insert(npf_conf, nat, NPF_PRI_NEXT);
|
||||
|
||||
/*
|
||||
|
@ -751,15 +755,13 @@ npfctl_parse_nat(char *buf)
|
|||
*/
|
||||
if (binat) {
|
||||
char *taddr_s = npfctl_val_single(from_v, NULL);
|
||||
in_addr_t taddr4;
|
||||
npf_addr_t taddr;
|
||||
nl_nat_t *bn;
|
||||
|
||||
npfctl_parse_cidr(taddr_s, &taddr4, &_dummy);
|
||||
memcpy(&taddr, &taddr4, sizeof(struct in_addr)); /* XXX IPv6 */
|
||||
npfctl_parse_cidr(taddr_s, npfctl_get_addrfamily(taddr_s), &taddr, &dummy);
|
||||
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);
|
||||
to_v, AF_INET, NULL, raddr_v, NULL);
|
||||
(void)npf_nat_insert(npf_conf, bn, NPF_PRI_NEXT);
|
||||
}
|
||||
return 0;
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: npfctl.c,v 1.6 2011/08/31 13:32:38 joerg Exp $ */
|
||||
/* $NetBSD: npfctl.c,v 1.7 2011/11/04 01:00:28 zoltan Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2009-2011 The NetBSD Foundation, Inc.
|
||||
|
@ -30,7 +30,7 @@
|
|||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__RCSID("$NetBSD: npfctl.c,v 1.6 2011/08/31 13:32:38 joerg Exp $");
|
||||
__RCSID("$NetBSD: npfctl.c,v 1.7 2011/11/04 01:00:28 zoltan Exp $");
|
||||
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/stat.h>
|
||||
|
@ -252,7 +252,8 @@ npfctl(int action, int argc, char **argv)
|
|||
tbl.nct_action = 0;
|
||||
arg = argv[3];
|
||||
}
|
||||
if (!npfctl_parse_v4mask(arg,
|
||||
if (!npfctl_parse_cidr(arg,
|
||||
npfctl_get_addrfamily(arg),
|
||||
&tbl.nct_addr, &tbl.nct_mask)) {
|
||||
errx(EXIT_FAILURE, "invalid CIDR '%s'", arg);
|
||||
}
|
||||
|
@ -276,7 +277,7 @@ npfctl(int action, int argc, char **argv)
|
|||
}
|
||||
break;
|
||||
}
|
||||
if (ret == -1) {
|
||||
if (ret) {
|
||||
err(EXIT_FAILURE, "ioctl");
|
||||
}
|
||||
close(fd);
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: npfctl.h,v 1.6 2011/02/02 02:20:25 rmind Exp $ */
|
||||
/* $NetBSD: npfctl.h,v 1.7 2011/11/04 01:00:28 zoltan Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2009-2011 The NetBSD Foundation, Inc.
|
||||
|
@ -74,22 +74,25 @@ char * xstrdup(const char *);
|
|||
void npfctl_init_data(void);
|
||||
int npfctl_ioctl_send(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 *);
|
||||
struct ifaddrs *npfctl_getif(char *, unsigned int *, bool, sa_family_t);
|
||||
void npfctl_create_mask(sa_family_t, u_int, npf_addr_t *);
|
||||
sa_family_t npfctl_get_addrfamily(const char *);
|
||||
sa_family_t npfctl_parse_cidr(char *, sa_family_t, npf_addr_t *, npf_netmask_t *);
|
||||
bool npfctl_parse_port(char *, bool *, in_port_t *, in_port_t *);
|
||||
|
||||
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 *);
|
||||
int, int, var_t *, sa_family_t, var_t *, var_t *, var_t *);
|
||||
|
||||
size_t npfctl_calc_ncsize(int []);
|
||||
size_t npfctl_failure_offset(int []);
|
||||
|
||||
void npfctl_gennc_ether(void **, int, uint16_t);
|
||||
void npfctl_gennc_v4cidr(void **, int,
|
||||
in_addr_t, in_addr_t, bool);
|
||||
const npf_addr_t *, const npf_netmask_t, bool);
|
||||
void npfctl_gennc_v6cidr(void **, int,
|
||||
const npf_addr_t *, const npf_netmask_t, bool);
|
||||
void npfctl_gennc_icmp(void **, int, int, int);
|
||||
void npfctl_gennc_tcpfl(void **, int , uint8_t, uint8_t);
|
||||
void npfctl_gennc_ports(void **, int,
|
||||
|
|
Loading…
Reference in New Issue