extensions: dccp: Fix for DCCP type 'INVALID'

Support for matching on invalid DCCP type field values was pretty
broken: While RFC4340 declares any type value from 10 to 15 invalid, the
extension's type name 'INVALID' mapped to type value 10 only. Fix this
by introduction of INVALID_OTHER_TYPE_MASK which has the remaining
invalid type's bits set and apply it if bit 10 is set after parsing the
type list. When printing, stop searching type names after printing
'INVALID' - unless numeric output was requested. The latter prints all
actual type values. Since parsing types in numeric form is not
supported, changing the output should not break existing scripts.

When translating into nftables syntax, the code returned prematurely if
'INVALID' was among the list of types - thereby emitting invalid syntax.
Instead print a real match for invalid types by use of a range
expression.

While being at it, fix syntax of translator output: If only
'--dccp-types' was translated, the output contained an extra 'dccp'. On
the other hand, if '--sport' and '--dport' was present, a required
'dccp' between the translations of both was missing.

Fixes: e40b11d7ef ("add support for new 'dccp' protocol match")
Fixes: c94a998724 ("extensions: libxt_dccp: Add translation to nft")
Signed-off-by: Phil Sutter <phil@nwl.cc>
This commit is contained in:
Phil Sutter
2020-12-02 13:37:06 +01:00
parent 93d0c97e8b
commit 4bcbc8e11a
2 changed files with 45 additions and 25 deletions
+36 -22
View File
@@ -76,6 +76,9 @@ static const char *const dccp_pkt_types[] = {
[DCCP_PKT_INVALID] = "INVALID",
};
/* Bits for type values 11-15 */
#define INVALID_OTHER_TYPE_MASK 0xf800
static uint16_t
parse_dccp_types(const char *typestring)
{
@@ -95,6 +98,9 @@ parse_dccp_types(const char *typestring)
xtables_error(PARAMETER_PROBLEM,
"Unknown DCCP type `%s'", ptr);
}
if (typemask & (1 << DCCP_PKT_INVALID))
typemask |= INVALID_OTHER_TYPE_MASK;
free(buffer);
return typemask;
@@ -193,9 +199,13 @@ print_types(uint16_t types, int inverted, int numeric)
if (numeric)
printf("%u", i);
else
else {
printf("%s", dccp_pkt_types[i]);
if (i == DCCP_PKT_INVALID)
break;
}
types &= ~(1 << i);
}
}
@@ -288,6 +298,7 @@ static const char *const dccp_pkt_types_xlate[] = {
[DCCP_PKT_RESET] = "reset",
[DCCP_PKT_SYNC] = "sync",
[DCCP_PKT_SYNCACK] = "syncack",
[DCCP_PKT_INVALID] = "10-15",
};
static int dccp_type_xlate(const struct xt_dccp_info *einfo,
@@ -296,10 +307,10 @@ static int dccp_type_xlate(const struct xt_dccp_info *einfo,
bool have_type = false, set_need = false;
uint16_t types = einfo->typemask;
if (types & (1 << DCCP_PKT_INVALID))
return 0;
xt_xlate_add(xl, " dccp type%s ", einfo->invflags ? " !=" : "");
if (types & INVALID_OTHER_TYPE_MASK) {
types &= ~INVALID_OTHER_TYPE_MASK;
types |= 1 << DCCP_PKT_INVALID;
}
if ((types != 0) && !(types == (types & -types))) {
xt_xlate_add(xl, "{");
@@ -335,34 +346,37 @@ static int dccp_xlate(struct xt_xlate *xl,
char *space = "";
int ret = 1;
xt_xlate_add(xl, "dccp ");
if (einfo->flags & XT_DCCP_SRC_PORTS) {
xt_xlate_add(xl, "dccp sport%s %u",
einfo->invflags & XT_DCCP_SRC_PORTS ? " !=" : "",
einfo->spts[0]);
if (einfo->spts[0] != einfo->spts[1])
xt_xlate_add(xl, "sport%s %u-%u",
einfo->invflags & XT_DCCP_SRC_PORTS ? " !=" : "",
einfo->spts[0], einfo->spts[1]);
else
xt_xlate_add(xl, "sport%s %u",
einfo->invflags & XT_DCCP_SRC_PORTS ? " !=" : "",
einfo->spts[0]);
xt_xlate_add(xl, "-%u", einfo->spts[1]);
space = " ";
}
if (einfo->flags & XT_DCCP_DEST_PORTS) {
xt_xlate_add(xl, "%sdccp dport%s %u", space,
einfo->invflags & XT_DCCP_DEST_PORTS ? " !=" : "",
einfo->dpts[0]);
if (einfo->dpts[0] != einfo->dpts[1])
xt_xlate_add(xl, "%sdport%s %u-%u", space,
einfo->invflags & XT_DCCP_DEST_PORTS ? " !=" : "",
einfo->dpts[0], einfo->dpts[1]);
else
xt_xlate_add(xl, "%sdport%s %u", space,
einfo->invflags & XT_DCCP_DEST_PORTS ? " !=" : "",
einfo->dpts[0]);
xt_xlate_add(xl, "-%u", einfo->dpts[1]);
space = " ";
}
if (einfo->flags & XT_DCCP_TYPE)
if (einfo->flags & XT_DCCP_TYPE && einfo->typemask) {
xt_xlate_add(xl, "%sdccp type%s ", space,
einfo->invflags & XT_DCCP_TYPE ? " !=" : "");
ret = dccp_type_xlate(einfo, xl);
space = " ";
}
/* FIXME: no dccp option support in nftables yet */
if (einfo->flags & XT_DCCP_OPTION)
ret = 0;
+9 -3
View File
@@ -7,8 +7,14 @@ nft add rule ip filter INPUT dccp dport 100-200 counter
iptables-translate -A INPUT -p dccp -m dccp ! --dport 100
nft add rule ip filter INPUT dccp dport != 100 counter
iptables-translate -A INPUT -p dccp -m dccp --dport 100 --dccp-types REQUEST,RESPONSE,DATA,ACK,DATAACK,CLOSEREQ,CLOSE,SYNC,SYNCACK
nft add rule ip filter INPUT dccp dport 100 dccp type {request, response, data, ack, dataack, closereq, close, sync, syncack} counter
iptables-translate -A INPUT -p dccp -m dccp --dccp-types CLOSE
nft add rule ip filter INPUT dccp type close counter
iptables-translate -A INPUT -p dccp -m dccp --dccp-types INVALID
nft add rule ip filter INPUT dccp type 10-15 counter
iptables-translate -A INPUT -p dccp -m dccp --dport 100 --dccp-types REQUEST,RESPONSE,DATA,ACK,DATAACK,CLOSEREQ,CLOSE,SYNC,SYNCACK,INVALID
nft add rule ip filter INPUT dccp dport 100 dccp type {request, response, data, ack, dataack, closereq, close, sync, syncack, 10-15} counter
iptables-translate -A INPUT -p dccp -m dccp --sport 200 --dport 100
nft add rule ip filter INPUT dccp sport 200 dport 100 counter
nft add rule ip filter INPUT dccp sport 200 dccp dport 100 counter