Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/usr.sbin/npf/npfctl npfctl:



details:   https://anonhg.NetBSD.org/src/rev/0f9f8c8f0988
branches:  trunk
changeset: 821006:0f9f8c8f0988
user:      rmind <rmind%NetBSD.org@localhost>
date:      Thu Jan 19 20:18:17 2017 +0000

description:
npfctl:
- Add protocol filter option for "map".
- Print user-friendly error if table contains an entry with invalid netmask.
- Add support for inline ports.

diffstat:

 usr.sbin/npf/npfctl/npf.conf.5  |  18 ++++---
 usr.sbin/npf/npfctl/npf_build.c |  19 ++++---
 usr.sbin/npf/npfctl/npf_data.c  |  91 ++++++++++++++++++++++++++++------------
 usr.sbin/npf/npfctl/npf_parse.y |  26 +++++++----
 usr.sbin/npf/npfctl/npfctl.h    |   8 +-
 5 files changed, 106 insertions(+), 56 deletions(-)

diffs (truncated from 429 to 300 lines):

diff -r 59d0287666f6 -r 0f9f8c8f0988 usr.sbin/npf/npfctl/npf.conf.5
--- a/usr.sbin/npf/npfctl/npf.conf.5    Thu Jan 19 19:09:06 2017 +0000
+++ b/usr.sbin/npf/npfctl/npf.conf.5    Thu Jan 19 20:18:17 2017 +0000
@@ -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 @@
 .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 @@
 ; 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-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 @@
 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 @@
 # 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.
diff -r 59d0287666f6 -r 0f9f8c8f0988 usr.sbin/npf/npfctl/npf_build.c
--- a/usr.sbin/npf/npfctl/npf_build.c   Thu Jan 19 19:09:06 2017 +0000
+++ b/usr.sbin/npf/npfctl/npf_build.c   Thu Jan 19 20:18:17 2017 +0000
@@ -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 @@
  */
 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 @@
        } 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 @@
  */
 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 @@
        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) {
diff -r 59d0287666f6 -r 0f9f8c8f0988 usr.sbin/npf/npfctl/npf_data.c
--- a/usr.sbin/npf/npfctl/npf_data.c    Thu Jan 19 19:09:06 2017 +0000
+++ b/usr.sbin/npf/npfctl/npf_data.c    Thu Jan 19 20:18:17 2017 +0000
@@ -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_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 @@
        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 @@
     unsigned long *nummask)
 {
        fam_addr_mask_t fam;
+       char buf[32];
 
        memset(&fam, 0, sizeof(fam));
 
@@ -209,12 +240,14 @@
                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 @@
 }
 
 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 @@
                        npfvar_add_elements(pvp, npfctl_parse_port_range(p, p));
                        break;
                default:
-                       yyerror("wrong variable '%s' type '%s' for port range",



Home | Main Index | Thread Index | Old Index