diff options
author | kp <kp@FreeBSD.org> | 2016-10-13 20:34:44 +0000 |
---|---|---|
committer | Luiz Souza <luiz@netgate.com> | 2017-07-17 19:15:17 -0500 |
commit | 59d32cb1534a80f7a00afd01d7593e74f634f3dc (patch) | |
tree | 220a8bb47fef72e167c78a67d884d0148ddd1dea | |
parent | 143eb5e93fc882f6bfe7be8d04839c70d76bdb69 (diff) | |
download | FreeBSD-src-59d32cb1534a80f7a00afd01d7593e74f634f3dc.zip FreeBSD-src-59d32cb1534a80f7a00afd01d7593e74f634f3dc.tar.gz |
pf: port extended DSCP support from OpenBSD
Ignore the ECN bits on 'tos' and 'set-tos' and allow to use
DCSP names instead of having to embed their TOS equivalents
as plain numbers.
Obtained from: OpenBSD
Sponsored by: OPNsense
Differential Revision: https://reviews.freebsd.org/D8165
(cherry picked from commit 3fbefcb2d1d30bf4f987d8ce451572c6722f0601)
-rw-r--r-- | sbin/pfctl/parse.y | 73 | ||||
-rw-r--r-- | share/man/man5/pf.conf.5 | 17 | ||||
-rw-r--r-- | sys/netpfil/pf/pf.c | 2 | ||||
-rw-r--r-- | sys/netpfil/pf/pf_norm.c | 2 |
4 files changed, 81 insertions, 13 deletions
diff --git a/sbin/pfctl/parse.y b/sbin/pfctl/parse.y index c5b86cf..7830032 100644 --- a/sbin/pfctl/parse.y +++ b/sbin/pfctl/parse.y @@ -360,6 +360,8 @@ void decide_address_family(struct node_host *, sa_family_t *); void remove_invalid_hosts(struct node_host **, sa_family_t *); int invalid_redirect(struct node_host *, sa_family_t); u_int16_t parseicmpspec(char *, sa_family_t); +int kw_casecmp(const void *, const void *); +int map_tos(char *string, int *); TAILQ_HEAD(loadanchorshead, loadanchors) loadanchorshead = TAILQ_HEAD_INITIALIZER(loadanchorshead); @@ -3665,15 +3667,17 @@ icmp6type : STRING { ; tos : STRING { - if (!strcmp($1, "lowdelay")) - $$ = IPTOS_LOWDELAY; - else if (!strcmp($1, "throughput")) - $$ = IPTOS_THROUGHPUT; - else if (!strcmp($1, "reliability")) - $$ = IPTOS_RELIABILITY; - else if ($1[0] == '0' && $1[1] == 'x') - $$ = strtoul($1, NULL, 16); - else + int val; + char *end; + + if (map_tos($1, &val)) + $$ = val; + else if ($1[0] == '0' && $1[1] == 'x') { + errno = 0; + $$ = strtoul($1, &end, 16); + if (errno || *end != '\0') + $$ = 256; + } else $$ = 256; /* flag bad argument */ if ($$ < 0 || $$ > 255) { yyerror("illegal tos value %s", $1); @@ -6414,6 +6418,57 @@ pfctl_load_anchors(int dev, struct pfctl *pf, struct pfr_buffer *trans) } int +kw_casecmp(const void *k, const void *e) +{ + return (strcasecmp(k, ((const struct keywords *)e)->k_name)); +} + +int +map_tos(char *s, int *val) +{ + /* DiffServ Codepoints and other TOS mappings */ + const struct keywords toswords[] = { + { "af11", IPTOS_DSCP_AF11 }, + { "af12", IPTOS_DSCP_AF12 }, + { "af13", IPTOS_DSCP_AF13 }, + { "af21", IPTOS_DSCP_AF21 }, + { "af22", IPTOS_DSCP_AF22 }, + { "af23", IPTOS_DSCP_AF23 }, + { "af31", IPTOS_DSCP_AF31 }, + { "af32", IPTOS_DSCP_AF32 }, + { "af33", IPTOS_DSCP_AF33 }, + { "af41", IPTOS_DSCP_AF41 }, + { "af42", IPTOS_DSCP_AF42 }, + { "af43", IPTOS_DSCP_AF43 }, + { "critical", IPTOS_PREC_CRITIC_ECP }, + { "cs0", IPTOS_DSCP_CS0 }, + { "cs1", IPTOS_DSCP_CS1 }, + { "cs2", IPTOS_DSCP_CS2 }, + { "cs3", IPTOS_DSCP_CS3 }, + { "cs4", IPTOS_DSCP_CS4 }, + { "cs5", IPTOS_DSCP_CS5 }, + { "cs6", IPTOS_DSCP_CS6 }, + { "cs7", IPTOS_DSCP_CS7 }, + { "ef", IPTOS_DSCP_EF }, + { "inetcontrol", IPTOS_PREC_INTERNETCONTROL }, + { "lowdelay", IPTOS_LOWDELAY }, + { "netcontrol", IPTOS_PREC_NETCONTROL }, + { "reliability", IPTOS_RELIABILITY }, + { "throughput", IPTOS_THROUGHPUT } + }; + const struct keywords *p; + + p = bsearch(s, toswords, sizeof(toswords)/sizeof(toswords[0]), + sizeof(toswords[0]), kw_casecmp); + + if (p) { + *val = p->k_val; + return (1); + } + return (0); +} + +int rt_tableid_max(void) { #ifdef __FreeBSD__ diff --git a/share/man/man5/pf.conf.5 b/share/man/man5/pf.conf.5 index 3ff63bb..6a7eebe 100644 --- a/share/man/man5/pf.conf.5 +++ b/share/man/man5/pf.conf.5 @@ -28,7 +28,7 @@ .\" ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE .\" POSSIBILITY OF SUCH DAMAGE. .\" -.Dd June 9, 2016 +.Dd October 6, 2016 .Dt PF.CONF 5 .Os .Sh NAME @@ -648,9 +648,16 @@ for matching IP packets. .Em TOS may be given as one of +.Ar critical , +.Ar inetcontrol , .Ar lowdelay , +.Ar netcontrol , .Ar throughput , .Ar reliability , +or one of the DiffServ Code Points: +.Ar ef , +.Ar af11 No ... Ar af43 , +.Ar cs0 No ... Ar cs7 ; or as either hex or decimal. .It Ar random-id Replaces the IP identification field with random values to compensate @@ -1697,9 +1704,16 @@ bits set. .Em TOS may be given as one of +.Ar critical , +.Ar inetcontrol , .Ar lowdelay , +.Ar netcontrol , .Ar throughput , .Ar reliability , +or one of the DiffServ Code Points: +.Ar ef , +.Ar af11 No ... Ar af43 , +.Ar cs0 No ... Ar cs7 ; or as either hex or decimal. .Pp For example, the following rules are identical: @@ -1803,7 +1817,6 @@ pass in proto tcp to port 25 set prio 2 pass in proto tcp to port 22 set prio (2, 5) .Ed .Pp - .It Ar tag Aq Ar string Packets matching this rule will be tagged with the specified string. diff --git a/sys/netpfil/pf/pf.c b/sys/netpfil/pf/pf.c index 47f534e..3bc692e 100644 --- a/sys/netpfil/pf/pf.c +++ b/sys/netpfil/pf/pf.c @@ -6295,7 +6295,7 @@ pf_test(int dir, struct ifnet *ifp, struct mbuf **m0, struct inpcb *inp) pd.sidx = (dir == PF_IN) ? 0 : 1; pd.didx = (dir == PF_IN) ? 1 : 0; pd.af = AF_INET; - pd.tos = h->ip_tos; + pd.tos = h->ip_tos & ~IPTOS_ECN_MASK; pd.tot_len = ntohs(h->ip_len); /* handle fragments that didn't get reassembled by normalization */ diff --git a/sys/netpfil/pf/pf_norm.c b/sys/netpfil/pf/pf_norm.c index f54e038..81ef54d 100644 --- a/sys/netpfil/pf/pf_norm.c +++ b/sys/netpfil/pf/pf_norm.c @@ -1815,7 +1815,7 @@ pf_scrub_ip(struct mbuf **m0, u_int32_t flags, u_int8_t min_ttl, u_int8_t tos) u_int16_t ov, nv; ov = *(u_int16_t *)h; - h->ip_tos = tos; + h->ip_tos = tos | (h->ip_tos & IPTOS_ECN_MASK); nv = *(u_int16_t *)h; h->ip_sum = pf_cksum_fixup(h->ip_sum, ov, nv, 0); |