summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorSusant Sahani <ssahani@gmail.com>2018-11-27 10:58:54 +0530
committerSusant Sahani <ssahani@gmail.com>2018-11-28 20:06:28 +0530
commit926062f08345c02d360414feae58c964de2b6415 (patch)
tree010ab395d80fa2c7cc092fd87428fd9c4769c684 /src
parent59a2a18e27435ed00741fc8703e19866de37e3d3 (diff)
downloadsystemd-926062f08345c02d360414feae58c964de2b6415.tar.gz
networkd: add support to configure ip rule port range and protocol.
Please see: iprule: support for ip_proto, sport and dport match options https://git.kernel.org/pub/scm/network/iproute2/iproute2.git/commit/?id=f686f764682745daf6a93b0a6330ba42a961f858 Closes 10622
Diffstat (limited to 'src')
-rw-r--r--src/basic/missing.h18
-rw-r--r--src/basic/parse-util.c20
-rw-r--r--src/basic/parse-util.h1
-rw-r--r--src/libsystemd/sd-netlink/netlink-message.c19
-rw-r--r--src/libsystemd/sd-netlink/netlink-types.c4
-rw-r--r--src/network/networkd-link.c3
-rw-r--r--src/network/networkd-manager.c25
-rw-r--r--src/network/networkd-network-gperf.gperf3
-rw-r--r--src/network/networkd-routing-policy-rule.c197
-rw-r--r--src/network/networkd-routing-policy-rule.h16
-rw-r--r--src/systemd/sd-netlink.h1
11 files changed, 294 insertions, 13 deletions
diff --git a/src/basic/missing.h b/src/basic/missing.h
index c0c1d40665..99a463b7b6 100644
--- a/src/basic/missing.h
+++ b/src/basic/missing.h
@@ -9,6 +9,7 @@
#include <linux/audit.h>
#include <linux/capability.h>
#include <linux/falloc.h>
+#include <linux/fib_rules.h>
#include <linux/if_link.h>
#include <linux/input.h>
#include <linux/loop.h>
@@ -988,7 +989,7 @@ struct input_mask {
#define IFLA_BRPORT_MAX (__IFLA_BRPORT_MAX - 1)
#endif
-#if !HAVE_FRA_UID_RANGE
+#if !HAVE_FRA_DPORT_RANGE
#define FRA_UNSPEC 0
#define FRA_DST 1
#define FRA_SRC 2
@@ -1010,7 +1011,11 @@ struct input_mask {
#define FRA_PAD 18
#define FRA_L3MDEV 19
#define FRA_UID_RANGE 20
-#define __FRA_MAX 12
+#define FRA_PROTOCOL 21
+#define FRA_IP_PROTO 22
+#define FRA_SPORT_RANGE 23
+#define FRA_DPORT_RANGE 24
+#define __FRA_MAX 25
#define FRA_MAX (__FRA_MAX - 1)
#endif
@@ -1311,6 +1316,15 @@ struct fib_rule_uid_range {
#endif
+#if ! HAVE_STRUCT_FIB_RULE_PORT_RANGE
+
+struct fib_rule_port_range {
+ __u16 start;
+ __u16 end;
+};
+
+#endif
+
#endif
#ifndef SOL_ALG
diff --git a/src/basic/parse-util.c b/src/basic/parse-util.c
index a9085348b5..ce8bb12670 100644
--- a/src/basic/parse-util.c
+++ b/src/basic/parse-util.c
@@ -710,6 +710,26 @@ int parse_ip_port(const char *s, uint16_t *ret) {
return 0;
}
+int parse_ip_port_range(const char *s, uint16_t *low, uint16_t *high) {
+ unsigned l, h;
+ int r;
+
+ r = parse_range(s, &l, &h);
+ if (r < 0)
+ return r;
+
+ if (l <= 0 || l > 65535 || h <= 0 || h > 65535)
+ return -EINVAL;
+
+ if (h < l)
+ return -EINVAL;
+
+ *low = l;
+ *high = h;
+
+ return 0;
+}
+
int parse_dev(const char *s, dev_t *ret) {
unsigned x, y;
dev_t d;
diff --git a/src/basic/parse-util.h b/src/basic/parse-util.h
index f3267f4cfe..e47641b429 100644
--- a/src/basic/parse-util.h
+++ b/src/basic/parse-util.h
@@ -115,5 +115,6 @@ int parse_permille(const char *p);
int parse_nice(const char *p, int *ret);
int parse_ip_port(const char *s, uint16_t *ret);
+int parse_ip_port_range(const char *s, uint16_t *low, uint16_t *high);
int parse_oom_score_adjust(const char *s, int *ret);
diff --git a/src/libsystemd/sd-netlink/netlink-message.c b/src/libsystemd/sd-netlink/netlink-message.c
index 487a58ca73..b0b25639f4 100644
--- a/src/libsystemd/sd-netlink/netlink-message.c
+++ b/src/libsystemd/sd-netlink/netlink-message.c
@@ -562,6 +562,25 @@ static int netlink_message_read_internal(sd_netlink_message *m, unsigned short t
return RTA_PAYLOAD(rta);
}
+int sd_netlink_message_read(sd_netlink_message *m, unsigned short type, size_t size, void *data) {
+ void *attr_data;
+ int r;
+
+ assert_return(m, -EINVAL);
+
+ r = netlink_message_read_internal(m, type, &attr_data, NULL);
+ if (r < 0)
+ return r;
+
+ if ((size_t) r < size)
+ return -EIO;
+
+ if (data)
+ memcpy(data, attr_data, size);
+
+ return 0;
+}
+
int sd_netlink_message_read_string(sd_netlink_message *m, unsigned short type, const char **data) {
int r;
void *attr_data;
diff --git a/src/libsystemd/sd-netlink/netlink-types.c b/src/libsystemd/sd-netlink/netlink-types.c
index 307b5aa343..823e654d11 100644
--- a/src/libsystemd/sd-netlink/netlink-types.c
+++ b/src/libsystemd/sd-netlink/netlink-types.c
@@ -641,6 +641,10 @@ static const NLType rtnl_routing_policy_rule_types[] = {
[FRA_PAD] = { .type = NETLINK_TYPE_U32 },
[FRA_L3MDEV] = { .type = NETLINK_TYPE_U64 },
[FRA_UID_RANGE] = { .size = sizeof(struct fib_rule_uid_range) },
+ [FRA_PROTOCOL] = { .type = NETLINK_TYPE_U8 },
+ [FRA_IP_PROTO] = { .type = NETLINK_TYPE_U8 },
+ [FRA_SPORT_RANGE] = { .size = sizeof(struct fib_rule_port_range) },
+ [FRA_DPORT_RANGE] = { .size = sizeof(struct fib_rule_port_range) },
};
static const NLTypeSystem rtnl_routing_policy_rule_type_system = {
diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c
index 4af1a559b2..02b102a47f 100644
--- a/src/network/networkd-link.c
+++ b/src/network/networkd-link.c
@@ -794,7 +794,8 @@ static int link_set_routing_policy_rule(Link *link) {
LIST_FOREACH(rules, rule, link->network->rules) {
r = routing_policy_rule_get(link->manager, rule->family, &rule->from, rule->from_prefixlen, &rule->to,
- rule->to_prefixlen, rule->tos, rule->fwmark, rule->table, rule->iif, rule->oif, &rrule);
+ rule->to_prefixlen, rule->tos, rule->fwmark, rule->table, rule->iif, rule->oif,
+ rule->protocol, &rule->sport, &rule->dport, &rrule);
if (r == 0) {
(void) routing_policy_rule_make_local(link->manager, rrule);
continue;
diff --git a/src/network/networkd-manager.c b/src/network/networkd-manager.c
index fe481f1c02..3b1ae0b41f 100644
--- a/src/network/networkd-manager.c
+++ b/src/network/networkd-manager.c
@@ -697,7 +697,8 @@ static int manager_rtnl_process_link(sd_netlink *rtnl, sd_netlink_message *messa
}
int manager_rtnl_process_rule(sd_netlink *rtnl, sd_netlink_message *message, void *userdata) {
- uint8_t tos = 0, to_prefixlen = 0, from_prefixlen = 0;
+ uint8_t tos = 0, to_prefixlen = 0, from_prefixlen = 0, protocol = 0;
+ struct fib_rule_port_range sport = {}, dport = {};
union in_addr_union to = {}, from = {};
RoutingPolicyRule *rule = NULL;
uint32_t fwmark = 0, table = 0;
@@ -829,12 +830,30 @@ int manager_rtnl_process_rule(sd_netlink *rtnl, sd_netlink_message *message, voi
return 0;
}
- (void) routing_policy_rule_get(m, family, &from, from_prefixlen, &to, to_prefixlen, tos, fwmark, table, iif, oif, &rule);
+ r = sd_netlink_message_read_u8(message, FRA_IP_PROTO, &protocol);
+ if (r < 0 && r != -ENODATA) {
+ log_warning_errno(r, "rtnl: could not get FRA_IP_PROTO attribute, ignoring: %m");
+ return 0;
+ }
+
+ r = sd_netlink_message_read(message, FRA_SPORT_RANGE, sizeof(sport), (void *) &sport);
+ if (r < 0 && r != -ENODATA) {
+ log_warning_errno(r, "rtnl: could not get FRA_SPORT_RANGE attribute, ignoring: %m");
+ return 0;
+ }
+
+ r = sd_netlink_message_read(message, FRA_DPORT_RANGE, sizeof(dport), (void *) &dport);
+ if (r < 0 && r != -ENODATA) {
+ log_warning_errno(r, "rtnl: could not get FRA_DPORT_RANGE attribute, ignoring: %m");
+ return 0;
+ }
+
+ (void) routing_policy_rule_get(m, family, &from, from_prefixlen, &to, to_prefixlen, tos, fwmark, table, iif, oif, protocol, &sport, &dport, &rule);
switch (type) {
case RTM_NEWRULE:
if (!rule) {
- r = routing_policy_rule_add_foreign(m, family, &from, from_prefixlen, &to, to_prefixlen, tos, fwmark, table, iif, oif, &rule);
+ r = routing_policy_rule_add_foreign(m, family, &from, from_prefixlen, &to, to_prefixlen, tos, fwmark, table, iif, oif, protocol, &sport, &dport, &rule);
if (r < 0) {
log_warning_errno(r, "Could not add rule, ignoring: %m");
return 0;
diff --git a/src/network/networkd-network-gperf.gperf b/src/network/networkd-network-gperf.gperf
index 8bbdd290ad..378b63af8c 100644
--- a/src/network/networkd-network-gperf.gperf
+++ b/src/network/networkd-network-gperf.gperf
@@ -101,6 +101,9 @@ RoutingPolicyRule.From, config_parse_routing_policy_rule_prefix,
RoutingPolicyRule.To, config_parse_routing_policy_rule_prefix, 0, 0
RoutingPolicyRule.IncomingInterface, config_parse_routing_policy_rule_device, 0, 0
RoutingPolicyRule.OutgoingInterface, config_parse_routing_policy_rule_device, 0, 0
+RoutingPolicyRule.Protocol, config_parse_routing_policy_rule_protocol, 0, 0
+RoutingPolicyRule.SourcePort, config_parse_routing_policy_rule_port_range, 0, 0
+RoutingPolicyRule.DestinationPort, config_parse_routing_policy_rule_port_range, 0, 0
Route.Gateway, config_parse_gateway, 0, 0
Route.Destination, config_parse_destination, 0, 0
Route.Source, config_parse_destination, 0, 0
diff --git a/src/network/networkd-routing-policy-rule.c b/src/network/networkd-routing-policy-rule.c
index 683c166289..1b2222cada 100644
--- a/src/network/networkd-routing-policy-rule.c
+++ b/src/network/networkd-routing-policy-rule.c
@@ -10,6 +10,7 @@
#include "netlink-util.h"
#include "networkd-manager.h"
#include "parse-util.h"
+#include "socket-protocol-list.h"
#include "socket-util.h"
#include "string-util.h"
#include "strv.h"
@@ -76,6 +77,10 @@ static void routing_policy_rule_hash_func(const void *b, struct siphash *state)
siphash24_compress(&rule->fwmark, sizeof(rule->fwmark), state);
siphash24_compress(&rule->table, sizeof(rule->table), state);
+ siphash24_compress(&rule->protocol, sizeof(rule->protocol), state);
+ siphash24_compress(&rule->sport, sizeof(rule->sport), state);
+ siphash24_compress(&rule->dport, sizeof(rule->dport), state);
+
if (rule->iif)
siphash24_compress(rule->iif, strlen(rule->iif), state);
@@ -128,6 +133,18 @@ static int routing_policy_rule_compare_func(const void *_a, const void *_b) {
if (!r)
return r;
+ r = CMP(a->protocol, b->protocol);
+ if (r != 0)
+ return r;
+
+ r = memcmp(&a->sport, &b->sport, sizeof(a->sport));
+ if (r != 0)
+ return r;
+
+ r = memcmp(&a->dport, &b->dport, sizeof(a->dport));
+ if (r != 0)
+ return r;
+
r = memcmp(&a->from, &b->from, FAMILY_ADDRESS_SIZE(a->family));
if (r != 0)
return r;
@@ -156,6 +173,9 @@ int routing_policy_rule_get(Manager *m,
uint32_t table,
const char *iif,
const char *oif,
+ uint8_t protocol,
+ struct fib_rule_port_range *sport,
+ struct fib_rule_port_range *dport,
RoutingPolicyRule **ret) {
RoutingPolicyRule rule, *existing;
@@ -172,7 +192,10 @@ int routing_policy_rule_get(Manager *m,
.fwmark = fwmark,
.table = table,
.iif = (char*) iif,
- .oif = (char*) oif
+ .oif = (char*) oif,
+ .protocol = protocol,
+ .sport = *sport,
+ .dport = *dport,
};
existing = set_get(m->rules, &rule);
@@ -222,6 +245,9 @@ static int routing_policy_rule_add_internal(Manager *m,
uint32_t table,
const char *_iif,
const char *_oif,
+ uint8_t protocol,
+ const struct fib_rule_port_range *sport,
+ const struct fib_rule_port_range *dport,
RoutingPolicyRule **ret) {
_cleanup_(routing_policy_rule_freep) RoutingPolicyRule *rule = NULL;
@@ -257,6 +283,9 @@ static int routing_policy_rule_add_internal(Manager *m,
rule->table = table;
rule->iif = iif;
rule->oif = oif;
+ rule->protocol = protocol;
+ rule->sport = *sport;
+ rule->dport = *dport;
r = set_ensure_allocated(rules, &routing_policy_rule_hash_ops);
if (r < 0)
@@ -286,9 +315,12 @@ int routing_policy_rule_add(Manager *m,
uint32_t table,
const char *iif,
const char *oif,
+ uint8_t protocol,
+ const struct fib_rule_port_range *sport,
+ const struct fib_rule_port_range *dport,
RoutingPolicyRule **ret) {
- return routing_policy_rule_add_internal(m, &m->rules, family, from, from_prefixlen, to, to_prefixlen, tos, fwmark, table, iif, oif, ret);
+ return routing_policy_rule_add_internal(m, &m->rules, family, from, from_prefixlen, to, to_prefixlen, tos, fwmark, table, iif, oif, protocol, sport, dport, ret);
}
int routing_policy_rule_add_foreign(Manager *m,
@@ -302,8 +334,11 @@ int routing_policy_rule_add_foreign(Manager *m,
uint32_t table,
const char *iif,
const char *oif,
+ uint8_t protocol,
+ const struct fib_rule_port_range *sport,
+ const struct fib_rule_port_range *dport,
RoutingPolicyRule **ret) {
- return routing_policy_rule_add_internal(m, &m->rules_foreign, family, from, from_prefixlen, to, to_prefixlen, tos, fwmark, table, iif, oif, ret);
+ return routing_policy_rule_add_internal(m, &m->rules_foreign, family, from, from_prefixlen, to, to_prefixlen, tos, fwmark, table, iif, oif, protocol, sport, dport, ret);
}
static int routing_policy_rule_remove_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userdata) {
@@ -544,6 +579,22 @@ int routing_policy_rule_configure(RoutingPolicyRule *rule, Link *link, sd_netlin
return log_error_errno(r, "Could not append FRA_OIFNAME attribute: %m");
}
+ r = sd_netlink_message_append_u8(m, FRA_IP_PROTO, rule->protocol);
+ if (r < 0)
+ return log_error_errno(r, "Could not append FRA_IP_PROTO attribute: %m");
+
+ if (rule->sport.start != 0 || rule->sport.end != 0) {
+ r = sd_netlink_message_append_data(m, FRA_SPORT_RANGE, &rule->sport, sizeof(rule->sport));
+ if (r < 0)
+ return log_error_errno(r, "Could not append FRA_SPORT_RANGE attribute: %m");
+ }
+
+ if (rule->dport.start != 0 || rule->dport.end != 0) {
+ r = sd_netlink_message_append_data(m, FRA_DPORT_RANGE, &rule->dport, sizeof(rule->dport));
+ if (r < 0)
+ return log_error_errno(r, "Could not append FRA_DPORT_RANGE attribute: %m");
+ }
+
rule->link = link;
r = sd_netlink_call_async(link->manager->rtnl, NULL, m, callback,
@@ -554,7 +605,7 @@ int routing_policy_rule_configure(RoutingPolicyRule *rule, Link *link, sd_netlin
link_ref(link);
r = routing_policy_rule_add(link->manager, rule->family, &rule->from, rule->from_prefixlen, &rule->to,
- rule->to_prefixlen, rule->tos, rule->fwmark, rule->table, rule->iif, rule->oif, NULL);
+ rule->to_prefixlen, rule->tos, rule->fwmark, rule->table, rule->iif, rule->oif, rule->protocol, &rule->sport, &rule->dport, NULL);
if (r < 0)
return log_error_errno(r, "Could not add rule: %m");
@@ -836,6 +887,95 @@ int config_parse_routing_policy_rule_device(
return 0;
}
+int config_parse_routing_policy_rule_port_range(
+ const char *unit,
+ const char *filename,
+ unsigned line,
+ const char *section,
+ unsigned section_line,
+ const char *lvalue,
+ int ltype,
+ const char *rvalue,
+ void *data,
+ void *userdata) {
+ _cleanup_(routing_policy_rule_freep) RoutingPolicyRule *n = NULL;
+ Network *network = userdata;
+ uint16_t low, high;
+ int r;
+
+ assert(filename);
+ assert(section);
+ assert(lvalue);
+ assert(rvalue);
+ assert(data);
+
+ r = routing_policy_rule_new_static(network, filename, section_line, &n);
+ if (r < 0)
+ return r;
+
+ r = parse_ip_port_range(rvalue, &low, &high);
+ if (r < 0) {
+ log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse routing policy rule port range '%s'", rvalue);
+ return 0;
+ }
+
+ if (streq(lvalue, "SourcePort")) {
+ n->sport.start = low;
+ n->sport.end = high;
+ } else {
+ n->dport.start = low;
+ n->dport.end = high;
+ }
+
+ n = NULL;
+
+ return 0;
+}
+
+int config_parse_routing_policy_rule_protocol(
+ const char *unit,
+ const char *filename,
+ unsigned line,
+ const char *section,
+ unsigned section_line,
+ const char *lvalue,
+ int ltype,
+ const char *rvalue,
+ void *data,
+ void *userdata) {
+
+ _cleanup_(routing_policy_rule_freep) RoutingPolicyRule *n = NULL;
+ Network *network = userdata;
+ int r;
+
+ assert(filename);
+ assert(section);
+ assert(lvalue);
+ assert(rvalue);
+ assert(data);
+
+ r = routing_policy_rule_new_static(network, filename, section_line, &n);
+ if (r < 0)
+ return r;
+
+ r = socket_protocol_from_name(rvalue);
+ if (r < 0) {
+ log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse routing policy rule protocol, ignoring: %s", rvalue);
+ return 0;
+ }
+
+ if (!IN_SET(r, IPPROTO_TCP, IPPROTO_UDP, IPPROTO_SCTP)) {
+ log_syntax(unit, LOG_ERR, filename, line, 0, "Invalid protocol '%s'. Protocol should be tcp/udp/sctp, ignoring", rvalue);
+ return 0;
+ }
+
+ n->protocol = r;
+
+ n = NULL;
+
+ return 0;
+}
+
static int routing_policy_rule_read_full_file(const char *state_file, char **ret) {
_cleanup_free_ char *s = NULL;
size_t size;
@@ -918,6 +1058,27 @@ int routing_policy_serialize_rules(Set *rules, FILE *f) {
space = true;
}
+ if (rule->protocol != 0) {
+ fprintf(f, "%sprotocol=%hhu",
+ space ? " " : "",
+ rule->protocol);
+ space = true;
+ }
+
+ if (rule->sport.start != 0 || rule->sport.end != 0) {
+ fprintf(f, "%ssourcesport=%hhu-%hhu",
+ space ? " " : "",
+ rule->sport.start, rule->sport.end);
+ space = true;
+ }
+
+ if (rule->dport.start != 0 || rule->dport.end != 0) {
+ fprintf(f, "%sdestinationport=%hhu-%hhu",
+ space ? " " : "",
+ rule->dport.start, rule->dport.end);
+ space = true;
+ }
+
fprintf(f, "%stable=%"PRIu32 "\n",
space ? " " : "",
rule->table);
@@ -929,6 +1090,7 @@ int routing_policy_serialize_rules(Set *rules, FILE *f) {
int routing_policy_load_rules(const char *state_file, Set **rules) {
_cleanup_strv_free_ char **l = NULL;
_cleanup_free_ char *data = NULL;
+ uint16_t low = 0, high = 0;
const char *p;
char **i;
int r;
@@ -1023,6 +1185,33 @@ int routing_policy_load_rules(const char *state_file, Set **rules) {
if (free_and_strdup(&rule->oif, b) < 0)
return log_oom();
+ } else if (streq(a, "protocol")) {
+ r = safe_atou8(b, &rule->protocol);
+ if (r < 0) {
+ log_error_errno(r, "Failed to parse RPDB rule protocol, ignoring: %s", b);
+ continue;
+ }
+ } else if (streq(a, "sourceport")) {
+
+ r = parse_ip_port_range(b, &low, &high);
+ if (r < 0) {
+ log_error_errno(r, "Invalid routing policy rule source port range, ignoring assignment:'%s'", b);
+ continue;
+ }
+
+ rule->sport.start = low;
+ rule->sport.end = high;
+
+ } else if (streq(a, "destinationport")) {
+
+ r = parse_ip_port_range(b, &low, &high);
+ if (r < 0) {
+ log_error_errno(r, "Invalid routing policy rule destination port range, ignoring assignment:'%s'", b);
+ continue;
+ }
+
+ rule->dport.start = low;
+ rule->dport.end = high;
}
}
diff --git a/src/network/networkd-routing-policy-rule.h b/src/network/networkd-routing-policy-rule.h
index 2e7474ef56..3bb3b4cd81 100644
--- a/src/network/networkd-routing-policy-rule.h
+++ b/src/network/networkd-routing-policy-rule.h
@@ -2,6 +2,7 @@
#pragma once
#include <inttypes.h>
+#include <linux/fib_rules.h>
#include <stdbool.h>
#include "in-addr-util.h"
@@ -24,6 +25,7 @@ struct RoutingPolicyRule {
NetworkConfigSection *section;
uint8_t tos;
+ uint8_t protocol;
uint32_t table;
uint32_t fwmark;
@@ -40,6 +42,9 @@ struct RoutingPolicyRule {
union in_addr_union to;
union in_addr_union from;
+ struct fib_rule_port_range sport;
+ struct fib_rule_port_range dport;
+
LIST_FIELDS(RoutingPolicyRule, rules);
};
@@ -54,11 +59,14 @@ int link_routing_policy_rule_remove_handler(sd_netlink *rtnl, sd_netlink_message
int link_routing_policy_rule_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userdata);
int routing_policy_rule_add(Manager *m, int family, const union in_addr_union *from, uint8_t from_prefixlen, const union in_addr_union *to, uint8_t to_prefixlen,
- uint8_t tos, uint32_t fwmark, uint32_t table, const char *iif, const char *oif, RoutingPolicyRule **ret);
+ uint8_t tos, uint32_t fwmark, uint32_t table, const char *iif, const char *oif, uint8_t protocol, const struct fib_rule_port_range *sport,
+ const struct fib_rule_port_range *dport, RoutingPolicyRule **ret);
int routing_policy_rule_add_foreign(Manager *m, int family, const union in_addr_union *from, uint8_t from_prefixlen, const union in_addr_union *to, uint8_t to_prefixlen,
- uint8_t tos, uint32_t fwmark, uint32_t table, const char *iif, const char *oif, RoutingPolicyRule **ret);
+ uint8_t tos, uint32_t fwmark, uint32_t table, const char *iif, const char *oif, uint8_t protocol, const struct fib_rule_port_range *sport,
+ const struct fib_rule_port_range *dport, RoutingPolicyRule **ret);
int routing_policy_rule_get(Manager *m, int family, const union in_addr_union *from, uint8_t from_prefixlen, const union in_addr_union *to, uint8_t to_prefixlen, uint8_t tos,
- uint32_t fwmark, uint32_t table, const char *iif, const char *oif, RoutingPolicyRule **ret);
+ uint32_t fwmark, uint32_t table, const char *iif, const char *oif, uint8_t protocol, struct fib_rule_port_range *sport,
+ struct fib_rule_port_range *dport, RoutingPolicyRule **ret);
int routing_policy_rule_make_local(Manager *m, RoutingPolicyRule *rule);
int routing_policy_serialize_rules(Set *rules, FILE *f);
int routing_policy_load_rules(const char *state_file, Set **rules);
@@ -70,3 +78,5 @@ CONFIG_PARSER_PROTOTYPE(config_parse_routing_policy_rule_fwmark_mask);
CONFIG_PARSER_PROTOTYPE(config_parse_routing_policy_rule_prefix);
CONFIG_PARSER_PROTOTYPE(config_parse_routing_policy_rule_priority);
CONFIG_PARSER_PROTOTYPE(config_parse_routing_policy_rule_device);
+CONFIG_PARSER_PROTOTYPE(config_parse_routing_policy_rule_port_range);
+CONFIG_PARSER_PROTOTYPE(config_parse_routing_policy_rule_protocol);
diff --git a/src/systemd/sd-netlink.h b/src/systemd/sd-netlink.h
index 276953eb8e..e1b89559a8 100644
--- a/src/systemd/sd-netlink.h
+++ b/src/systemd/sd-netlink.h
@@ -85,6 +85,7 @@ int sd_netlink_message_open_container(sd_netlink_message *m, unsigned short type
int sd_netlink_message_open_container_union(sd_netlink_message *m, unsigned short type, const char *key);
int sd_netlink_message_close_container(sd_netlink_message *m);
+int sd_netlink_message_read(sd_netlink_message *m, unsigned short type, size_t size, void *data);
int sd_netlink_message_read_string(sd_netlink_message *m, unsigned short type, const char **data);
int sd_netlink_message_read_u8(sd_netlink_message *m, unsigned short type, uint8_t *data);
int sd_netlink_message_read_u16(sd_netlink_message *m, unsigned short type, uint16_t *data);