Skip to content

Commit 26ee8dc

Browse files
firewall rules: add support for IPv4 and IPv6 packet fragments
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"} ] } } ```
1 parent c40c831 commit 26ee8dc

File tree

1 file changed

+30
-0
lines changed

1 file changed

+30
-0
lines changed

klib/firewall.c

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ typedef struct firewall_constraint {
1818

1919
enum firewall_l3_constraint {
2020
FW_L3_SRC,
21+
FW_L3_FRAG,
2122
FW_L3_PROTO,
2223
};
2324

@@ -76,6 +77,10 @@ static boolean firewall_ip4_match(vector constraints, void *buf, unsigned int le
7677
if (!firewall_match_buf(&hdr->src, c))
7778
return false;
7879
break;
80+
case FW_L3_FRAG:
81+
if (!firewall_match_val((IPH_OFFSET(hdr) & lwip_htons(IP_OFFMASK)) != 0, c))
82+
return false;
83+
break;
7984
case FW_L3_PROTO:
8085
if (!firewall_match_val(IPH_PROTO(hdr), c))
8186
return false;
@@ -162,6 +167,12 @@ static boolean firewall_ip6_match(vector constraints, void *buf, unsigned int le
162167
if (!firewall_match_buf(&hdr->src, c))
163168
return false;
164169
break;
170+
case FW_L3_FRAG:
171+
if (!frag_parsed)
172+
is_fragment = firewall_ip6_is_fragment(hdr, len);
173+
if (!firewall_match_val(is_fragment, c))
174+
return false;
175+
break;
165176
case FW_L3_PROTO: {
166177
u8 proto = firewall_ip6_get_hdr(buf, len, IP6_NEXTH_NONE, l4_hdr);
167178
if (!*l4_hdr || !firewall_match_val(proto, c))
@@ -300,6 +311,7 @@ static void firewall_dealloc_l3_constraint(heap h, firewall_constraint c)
300311
deallocate(h, c_buf, sizeof(*c_buf) + pad(c_buf->len, 8) / 8);
301312
break;
302313
}
314+
case FW_L3_FRAG:
303315
case FW_L3_PROTO: {
304316
firewall_constraint_val c_val = (firewall_constraint_val)c;
305317
deallocate(h, c_val, sizeof(*c_val));
@@ -366,6 +378,24 @@ static boolean firewall_rule_parse_l3(heap h, firewall_rule rule, value spec, bo
366378
runtime_memcpy(&c->buf, &addr, byte_count);
367379
vector_push(rule->l3_match, c);
368380
}
381+
string fragment = get_string(spec, sym(fragment));
382+
if (fragment) {
383+
boolean is_fragment;
384+
if (!buffer_strcmp(fragment, "y")) {
385+
is_fragment = true;
386+
} else if (!buffer_strcmp(fragment, "n")) {
387+
is_fragment = false;
388+
} else {
389+
msg_err("firewall: invalid ip fragment rule '%s'", buffer_to_sstring(fragment));
390+
return false;
391+
}
392+
firewall_constraint_val c = allocate(h, sizeof(*c));
393+
assert(c != INVALID_ADDRESS);
394+
c->c.type = FW_L3_FRAG;
395+
c->c.equals = true;
396+
c->val = is_fragment;
397+
vector_push(rule->l3_match, c);
398+
}
369399
rule->ip_version = ipv6 ? 6 : 4;
370400
return true;
371401
}

0 commit comments

Comments
 (0)