Merge pull request #20021 from wat-ze-hex/socket-bind-ip-proto-2021-06-23

core/bpf: support IP protocol in SocketBind{Allow|Deny}=
This commit is contained in:
Zbigniew Jędrzejewski-Szmek
2021-06-30 14:46:27 +02:00
committed by GitHub
18 changed files with 374 additions and 107 deletions
+32 -11
View File
@@ -772,26 +772,32 @@ BPFProgram=bind6:/sys/fs/bpf/sock-addr-hook
<para>Allow or deny binding a socket address to a socket by matching it with the <replaceable>bind-rule</replaceable> and
applying a corresponding action if there is a match.</para>
<para><replaceable>bind-rule</replaceable> describes socket properties such as <replaceable>address-family</replaceable>
and <replaceable>ip-ports</replaceable>.</para>
<para><replaceable>bind-rule</replaceable> describes socket properties such as <replaceable>address-family</replaceable>,
<replaceable>transport-protocol</replaceable> and <replaceable>ip-ports</replaceable>.</para>
<para><replaceable>bind-rule</replaceable> := [<replaceable>address-family</replaceable><constant>:</constant>]<replaceable>ip-ports</replaceable></para>
<para><replaceable>bind-rule</replaceable> :=
{ [<replaceable>address-family</replaceable><constant>:</constant>][<replaceable>transport-protocol</replaceable><constant>:</constant>][<replaceable>ip-ports</replaceable>] | <constant>any</constant> }</para>
<para><replaceable>address-family</replaceable> := { <constant>ipv4</constant> | <constant>ipv6</constant> }</para>
<para><replaceable>ip-ports</replaceable> := { <replaceable>ip-port</replaceable> | <replaceable>ip-port-range</replaceable> |
<constant>any</constant> }</para>
<para><replaceable>transport-protocol</replaceable> := { <constant>tcp</constant> | <constant>udp</constant> }</para>
<para>An optional <replaceable>address-family</replaceable> expects <constant>IPv4</constant> or <constant>IPv6</constant> values.
If not specified, a rule will be matched for both IPv4 and IPv6 addresses and applied depending on other socket fields, e.g.
<para><replaceable>ip-ports</replaceable> := { <replaceable>ip-port</replaceable> | <replaceable>ip-port-range</replaceable> }</para>
<para>An optional <replaceable>address-family</replaceable> expects <constant>ipv4</constant> or <constant>ipv6</constant> values.
If not specified, a rule will be matched for both IPv4 and IPv6 addresses and applied depending on other socket fields, e.g. <replaceable>transport-protocol</replaceable>,
<replaceable>ip-port</replaceable>.</para>
<para><replaceable>ip-port</replaceable> value must lie within 1…65535 interval inclusively, i.e.
<para>An optional <replaceable>transport-protocol</replaceable> expects <constant>tcp</constant> or <constant>udp</constant> transport protocol names.
If not specified, a rule will be matched for any transport protocol.</para>
<para>An optional <replaceable>ip-port</replaceable> value must lie within 1…65535 interval inclusively, i.e.
dynamic port <constant>0</constant> is not allowed. A range of sequential ports is described by
<replaceable>ip-port-range</replaceable> := <replaceable>ip-port-low</replaceable><constant>-</constant><replaceable>ip-port-high</replaceable>,
where <replaceable>ip-port-low</replaceable> is smaller than or equal to <replaceable>ip-port-high</replaceable>
and both are within 1…65535 inclusively. A special value <constant>any</constant>
should be used to apply a rule to any port with a positive value.</para>
and both are within 1…65535 inclusively.</para>
<para>A special value <constant>any</constant> can be used to apply a rule to any address family, transport protocol and any port with a positive value.</para>
<para>To allow multiple rules assign <varname>SocketBindAllow=</varname> or <varname>SocketBindDeny=</varname> multiple times.
To clear the existing assignments pass an empty <varname>SocketBindAllow=</varname> or <varname>SocketBindDeny=</varname>
@@ -825,11 +831,26 @@ SocketBindDeny=any
…
# Deny binding IPv6 socket addresses.
[Service]
SocketBindDeny=ipv6:any
SocketBindDeny=ipv6
…
# Deny binding IPv4 and IPv6 socket addresses.
[Service]
SocketBindDeny=any
…
# Allow binding only over TCP
[Service]
SocketBindAllow=tcp
SocketBindDeny=any
…
# Allow binding only over IPv6/TCP
[Service]
SocketBindAllow=ipv6:tcp
SocketBindDeny=any
…
# Allow binding ports within 10000-65535 range over IPv4/UDP.
[Service]
SocketBindAllow=ipv4:udp:10000-65535
SocketBindDeny=any
…</programlisting></para>
</listitem>
</varlistentry>
+1
View File
@@ -35,6 +35,7 @@ static int update_rules_map(
LIST_FOREACH(socket_bind_items, item, head) {
struct socket_bind_rule val = {
.address_family = (uint32_t) item->address_family,
.protocol = item->ip_protocol,
.nr_ports = item->nr_ports,
.port_min = item->port_min,
};
+16 -12
View File
@@ -11,35 +11,39 @@
/*
* Bind rule is matched with socket fields accessible to cgroup/bind{4,6} hook
* through bpf_sock_addr struct.
* address_family is expected to be one of AF_UNSPEC, AF_INET or AF_INET6.
* 'address_family' is expected to be one of AF_UNSPEC, AF_INET or AF_INET6.
* Matching by family is bypassed for rules with AF_UNSPEC set, which makes the
* rest of a rule applicable for both IPv4 and IPv6 addresses.
* If matching by family is either successful or bypassed, a rule and a socket
* are matched by ports.
* nr_ports and port_min fields specify a set of ports to match a user port
* are matched by ip protocol.
* If 'protocol' is 0, matching is bypassed.
* 'nr_ports' and 'port_min' fields specify a set of ports to match a user port
* with.
* If nr_ports is 0, matching by port is bypassed, making that rule applicable
* If 'nr_ports' is 0, matching by port is bypassed, making that rule applicable
* for all possible ports, e.g. [1, 65535] range. Thus a rule with
* address_family and nr_ports equal to AF_UNSPEC and 0 correspondingly forms
* 'allow any' or 'deny any' cases.
* For positive nr_ports, a user_port lying in a range from port_min to
* port_min + nr_ports exclusively is considered to be a match. nr_ports
* 'address_family', 'protocol' and 'nr_ports' equal to AF_UNSPEC, 0 and 0
* correspondingly forms 'allow any' or 'deny any' cases.
* For positive 'nr_ports', a user_port lying in a range from 'port_min' to'
* 'port_min' + 'nr_ports' exclusively is considered to be a match. 'nr_ports'
* equalling to 1 forms a rule for a single port.
* Ports are in host order.
*
* Examples:
* AF_UNSPEC, 1, 7777: match IPv4 and IPv6 addresses with 7777 user port;
* AF_UNSPEC, 1, 0, 7777: match IPv4 and IPv6 addresses with 7777 user port;
*
* AF_INET, 1023, 1: match IPv4 addresses with user port in [1, 1023]
* AF_INET, 1023, 0, 1: match IPv4 addresses with user port in [1, 1023]
* range inclusively;
*
* AF_INET6, 0, 0: match IPv6 addresses;
* AF_INET6, 0, 0, 0: match IPv6 addresses;
*
* AF_UNSPEC, 0, 0: match IPv4 and IPv6 addresses.
* AF_UNSPEC, 0, 0, 0: match IPv4 and IPv6 addresses;
*
* AF_INET6, IPPROTO_TCP, 0, 0: match IPv6/TCP addresses.
*/
struct socket_bind_rule {
__u32 address_family;
__u32 protocol;
__u16 nr_ports;
__u16 port_min;
};
+10 -2
View File
@@ -39,6 +39,11 @@ static __always_inline bool match_af(
return r->address_family == AF_UNSPEC || address_family == r->address_family;
}
static __always_inline bool match_protocol(
__u32 protocol, const struct socket_bind_rule *r) {
return r->protocol == 0 || r->protocol == protocol;
}
static __always_inline bool match_user_port(
__u16 port, const struct socket_bind_rule *r) {
return r->nr_ports == 0 ||
@@ -47,9 +52,12 @@ static __always_inline bool match_user_port(
static __always_inline bool match(
__u8 address_family,
__u32 protocol,
__u16 port,
const struct socket_bind_rule *r) {
return match_af(address_family, r) && match_user_port(port, r);
return match_af(address_family, r) &&
match_protocol(protocol, r) &&
match_user_port(port, r);
}
static __always_inline bool match_rules(
@@ -67,7 +75,7 @@ static __always_inline bool match_rules(
if (!rule)
break;
if (match(ctx->user_family, port, rule))
if (match(ctx->user_family, ctx->protocol, port, rule))
return true;
}
+12 -5
View File
@@ -20,6 +20,7 @@
#include "fileio.h"
#include "fs-util.h"
#include "io-util.h"
#include "ip-protocol-list.h"
#include "limits-util.h"
#include "nulstr-util.h"
#include "parse-util.h"
@@ -593,18 +594,24 @@ void cgroup_context_dump(Unit *u, FILE* f, const char *prefix) {
}
void cgroup_context_dump_socket_bind_item(const CGroupSocketBindItem *item, FILE *f) {
const char *family, *colon;
const char *family, *colon1, *protocol = "", *colon2 = "";
family = strempty(af_to_ipv4_ipv6(item->address_family));
colon = isempty(family) ? "" : ":";
colon1 = isempty(family) ? "" : ":";
if (item->ip_protocol != 0) {
protocol = ip_protocol_to_tcp_udp(item->ip_protocol);
colon2 = ":";
}
if (item->nr_ports == 0)
fprintf(f, " %s%sany", family, colon);
fprintf(f, " %s%s%s%sany", family, colon1, protocol, colon2);
else if (item->nr_ports == 1)
fprintf(f, " %s%s%" PRIu16, family, colon, item->port_min);
fprintf(f, " %s%s%s%s%" PRIu16, family, colon1, protocol, colon2, item->port_min);
else {
uint16_t port_max = item->port_min + item->nr_ports - 1;
fprintf(f, " %s%s%" PRIu16 "-%" PRIu16, family, colon, item->port_min, port_max);
fprintf(f, " %s%s%s%s%" PRIu16 "-%" PRIu16, family, colon1, protocol, colon2,
item->port_min, port_max);
}
}
+2 -2
View File
@@ -104,8 +104,8 @@ struct CGroupBPFForeignProgram {
struct CGroupSocketBindItem {
LIST_FIELDS(CGroupSocketBindItem, socket_bind_items);
int32_t address_family;
int32_t ip_protocol;
int address_family;
int ip_protocol;
uint16_t nr_ports;
uint16_t port_min;
};
+3 -2
View File
@@ -15,6 +15,7 @@
#include "errno-util.h"
#include "fd-util.h"
#include "fileio.h"
#include "ip-protocol-list.h"
#include "limits-util.h"
#include "parse-util.h"
#include "path-util.h"
@@ -1895,8 +1896,8 @@ int bus_cgroup_set_property(
if (!IN_SET(family, AF_UNSPEC, AF_INET, AF_INET6))
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "%s= expects INET or INET6 family, if specified.", name);
if (ip_protocol != 0)
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "%s= expects ip protocol equals to 0, for the time being.", name);
if (!IN_SET(ip_protocol, 0, IPPROTO_TCP, IPPROTO_UDP))
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "%s= expects TCP or UDP protocol, if specified.", name);
if (port_min + (uint32_t) nr_ports > (1 << 16))
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "%s= expects maximum port value lesser than 65536.", name);
+6 -37
View File
@@ -47,6 +47,7 @@
#include "log.h"
#include "mountpoint-util.h"
#include "nulstr-util.h"
#include "parse-socket-bind-item.h"
#include "parse-util.h"
#include "path-util.h"
#include "percent-util.h"
@@ -5633,62 +5634,30 @@ int config_parse_cgroup_socket_bind(
void *data,
void *userdata) {
_cleanup_free_ CGroupSocketBindItem *item = NULL;
const char *user_port;
uint16_t nr_ports = 0, port_min = 0;
CGroupSocketBindItem **head = data;
_cleanup_free_ char *word = NULL;
int af, r;
uint16_t nr_ports, port_min;
int af, ip_protocol, r;
if (isempty(rvalue)) {
cgroup_context_remove_socket_bind(head);
return 0;
}
r = extract_first_word(&rvalue, &word, ":", 0);
r = parse_socket_bind_item(rvalue, &af, &ip_protocol, &nr_ports, &port_min);
if (r == -ENOMEM)
return log_oom();
if (r <= 0) {
if (r < 0) {
log_syntax(unit, LOG_WARNING, filename, line, r,
"Unable to parse %s= assignment, ignoring: %s", lvalue, rvalue);
return 0;
}
if (rvalue) {
af = af_from_ipv4_ipv6(word);
if (af == AF_UNSPEC) {
log_syntax(unit, LOG_WARNING, filename, line, 0,
"Only \"ipv4\" and \"ipv6\" protocols are supported, ignoring.");
return 0;
}
user_port = rvalue;
} else {
af = AF_UNSPEC;
user_port = word;
}
if (!streq(user_port, "any")) {
uint16_t port_max;
r = parse_ip_port_range(user_port, &port_min, &port_max);
if (r == -ENOMEM)
return log_oom();
if (r < 0) {
log_syntax(unit, LOG_WARNING, filename, line, r,
"Invalid port or port range, ignoring: %m");
return 0;
}
nr_ports = 1 + port_max - port_min;
}
item = new(CGroupSocketBindItem, 1);
if (!item)
return log_oom();
*item = (CGroupSocketBindItem) {
.address_family = af,
/* No ip protocol specified for now. */
.ip_protocol = 0,
.ip_protocol = ip_protocol,
.nr_ports = nr_ports,
.port_min = port_min,
};
+7 -31
View File
@@ -27,6 +27,7 @@
#include "mountpoint-util.h"
#include "nsflags.h"
#include "numa-util.h"
#include "parse-socket-bind-item.h"
#include "parse-util.h"
#include "path-util.h"
#include "percent-util.h"
@@ -868,42 +869,17 @@ static int bus_append_cgroup_property(sd_bus_message *m, const char *field, cons
if (isempty(eq))
r = sd_bus_message_append(m, "(sv)", field, "a(iiqq)", 0);
else {
/* No ip protocol specified for now. */
int32_t family = AF_UNSPEC, ip_protocol = 0;
const char *address_family, *user_port;
_cleanup_free_ char *word = NULL;
int32_t family, ip_protocol;
uint16_t nr_ports, port_min;
r = extract_first_word(&eq, &word, ":", 0);
r = parse_socket_bind_item(eq, &family, &ip_protocol, &nr_ports, &port_min);
if (r == -ENOMEM)
return log_oom();
if (r < 0)
return log_error_errno(r, "Failed to parse %s: %m", field);
return log_error_errno(r, "Failed to parse %s", field);
address_family = eq ? word : NULL;
if (address_family) {
family = af_from_ipv4_ipv6(address_family);
if (family == AF_UNSPEC)
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
"Only \"ipv4\" and \"ipv6\" protocols are supported");
}
user_port = eq ? eq : word;
if (streq(user_port, "any")) {
r = sd_bus_message_append(m, "(sv)", field, "a(iiqq)", 1, family, ip_protocol, 0, 0);
if (r < 0)
return bus_log_create_error(r);
} else {
uint16_t port_min, port_max;
r = parse_ip_port_range(user_port, &port_min, &port_max);
if (r == -ENOMEM)
return log_oom();
if (r < 0)
return log_error_errno(r, "Invalid port or port range: %s", user_port);
r = sd_bus_message_append(
m, "(sv)", field, "a(iiqq)", 1, family, ip_protocol, port_max - port_min + 1, port_min);
}
r = sd_bus_message_append(
m, "(sv)", field, "a(iiqq)", 1, family, ip_protocol, nr_ports, port_min);
}
if (r < 0)
return bus_log_create_error(r);
+10
View File
@@ -65,3 +65,13 @@ int parse_ip_protocol(const char *s) {
return i;
}
const char *ip_protocol_to_tcp_udp(int id) {
return IN_SET(id, IPPROTO_TCP, IPPROTO_UDP) ?
ip_protocol_to_name(id) : NULL;
}
int ip_protocol_from_tcp_udp(const char *ip_protocol) {
int id = ip_protocol_from_name(ip_protocol);
return IN_SET(id, IPPROTO_TCP, IPPROTO_UDP) ? id : -EINVAL;
}
+3
View File
@@ -4,3 +4,6 @@
const char *ip_protocol_to_name(int id);
int ip_protocol_from_name(const char *name);
int parse_ip_protocol(const char *s);
const char *ip_protocol_to_tcp_udp(int id);
int ip_protocol_from_tcp_udp(const char *ip_protocol);
+2
View File
@@ -225,6 +225,8 @@ shared_sources = files('''
pager.h
parse-argument.c
parse-argument.h
parse-socket-bind-item.c
parse-socket-bind-item.h
pe-header.h
pkcs11-util.c
pkcs11-util.h
+146
View File
@@ -0,0 +1,146 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */
#include "af-list.h"
#include "extract-word.h"
#include "ip-protocol-list.h"
#include "parse-socket-bind-item.h"
#include "parse-util.h"
static int parse_af_token(
const char *token,
int *family,
int *ip_protocol,
uint16_t *nr_ports,
uint16_t *port_min) {
int af;
assert(token);
assert(family);
af = af_from_ipv4_ipv6(token);
if (af == AF_UNSPEC)
return -EINVAL;
*family = af;
return 0;
}
static int parse_ip_protocol_token(
const char *token,
int *family,
int *ip_protocol,
uint16_t *nr_ports,
uint16_t *port_min) {
int proto;
assert(token);
assert(ip_protocol);
proto = ip_protocol_from_tcp_udp(token);
if (proto < 0)
return -EINVAL;
*ip_protocol = proto;
return 0;
}
static int parse_ip_ports_token(
const char *token,
int *family,
int *ip_protocol,
uint16_t *nr_ports,
uint16_t *port_min) {
assert(token);
assert(nr_ports);
assert(port_min);
if (streq(token, "any"))
*nr_ports = *port_min = 0;
else {
uint16_t mn = 0, mx = 0;
int r = parse_ip_port_range(token, &mn, &mx);
if (r < 0)
return r;
*nr_ports = mx - mn + 1;
*port_min = mn;
}
return 0;
}
typedef int (*parse_token_f)(
const char *,
int *,
int *,
uint16_t *,
uint16_t *);
int parse_socket_bind_item(
const char *str,
int *address_family,
int *ip_protocol,
uint16_t *nr_ports,
uint16_t *port_min) {
/* Order of token parsers is important. */
const parse_token_f parsers[] = {
&parse_af_token,
&parse_ip_protocol_token,
&parse_ip_ports_token,
};
parse_token_f const *parser_ptr = parsers;
int af = AF_UNSPEC, proto = 0, r;
uint16_t nr = 0, mn = 0;
const char *p = str;
assert(str);
assert(address_family);
assert(ip_protocol);
assert(nr_ports);
assert(port_min);
if (isempty(p))
return -EINVAL;
for (;;) {
_cleanup_free_ char *token = NULL;
r = extract_first_word(&p, &token, ":", EXTRACT_DONT_COALESCE_SEPARATORS);
if (r == 0)
break;
if (r < 0)
return r;
if (isempty(token))
return -EINVAL;
while (parser_ptr != parsers + ELEMENTSOF(parsers)) {
r = (*parser_ptr)(token, &af, &proto, &nr, &mn);
if (r == -ENOMEM)
return r;
++parser_ptr;
/* Continue to next token if parsing succeeded,
* otherwise apply next parser to the same token.
*/
if (r >= 0)
break;
}
if (parser_ptr == parsers + ELEMENTSOF(parsers))
break;
}
/* Failed to parse a token. */
if (r < 0)
return r;
/* Parsers applied succesfully, but end of the string not reached. */
if (p)
return -EINVAL;
*address_family = af;
*ip_protocol = proto;
*nr_ports = nr;
*port_min = mn;
return 0;
}
+12
View File
@@ -0,0 +1,12 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */
#pragma once
#include <stdint.h>
int parse_socket_bind_item(
const char *str,
int *address_family,
int *ip_protocol,
uint16_t *nr_ports,
uint16_t *port_min);
+14 -5
View File
@@ -17,6 +17,7 @@
#include "hexdecoct.h"
#include "hostname-util.h"
#include "in-addr-util.h"
#include "ip-protocol-list.h"
#include "journal-file.h"
#include "list.h"
#include "locale-util.h"
@@ -1718,19 +1719,27 @@ static int print_property(const char *name, const char *expected_value, sd_bus_m
if (r < 0)
return bus_log_parse_error(r);
while ((r = sd_bus_message_read(m, "(iiqq)", &af, &ip_protocol, &nr_ports, &port_min)) > 0) {
const char *family, *colon;
const char *family, *colon1, *protocol = "", *colon2 = "";
family = strempty(af_to_ipv4_ipv6(af));
colon = isempty(family) ? "" : ":";
colon1 = isempty(family) ? "" : ":";
if (ip_protocol != 0) {
protocol = ip_protocol_to_tcp_udp(ip_protocol);
colon2 = "";
}
if (nr_ports == 0)
bus_print_property_valuef(name, expected_value, flags, "%s%sany", family, colon);
bus_print_property_valuef(name, expected_value, flags, "%s%s%s%sany",
family, colon1, protocol, colon2);
else if (nr_ports == 1)
bus_print_property_valuef(
name, expected_value, flags, "%s%s%hu", family, colon, port_min);
name, expected_value, flags, "%s%s%s%s%hu",
family, colon1, protocol, colon2, port_min);
else
bus_print_property_valuef(
name, expected_value, flags, "%s%s%hu-%hu", family, colon, port_min,
name, expected_value, flags, "%s%s%s%s%hu-%hu",
family, colon1, protocol, colon2, port_min,
(uint16_t) (port_min + nr_ports - 1));
}
if (r < 0)
+2
View File
@@ -242,6 +242,8 @@ tests += [
[['src/test/test-parse-argument.c']],
[['src/test/test-parse-socket-bind-item.c']],
[['src/test/test-parse-util.c']],
[['src/test/test-sysctl-util.c']],
+91
View File
@@ -0,0 +1,91 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */
#include <linux/in.h>
#include <sys/socket.h>
#include <stdio.h>
#include "macro.h"
#include "parse-socket-bind-item.h"
static void test_valid_item(
const char *str,
int expected_af,
int expected_ip_protocol,
uint16_t expected_nr_ports,
uint16_t expected_port_min) {
uint16_t nr_ports, port_min;
int af, ip_protocol;
assert_se(parse_socket_bind_item(str, &af, &ip_protocol, &nr_ports, &port_min) >= 0);
assert_se(af == expected_af);
assert_se(ip_protocol == expected_ip_protocol);
assert_se(nr_ports == expected_nr_ports);
assert_se(port_min == expected_port_min);
log_info("%s: \"%s\" ok", __func__, str);
}
static void test_invalid_item(const char *str) {
uint16_t nr_ports, port_min;
int af, ip_protocol;
assert_se(parse_socket_bind_item(str, &af, &ip_protocol, &nr_ports, &port_min) == -EINVAL);
log_info("%s: \"%s\" ok", __func__, str);
}
int main(int argc, char *argv[]) {
test_valid_item("any", AF_UNSPEC, 0, 0, 0);
test_valid_item("ipv4", AF_INET, 0, 0, 0);
test_valid_item("ipv6", AF_INET6, 0, 0, 0);
test_valid_item("ipv4:any", AF_INET, 0, 0, 0);
test_valid_item("ipv6:any", AF_INET6, 0, 0, 0);
test_valid_item("tcp", AF_UNSPEC, IPPROTO_TCP, 0, 0);
test_valid_item("udp", AF_UNSPEC, IPPROTO_UDP, 0, 0);
test_valid_item("tcp:any", AF_UNSPEC, IPPROTO_TCP, 0, 0);
test_valid_item("udp:any", AF_UNSPEC, IPPROTO_UDP, 0, 0);
test_valid_item("6666", AF_UNSPEC, 0, 1, 6666);
test_valid_item("6666-6667", AF_UNSPEC, 0, 2, 6666);
test_valid_item("65535", AF_UNSPEC, 0, 1, 65535);
test_valid_item("1-65535", AF_UNSPEC, 0, 65535, 1);
test_valid_item("ipv4:tcp", AF_INET, IPPROTO_TCP, 0, 0);
test_valid_item("ipv4:udp", AF_INET, IPPROTO_UDP, 0, 0);
test_valid_item("ipv6:tcp", AF_INET6, IPPROTO_TCP, 0, 0);
test_valid_item("ipv6:udp", AF_INET6, IPPROTO_UDP, 0, 0);
test_valid_item("ipv4:6666", AF_INET, 0, 1, 6666);
test_valid_item("ipv6:6666", AF_INET6, 0, 1, 6666);
test_valid_item("tcp:6666", AF_UNSPEC, IPPROTO_TCP, 1, 6666);
test_valid_item("udp:6666", AF_UNSPEC, IPPROTO_UDP, 1, 6666);
test_valid_item("ipv4:tcp:6666", AF_INET, IPPROTO_TCP, 1, 6666);
test_valid_item("ipv6:tcp:6666", AF_INET6, IPPROTO_TCP, 1, 6666);
test_valid_item("ipv6:udp:6666-6667", AF_INET6, IPPROTO_UDP, 2, 6666);
test_valid_item("ipv6:tcp:any", AF_INET6, IPPROTO_TCP, 0, 0);
test_invalid_item("");
test_invalid_item(":");
test_invalid_item("::");
test_invalid_item("any:");
test_invalid_item("meh");
test_invalid_item("zupa:meh");
test_invalid_item("zupa:meh:eh");
test_invalid_item("ip");
test_invalid_item("dccp");
test_invalid_item("ipv6meh");
test_invalid_item("ipv6::");
test_invalid_item("ipv6:ipv6");
test_invalid_item("ipv6:icmp");
test_invalid_item("ipv6:tcp:0");
test_invalid_item("65536");
test_invalid_item("0-65535");
test_invalid_item("ipv6:tcp:6666-6665");
test_invalid_item("ipv6:tcp:6666-100000");
test_invalid_item("ipv6::6666");
test_invalid_item("ipv6:tcp:any:");
test_invalid_item("ipv6:tcp:any:ipv6");
test_invalid_item("ipv6:tcp:6666:zupa");
test_invalid_item("ipv6:tcp:6666:any");
test_invalid_item("ipv6:tcp:6666 zupa");
test_invalid_item("ipv6:tcp:6666: zupa");
test_invalid_item("ipv6:tcp:6666\n zupa");
return 0;
}
+5
View File
@@ -146,6 +146,11 @@ int main(int argc, char *argv[]) {
assert_se(test_socket_bind(m, "socket_bind_test.service", netcat_path, "6666", STRV_MAKE("6667", "6668", ""), STRV_MAKE("any")) >= 0);
assert_se(test_socket_bind(m, "socket_bind_test.service", netcat_path, "7777", STRV_MAKE_EMPTY, STRV_MAKE_EMPTY) >= 0);
assert_se(test_socket_bind(m, "socket_bind_test.service", netcat_path, "8888", STRV_MAKE("any"), STRV_MAKE("any")) >= 0);
assert_se(test_socket_bind(m, "socket_bind_test.service", netcat_path, "8888", STRV_MAKE("ipv6:tcp:8888-8889"), STRV_MAKE("any")) >= 0);
assert_se(test_socket_bind(m, "socket_bind_test.service", netcat_path, "10000", STRV_MAKE("ipv6:udp:9999-10000"), STRV_MAKE("any")) >= 0);
assert_se(test_socket_bind(m, "socket_bind_test.service", netcat_path, "6666", STRV_MAKE("ipv4:tcp:6666"), STRV_MAKE("any")) >= 0);
assert_se(test_socket_bind(m, "socket_bind_test.service", netcat_path, "6666", STRV_MAKE("ipv4:udp:6666"), STRV_MAKE("any")) >= 0);
assert_se(test_socket_bind(m, "socket_bind_test.service", netcat_path, "6666", STRV_MAKE("tcp:6666"), STRV_MAKE("any")) >= 0);
return 0;
}