Skip to content

Commit 560d762

Browse files
author
Julia Kartseva
committed
bpf: add ip proto matching to socket-bind prog
Lookup ip protocol in a socket address to allow or deny binding a socket to the address. Matching rule is extended with 'protocol' field. If its value is 0 (IPPROTO_IP) ip protocol comparison is omitted and matching is passed to the next token which is ip ports. Documentation is updated.
1 parent 9fcfc04 commit 560d762

File tree

3 files changed

+27
-14
lines changed

3 files changed

+27
-14
lines changed

src/core/bpf-socket-bind.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ static int update_rules_map(
3535
LIST_FOREACH(socket_bind_items, item, head) {
3636
struct socket_bind_rule val = {
3737
.address_family = (uint32_t) item->address_family,
38+
.protocol = item->ip_protocol,
3839
.nr_ports = item->nr_ports,
3940
.port_min = item->port_min,
4041
};

src/core/bpf/socket_bind/socket-bind-api.bpf.h

Lines changed: 16 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -11,35 +11,39 @@
1111
/*
1212
* Bind rule is matched with socket fields accessible to cgroup/bind{4,6} hook
1313
* through bpf_sock_addr struct.
14-
* address_family is expected to be one of AF_UNSPEC, AF_INET or AF_INET6.
14+
* 'address_family' is expected to be one of AF_UNSPEC, AF_INET or AF_INET6.
1515
* Matching by family is bypassed for rules with AF_UNSPEC set, which makes the
1616
* rest of a rule applicable for both IPv4 and IPv6 addresses.
1717
* If matching by family is either successful or bypassed, a rule and a socket
18-
* are matched by ports.
19-
* nr_ports and port_min fields specify a set of ports to match a user port
18+
* are matched by ip protocol.
19+
* If 'protocol' is 0, matching is bypassed.
20+
* 'nr_ports' and 'port_min' fields specify a set of ports to match a user port
2021
* with.
21-
* If nr_ports is 0, matching by port is bypassed, making that rule applicable
22+
* If 'nr_ports' is 0, matching by port is bypassed, making that rule applicable
2223
* for all possible ports, e.g. [1, 65535] range. Thus a rule with
23-
* address_family and nr_ports equal to AF_UNSPEC and 0 correspondingly forms
24-
* 'allow any' or 'deny any' cases.
25-
* For positive nr_ports, a user_port lying in a range from port_min to
26-
* port_min + nr_ports exclusively is considered to be a match. nr_ports
24+
* 'address_family', 'protocol' and 'nr_ports' equal to AF_UNSPEC, 0 and 0
25+
* correspondingly forms 'allow any' or 'deny any' cases.
26+
* For positive 'nr_ports', a user_port lying in a range from 'port_min' to'
27+
* 'port_min' + 'nr_ports' exclusively is considered to be a match. 'nr_ports'
2728
* equalling to 1 forms a rule for a single port.
2829
* Ports are in host order.
2930
*
3031
* Examples:
31-
* AF_UNSPEC, 1, 7777: match IPv4 and IPv6 addresses with 7777 user port;
32+
* AF_UNSPEC, 1, 0, 7777: match IPv4 and IPv6 addresses with 7777 user port;
3233
*
33-
* AF_INET, 1023, 1: match IPv4 addresses with user port in [1, 1023]
34+
* AF_INET, 1023, 0, 1: match IPv4 addresses with user port in [1, 1023]
3435
* range inclusively;
3536
*
36-
* AF_INET6, 0, 0: match IPv6 addresses;
37+
* AF_INET6, 0, 0, 0: match IPv6 addresses;
3738
*
38-
* AF_UNSPEC, 0, 0: match IPv4 and IPv6 addresses.
39+
* AF_UNSPEC, 0, 0, 0: match IPv4 and IPv6 addresses;
40+
*
41+
* AF_INET6, IPPROTO_TCP, 0, 0: match IPv6/TCP addresses.
3942
*/
4043

4144
struct socket_bind_rule {
4245
__u32 address_family;
46+
__u32 protocol;
4347
__u16 nr_ports;
4448
__u16 port_min;
4549
};

src/core/bpf/socket_bind/socket-bind.bpf.c

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,11 @@ static __always_inline bool match_af(
3939
return r->address_family == AF_UNSPEC || address_family == r->address_family;
4040
}
4141

42+
static __always_inline bool match_protocol(
43+
__u32 protocol, const struct socket_bind_rule *r) {
44+
return r->protocol == 0 || r->protocol == protocol;
45+
}
46+
4247
static __always_inline bool match_user_port(
4348
__u16 port, const struct socket_bind_rule *r) {
4449
return r->nr_ports == 0 ||
@@ -47,9 +52,12 @@ static __always_inline bool match_user_port(
4752

4853
static __always_inline bool match(
4954
__u8 address_family,
55+
__u32 protocol,
5056
__u16 port,
5157
const struct socket_bind_rule *r) {
52-
return match_af(address_family, r) && match_user_port(port, r);
58+
return match_af(address_family, r) &&
59+
match_protocol(protocol, r) &&
60+
match_user_port(port, r);
5361
}
5462

5563
static __always_inline bool match_rules(
@@ -67,7 +75,7 @@ static __always_inline bool match_rules(
6775
if (!rule)
6876
break;
6977

70-
if (match(ctx->user_family, port, rule))
78+
if (match(ctx->user_family, ctx->protocol, port, rule))
7179
return true;
7280
}
7381

0 commit comments

Comments
 (0)