Skip to content

Commit

Permalink
firewall rules: add support for IPv4 and IPv6 packet fragments
Browse files Browse the repository at this point in the history
Add support for a new "fragment" tuple attribute that can be
specified in "ip" and "ip6" tuples in firewall rules; this new
attribute can have a "y" or "n" value: "y" makes the rule match the
second and subsequent fragments of fragmented IP packets, while
"n" makes the rule match non-fragmented packets and the first
fragment of fragmented packets.
Example snippet of Ops configuration that makes the firewall drop
all fragmented IPv4 packets:
```
  "ManifestPassthrough": {
    "firewall": {
      "rules": [
        {"ip": {"fragment": "y"}, "action": "drop"}
      ]
    }
  }
```
  • Loading branch information
francescolavra committed Jan 18, 2025
1 parent c40c831 commit 26ee8dc
Showing 1 changed file with 30 additions and 0 deletions.
30 changes: 30 additions & 0 deletions klib/firewall.c
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ typedef struct firewall_constraint {

enum firewall_l3_constraint {
FW_L3_SRC,
FW_L3_FRAG,
FW_L3_PROTO,
};

Expand Down Expand Up @@ -76,6 +77,10 @@ static boolean firewall_ip4_match(vector constraints, void *buf, unsigned int le
if (!firewall_match_buf(&hdr->src, c))
return false;
break;
case FW_L3_FRAG:
if (!firewall_match_val((IPH_OFFSET(hdr) & lwip_htons(IP_OFFMASK)) != 0, c))
return false;
break;
case FW_L3_PROTO:
if (!firewall_match_val(IPH_PROTO(hdr), c))
return false;
Expand Down Expand Up @@ -162,6 +167,12 @@ static boolean firewall_ip6_match(vector constraints, void *buf, unsigned int le
if (!firewall_match_buf(&hdr->src, c))
return false;
break;
case FW_L3_FRAG:
if (!frag_parsed)
is_fragment = firewall_ip6_is_fragment(hdr, len);
if (!firewall_match_val(is_fragment, c))
return false;
break;
case FW_L3_PROTO: {
u8 proto = firewall_ip6_get_hdr(buf, len, IP6_NEXTH_NONE, l4_hdr);
if (!*l4_hdr || !firewall_match_val(proto, c))
Expand Down Expand Up @@ -300,6 +311,7 @@ static void firewall_dealloc_l3_constraint(heap h, firewall_constraint c)
deallocate(h, c_buf, sizeof(*c_buf) + pad(c_buf->len, 8) / 8);
break;
}
case FW_L3_FRAG:
case FW_L3_PROTO: {
firewall_constraint_val c_val = (firewall_constraint_val)c;
deallocate(h, c_val, sizeof(*c_val));
Expand Down Expand Up @@ -366,6 +378,24 @@ static boolean firewall_rule_parse_l3(heap h, firewall_rule rule, value spec, bo
runtime_memcpy(&c->buf, &addr, byte_count);
vector_push(rule->l3_match, c);
}
string fragment = get_string(spec, sym(fragment));
if (fragment) {
boolean is_fragment;
if (!buffer_strcmp(fragment, "y")) {
is_fragment = true;
} else if (!buffer_strcmp(fragment, "n")) {
is_fragment = false;
} else {
msg_err("firewall: invalid ip fragment rule '%s'", buffer_to_sstring(fragment));
return false;
}
firewall_constraint_val c = allocate(h, sizeof(*c));
assert(c != INVALID_ADDRESS);
c->c.type = FW_L3_FRAG;
c->c.equals = true;
c->val = is_fragment;
vector_push(rule->l3_match, c);
}
rule->ip_version = ipv6 ? 6 : 4;
return true;
}
Expand Down

0 comments on commit 26ee8dc

Please sign in to comment.