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
This commit is contained in:
Kristof Provost 2016-10-13 20:34:44 +00:00
parent cc94f0c2d7
commit 1f4955785d
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=307235
4 changed files with 81 additions and 13 deletions

View File

@ -351,6 +351,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 *);
static TAILQ_HEAD(loadanchorshead, loadanchors)
loadanchorshead = TAILQ_HEAD_INITIALIZER(loadanchorshead);
@ -3584,15 +3586,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);
@ -6249,6 +6253,57 @@ pfctl_load_anchors(int dev, struct pfctl *pf, struct pfr_buffer *trans)
return (0);
}
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)
{

View File

@ -28,7 +28,7 @@
.\" ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
.\" POSSIBILITY OF SUCH DAMAGE.
.\"
.Dd September 28, 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.

View File

@ -5893,7 +5893,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 */

View File

@ -1811,7 +1811,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);