Module Name: src
Committed By: rmind
Date: Thu Jan 19 20:18:18 UTC 2017
Modified Files:
src/usr.sbin/npf/npfctl: npf.conf.5 npf_build.c npf_data.c npf_parse.y
npfctl.h
Log Message:
npfctl:
- Add protocol filter option for "map".
- Print user-friendly error if table contains an entry with invalid netmask.
- Add support for inline ports.
To generate a diff of this commit:
cvs rdiff -u -r1.46 -r1.47 src/usr.sbin/npf/npfctl/npf.conf.5
cvs rdiff -u -r1.43 -r1.44 src/usr.sbin/npf/npfctl/npf_build.c \
src/usr.sbin/npf/npfctl/npfctl.h
cvs rdiff -u -r1.27 -r1.28 src/usr.sbin/npf/npfctl/npf_data.c
cvs rdiff -u -r1.41 -r1.42 src/usr.sbin/npf/npfctl/npf_parse.y
Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.
Modified files:
Index: src/usr.sbin/npf/npfctl/npf.conf.5
diff -u src/usr.sbin/npf/npfctl/npf.conf.5:1.46 src/usr.sbin/npf/npfctl/npf.conf.5:1.47
--- src/usr.sbin/npf/npfctl/npf.conf.5:1.46 Tue Jan 3 01:29:49 2017
+++ src/usr.sbin/npf/npfctl/npf.conf.5 Thu Jan 19 20:18:17 2017
@@ -1,4 +1,4 @@
-.\" $NetBSD: npf.conf.5,v 1.46 2017/01/03 01:29:49 rmind Exp $
+.\" $NetBSD: npf.conf.5,v 1.47 2017/01/19 20:18:17 rmind Exp $
.\"
.\" Copyright (c) 2009-2017 The NetBSD Foundation, Inc.
.\" All rights reserved.
@@ -228,11 +228,15 @@ For example:
.Bd -literal
procedure "someproc" {
log: npflog0
- normalize: "random-id", "min-ttl" 64
+ normalize: "random-id", "min-ttl" 64, "max-mss" 1432
}
.Ed
.Pp
In this case, the procedure calls the logging and normalisation modules.
+Traffic normalisation has a set of different mechanisms.
+In the example above, the normalisation procedure has arguments which
+apply the following mechanisms: IPv4 ID randomisation, Don't Fragment (DF)
+flag cleansing, minimum TTL enforcement and TCP MSS "clamping".
.Ss Misc
Text after a hash
.Pq Sq #
@@ -275,9 +279,9 @@ table-def = "table" table-id "type" ( "h
; Mapping for address translation.
map = "map" interface
- ( "static" [ "algo" algorithm ] | "dynamic" )
+ ( "static" [ "algo" algorithm ] | "dynamic" ) [ proto ]
net-seg ( "->" | "<-" | "<->" ) net-seg
- [ "pass" filt-opts ]
+ [ "pass" [ proto ] filt-opts ]
; Rule procedure definition. The name should be in the double quotes.
;
@@ -295,8 +299,7 @@ group = "group" ( "default" | group-opt
group-opts = name-string [ "in" | "out" ] [ "on" interface ]
rule-list = [ rule new-line ] rule-list
-npf-filter = [ "family" family-opt ] [ "proto" protocol [ proto-opts ] ]
- ( "all" | filt-opts )
+npf-filter = [ "family" family-opt ] [ proto ] ( "all" | filt-opts )
static-rule = ( "block" [ block-opts ] | "pass" )
[ "stateful" | "stateful-ends" ]
[ "in" | out" ] [ "final" ] [ "on" interface ]
@@ -306,6 +309,7 @@ static-rule = ( "block" [ block-opts ] |
dynamic-ruleset = "ruleset" group-opts
rule = static-rule | dynamic-ruleset
+proto = "proto" protocol [ proto-opts ]
block-opts = "return-rst" | "return-icmp" | "return"
family-opt = "inet4" | "inet6"
proto-opts = "flags" tcp-flags [ "/" tcp-flag-mask ] |
@@ -345,7 +349,7 @@ alg "icmp"
# Note: if $ext_if has multiple IP address (e.g. IPv6 as well),
# then the translation address has to be specified explicitly.
map $ext_if dynamic 10.1.1.0/24 -> $ext_if
-map $ext_if dynamic 10.1.1.2 port 22 <- $ext_if port 9022
+map $ext_if dynamic proto tcp 10.1.1.2 port 22 <- $ext_if port 9022
procedure "log" {
# Note: npf_ext_log kernel module should be loaded, if not built-in.
Index: src/usr.sbin/npf/npfctl/npf_build.c
diff -u src/usr.sbin/npf/npfctl/npf_build.c:1.43 src/usr.sbin/npf/npfctl/npf_build.c:1.44
--- src/usr.sbin/npf/npfctl/npf_build.c:1.43 Tue Jan 3 01:29:49 2017
+++ src/usr.sbin/npf/npfctl/npf_build.c Thu Jan 19 20:18:17 2017
@@ -1,4 +1,4 @@
-/* $NetBSD: npf_build.c,v 1.43 2017/01/03 01:29:49 rmind Exp $ */
+/* $NetBSD: npf_build.c,v 1.44 2017/01/19 20:18:17 rmind Exp $ */
/*-
* Copyright (c) 2011-2017 The NetBSD Foundation, Inc.
@@ -34,7 +34,7 @@
*/
#include <sys/cdefs.h>
-__RCSID("$NetBSD: npf_build.c,v 1.43 2017/01/03 01:29:49 rmind Exp $");
+__RCSID("$NetBSD: npf_build.c,v 1.44 2017/01/19 20:18:17 rmind Exp $");
#include <sys/types.h>
#include <sys/mman.h>
@@ -586,9 +586,9 @@ npfctl_build_rule(uint32_t attr, const c
*/
static nl_nat_t *
npfctl_build_nat(int type, const char *ifname, const addr_port_t *ap,
- const filt_opts_t *fopts, u_int flags)
+ const opt_proto_t *op, const filt_opts_t *fopts, u_int flags)
{
- const opt_proto_t op = { .op_proto = -1, .op_opts = NULL };
+ const opt_proto_t def_op = { .op_proto = -1, .op_opts = NULL };
fam_addr_mask_t *am = npfctl_get_singlefam(ap->ap_netaddr);
in_port_t port;
nl_nat_t *nat;
@@ -600,10 +600,13 @@ npfctl_build_nat(int type, const char *i
} else {
port = 0;
}
+ if (!op) {
+ op = &def_op;
+ }
nat = npf_nat_create(type, flags, ifname, am->fam_family,
&am->fam_addr, am->fam_mask, port);
- npfctl_build_code(nat, am->fam_family, &op, fopts);
+ npfctl_build_code(nat, am->fam_family, op, fopts);
npf_nat_insert(npf_conf, nat, NPF_PRI_LAST);
return nat;
}
@@ -613,7 +616,7 @@ npfctl_build_nat(int type, const char *i
*/
void
npfctl_build_natseg(int sd, int type, const char *ifname,
- const addr_port_t *ap1, const addr_port_t *ap2,
+ const addr_port_t *ap1, const addr_port_t *ap2, const opt_proto_t *op,
const filt_opts_t *fopts, u_int algo)
{
fam_addr_mask_t *am1 = NULL, *am2 = NULL;
@@ -692,12 +695,12 @@ npfctl_build_natseg(int sd, int type, co
if (type & NPF_NATIN) {
memset(&imfopts, 0, sizeof(filt_opts_t));
memcpy(&imfopts.fo_to, ap2, sizeof(addr_port_t));
- nt1 = npfctl_build_nat(NPF_NATIN, ifname, ap1, fopts, flags);
+ nt1 = npfctl_build_nat(NPF_NATIN, ifname, ap1, op, fopts, flags);
}
if (type & NPF_NATOUT) {
memset(&imfopts, 0, sizeof(filt_opts_t));
memcpy(&imfopts.fo_from, ap1, sizeof(addr_port_t));
- nt2 = npfctl_build_nat(NPF_NATOUT, ifname, ap2, fopts, flags);
+ nt2 = npfctl_build_nat(NPF_NATOUT, ifname, ap2, op, fopts, flags);
}
if (algo == NPF_ALGO_NPT66) {
Index: src/usr.sbin/npf/npfctl/npfctl.h
diff -u src/usr.sbin/npf/npfctl/npfctl.h:1.43 src/usr.sbin/npf/npfctl/npfctl.h:1.44
--- src/usr.sbin/npf/npfctl/npfctl.h:1.43 Tue Jan 3 01:29:49 2017
+++ src/usr.sbin/npf/npfctl/npfctl.h Thu Jan 19 20:18:17 2017
@@ -1,7 +1,7 @@
-/* $NetBSD: npfctl.h,v 1.43 2017/01/03 01:29:49 rmind Exp $ */
+/* $NetBSD: npfctl.h,v 1.44 2017/01/19 20:18:17 rmind Exp $ */
/*-
- * Copyright (c) 2009-2013 The NetBSD Foundation, Inc.
+ * Copyright (c) 2009-2017 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This material is based upon work partially supported by The
@@ -127,7 +127,7 @@ npfvar_t * npfctl_parse_tcpflag(const ch
npfvar_t * npfctl_parse_table_id(const char *);
npfvar_t * npfctl_parse_icmp(int, int, int);
npfvar_t * npfctl_parse_port_range(in_port_t, in_port_t);
-npfvar_t * npfctl_parse_port_range_variable(const char *);
+npfvar_t * npfctl_parse_port_range_variable(const char *, npfvar_t *);
npfvar_t * npfctl_parse_fam_addr_mask(const char *, const char *,
unsigned long *);
bool npfctl_parse_cidr(char *, fam_addr_mask_t *, int *);
@@ -204,7 +204,7 @@ void npfctl_build_rule(uint32_t, const
const char *, const char *);
void npfctl_build_natseg(int, int, const char *,
const addr_port_t *, const addr_port_t *,
- const filt_opts_t *, unsigned);
+ const opt_proto_t *, const filt_opts_t *, unsigned);
void npfctl_build_maprset(const char *, int, const char *);
void npfctl_build_table(const char *, u_int, const char *);
Index: src/usr.sbin/npf/npfctl/npf_data.c
diff -u src/usr.sbin/npf/npfctl/npf_data.c:1.27 src/usr.sbin/npf/npfctl/npf_data.c:1.28
--- src/usr.sbin/npf/npfctl/npf_data.c:1.27 Tue Dec 27 22:35:33 2016
+++ src/usr.sbin/npf/npfctl/npf_data.c Thu Jan 19 20:18:17 2017
@@ -1,7 +1,7 @@
-/* $NetBSD: npf_data.c,v 1.27 2016/12/27 22:35:33 rmind Exp $ */
+/* $NetBSD: npf_data.c,v 1.28 2017/01/19 20:18:17 rmind Exp $ */
/*-
- * Copyright (c) 2009-2014 The NetBSD Foundation, Inc.
+ * Copyright (c) 2009-2017 The NetBSD Foundation, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -31,7 +31,7 @@
*/
#include <sys/cdefs.h>
-__RCSID("$NetBSD: npf_data.c,v 1.27 2016/12/27 22:35:33 rmind Exp $");
+__RCSID("$NetBSD: npf_data.c,v 1.28 2017/01/19 20:18:17 rmind Exp $");
#include <stdlib.h>
#include <stddef.h>
@@ -129,6 +129,12 @@ npfctl_copy_address(sa_family_t fam, npf
}
}
+/*
+ * npfctl_parse_fam_addr: parse a given a string and return the address
+ * family with the actual address as npf_addr_t.
+ *
+ * => Return true on success; false otherwise.
+ */
static bool
npfctl_parse_fam_addr(const char *name, sa_family_t *fam, npf_addr_t *addr)
{
@@ -154,41 +160,65 @@ npfctl_parse_fam_addr(const char *name,
return true;
}
+/*
+ * npfctl_parse_mask: parse a given string which represents a mask and
+ * can either be in quad-dot or CIDR block notation; validates the mask
+ * given the family.
+ *
+ * => Returns true if mask is valid (or is NULL); false otherwise.
+ */
static bool
npfctl_parse_mask(const char *s, sa_family_t fam, npf_netmask_t *mask)
{
+ unsigned max_mask = NPF_MAX_NETMASK;
char *ep = NULL;
npf_addr_t addr;
uint8_t *ap;
- if (s) {
- errno = 0;
- *mask = (npf_netmask_t)strtol(s, &ep, 0);
- if (*ep == '\0' && s != ep && errno != ERANGE)
- return true;
- if (!npfctl_parse_fam_addr(s, &fam, &addr))
- return false;
- }
-
assert(fam == AF_INET || fam == AF_INET6);
- *mask = NPF_NO_NETMASK;
- if (ep == NULL) {
+ if (!s) {
+ /* No mask. */
+ *mask = NPF_NO_NETMASK;
return true;
}
+ errno = 0;
+ *mask = (npf_netmask_t)strtol(s, &ep, 0);
+ if (*ep == '\0' && s != ep && errno != ERANGE) {
+ /* Just a number -- CIDR notation. */
+ goto check;
+ }
+
+ /* Other characters: try to parse a full address. */
+ if (!npfctl_parse_fam_addr(s, &fam, &addr)) {
+ return false;
+ }
+
+ /* Convert the address to CIDR block number. */
ap = addr.word8 + (*mask / 8) - 1;
while (ap >= addr.word8) {
for (int j = 8; j > 0; j--) {
if (*ap & 1)
- return true;
+ goto check;
*ap >>= 1;
(*mask)--;
if (*mask == 0)
- return true;
+ goto check;
}
ap--;
}
+ *mask = NPF_NO_NETMASK;
return true;
+check:
+ switch (fam) {
+ case AF_INET:
+ max_mask = 32;
+ break;
+ case AF_INET6:
+ max_mask = 128;
+ break;
+ }
+ return *mask <= max_mask;
}
/*
@@ -202,6 +232,7 @@ npfctl_parse_fam_addr_mask(const char *a
unsigned long *nummask)
{
fam_addr_mask_t fam;
+ char buf[32];
memset(&fam, 0, sizeof(fam));
@@ -209,12 +240,14 @@ npfctl_parse_fam_addr_mask(const char *a
return NULL;
/*
- * Note: both mask and nummask may be NULL. In such case,
- * npfctl_parse_mask() will handle and will set full mask.
+ * Mask may be NULL. In such case, "no mask" value will be set.
*/
if (nummask) {
- fam.fam_mask = *nummask;
- } else if (!npfctl_parse_mask(mask, fam.fam_family, &fam.fam_mask)) {
+ /* Let npfctl_parse_mask() validate the number. */
+ snprintf(buf, sizeof(buf), "%lu", *nummask);
+ mask = buf;
+ }
+ if (!npfctl_parse_mask(mask, fam.fam_family, &fam.fam_mask)) {
return NULL;
}
return npfvar_create_element(NPFVAR_FAM, &fam, sizeof(fam));
@@ -249,17 +282,16 @@ npfctl_parse_port_range(in_port_t s, in_
}
npfvar_t *
-npfctl_parse_port_range_variable(const char *v)
+npfctl_parse_port_range_variable(const char *v, npfvar_t *vp)
{
- npfvar_t *vp = npfvar_lookup(v);
size_t count = npfvar_get_count(vp);
npfvar_t *pvp = npfvar_create();
port_range_t *pr;
- in_port_t p;
for (size_t i = 0; i < count; i++) {
int type = npfvar_get_type(vp, i);
void *data = npfvar_get_data(vp, type, i);
+ in_port_t p;
switch (type) {
case NPFVAR_IDENTIFIER:
@@ -277,8 +309,13 @@ npfctl_parse_port_range_variable(const c
npfvar_add_elements(pvp, npfctl_parse_port_range(p, p));
break;
default:
- yyerror("wrong variable '%s' type '%s' for port range",
- v, npfvar_type(type));
+ if (v) {
+ yyerror("wrong variable '%s' type '%s' "
+ "for port range", v, npfvar_type(type));
+ } else {
+ yyerror("wrong element '%s' in the "
+ "inline list", npfvar_type(type));
+ }
npfvar_destroy(pvp);
return NULL;
}
@@ -322,13 +359,11 @@ npfctl_parse_ifnet(const char *ifname, c
memset(&fam, 0, sizeof(fam));
fam.fam_family = sa->sa_family;
fam.fam_ifindex = ifna.ifna_index;
+ fam.fam_mask = NPF_NO_NETMASK;
if (!npfctl_copy_address(sa->sa_family, &fam.fam_addr, sa))
goto out;
- if (!npfctl_parse_mask(NULL, fam.fam_family, &fam.fam_mask))
- goto out;
-
if (!npfvar_add_element(vpa, NPFVAR_FAM, &fam, sizeof(fam)))
goto out;
}
Index: src/usr.sbin/npf/npfctl/npf_parse.y
diff -u src/usr.sbin/npf/npfctl/npf_parse.y:1.41 src/usr.sbin/npf/npfctl/npf_parse.y:1.42
--- src/usr.sbin/npf/npfctl/npf_parse.y:1.41 Wed Jan 11 02:11:21 2017
+++ src/usr.sbin/npf/npfctl/npf_parse.y Thu Jan 19 20:18:17 2017
@@ -1,4 +1,4 @@
-/* $NetBSD: npf_parse.y,v 1.41 2017/01/11 02:11:21 christos Exp $ */
+/* $NetBSD: npf_parse.y,v 1.42 2017/01/19 20:18:17 rmind Exp $ */
/*-
* Copyright (c) 2011-2017 The NetBSD Foundation, Inc.
@@ -36,7 +36,9 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#ifdef __NetBSD__
#include <vis.h>
+#endif
#include "npfctl.h"
@@ -65,11 +67,14 @@ yyerror(const char *fmt, ...)
fprintf(stderr, "%s:%d:%d: %s", yyfilename,
yylineno - (int)eol, yycolumn, msg);
if (!eol) {
+#ifdef __NetBSD__
size_t len = strlen(context);
char *dst = ecalloc(1, len * 4 + 1);
strvisx(dst, context, len, VIS_WHITE|VIS_CSTYLE);
- fprintf(stderr, " near '%s'", dst);
+ context = dst
+#endif
+ fprintf(stderr, " near '%s'", context);
}
fprintf(stderr, "\n");
exit(EXIT_FAILURE);
@@ -347,13 +352,14 @@ mapseg
;
map
- : MAP ifref map_sd map_algo mapseg map_type mapseg PASS filt_opts
+ : MAP ifref map_sd map_algo mapseg map_type mapseg
+ PASS opt_proto filt_opts
{
- npfctl_build_natseg($3, $6, $2, &$5, &$7, &$9, $4);
+ npfctl_build_natseg($3, $6, $2, &$5, &$7, &$9, &$10, $4);
}
- | MAP ifref map_sd map_algo mapseg map_type mapseg
+ | MAP ifref map_sd map_algo opt_proto mapseg map_type mapseg
{
- npfctl_build_natseg($3, $6, $2, &$5, &$7, NULL, $4);
+ npfctl_build_natseg($3, $7, $2, &$6, &$8, &$5, NULL, $4);
}
| MAP RULESET group_opts
{
@@ -722,12 +728,14 @@ port_range
}
| PORT VAR_ID
{
- $$ = npfctl_parse_port_range_variable($2);
+ npfvar_t *vp = npfvar_lookup($2);
+ $$ = npfctl_parse_port_range_variable($2, vp);
}
- |
+ | PORT list
{
- $$ = NULL;
+ $$ = npfctl_parse_port_range_variable(NULL, $2);
}
+ | { $$ = NULL; }
;
port