1
0
mirror of https://github.com/systemd/systemd synced 2025-10-01 17:54:45 +02:00

Compare commits

...

10 Commits

Author SHA1 Message Date
Yu Watanabe
27edd36eaa network: fix typo 2021-02-20 18:58:07 +09:00
Yu Watanabe
aa3069977e
Merge pull request #18689 from yuwata/network-address-broadcast-no
network: make Broadcast= accept "no"
2021-02-20 16:55:28 +09:00
Yu Watanabe
045db4fa0d test-network: add tests for Broadcast= with boolean settings 2021-02-20 14:23:07 +09:00
Yu Watanabe
832583ada8 network: make Broadcast= accept boolean value
And disable it for wireguard interfaces by default.

Closes #18492.
2021-02-20 14:23:00 +09:00
Yu Watanabe
7f37ecf7e5
Merge pull request #18699 from yuwata/network-route-add-nexthop-setting
network: add NextHop= setting in [Route] section
2021-02-20 14:17:17 +09:00
Lennart Poettering
6c41cf4459 sd-bus: simplify sd_bus_reply()
there's no point in having two arguments, if one does as well.
2021-02-20 13:44:02 +09:00
Yu Watanabe
cee0f719d8 test-network: add tests for NextHop= setting in [Route] 2021-02-19 22:42:39 +09:00
Yu Watanabe
e918b3c12a network: add nexthop ID in debugging logs 2021-02-19 22:42:39 +09:00
Yu Watanabe
324e342219 network: add NextHop= setting in [Route] section 2021-02-19 22:42:39 +09:00
Yu Watanabe
69e244e321 network: also manage nexthops by ID
It will be used in later commits.
2021-02-19 22:42:39 +09:00
24 changed files with 299 additions and 74 deletions

5
NEWS
View File

@ -123,8 +123,9 @@ CHANGES WITH 248:
systemctl --user -M lennart@ start quux systemctl --user -M lennart@ start quux
* sd-bus also gained a convenience function sd_bus_reply() to call * sd-bus also gained a convenience function sd_bus_message_send() to
sd_bus_send() with an existing reply message. simplify invocations of sd_bus_send(), taking only a single
parameter: the message to send.
* sd-event allows rate limits to be set on event sources, for dealing * sd-event allows rate limits to be set on event sources, for dealing
with high-priority event sources that might starve out others. See with high-priority event sources that might starve out others. See

View File

@ -405,17 +405,14 @@ manpages = [
'sd_bus_reply_method_errorf', 'sd_bus_reply_method_errorf',
'sd_bus_reply_method_errorfv'], 'sd_bus_reply_method_errorfv'],
''], ''],
['sd_bus_reply_method_return', ['sd_bus_reply_method_return', '3', ['sd_bus_reply_method_returnv'], ''],
'3',
['sd_bus_reply', 'sd_bus_reply_method_returnv'],
''],
['sd_bus_request_name', ['sd_bus_request_name',
'3', '3',
['sd_bus_release_name', ['sd_bus_release_name',
'sd_bus_release_name_async', 'sd_bus_release_name_async',
'sd_bus_request_name_async'], 'sd_bus_request_name_async'],
''], ''],
['sd_bus_send', '3', ['sd_bus_send_to'], ''], ['sd_bus_send', '3', ['sd_bus_message_send', 'sd_bus_send_to'], ''],
['sd_bus_set_address', '3', ['sd_bus_get_address', 'sd_bus_set_exec'], ''], ['sd_bus_set_address', '3', ['sd_bus_get_address', 'sd_bus_set_exec'], ''],
['sd_bus_set_close_on_exit', '3', ['sd_bus_get_close_on_exit'], ''], ['sd_bus_set_close_on_exit', '3', ['sd_bus_get_close_on_exit'], ''],
['sd_bus_set_connected_signal', '3', ['sd_bus_get_connected_signal'], ''], ['sd_bus_set_connected_signal', '3', ['sd_bus_get_connected_signal'], ''],

View File

@ -54,9 +54,9 @@
<citerefentry><refentrytitle>sd_bus_call_method</refentrytitle><manvolnum>3</manvolnum></citerefentry>, <citerefentry><refentrytitle>sd_bus_call_method</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd_bus_call_method_async</refentrytitle><manvolnum>3</manvolnum></citerefentry>, <citerefentry><refentrytitle>sd_bus_call_method_async</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd_bus_can_send</refentrytitle><manvolnum>3</manvolnum></citerefentry>, <citerefentry><refentrytitle>sd_bus_can_send</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd_bus_close</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd_bus_creds_get_pid</refentrytitle><manvolnum>3</manvolnum></citerefentry>, <citerefentry><refentrytitle>sd_bus_creds_get_pid</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd_bus_creds_new_from_pid</refentrytitle><manvolnum>3</manvolnum></citerefentry>, <citerefentry><refentrytitle>sd_bus_creds_new_from_pid</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd_bus_close</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd_bus_default</refentrytitle><manvolnum>3</manvolnum></citerefentry>, <citerefentry><refentrytitle>sd_bus_default</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd_bus_emit_interfaces_added</refentrytitle><manvolnum>3</manvolnum></citerefentry>, <citerefentry><refentrytitle>sd_bus_emit_interfaces_added</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd_bus_emit_interfaces_added_strv</refentrytitle><manvolnum>3</manvolnum></citerefentry>, <citerefentry><refentrytitle>sd_bus_emit_interfaces_added_strv</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
@ -83,19 +83,19 @@
<citerefentry><refentrytitle>sd_bus_get_fd</refentrytitle><manvolnum>3</manvolnum></citerefentry>, <citerefentry><refentrytitle>sd_bus_get_fd</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd_bus_get_method_call_timeout</refentrytitle><manvolnum>3</manvolnum></citerefentry>, <citerefentry><refentrytitle>sd_bus_get_method_call_timeout</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd_bus_get_n_queued_read</refentrytitle><manvolnum>3</manvolnum></citerefentry>, <citerefentry><refentrytitle>sd_bus_get_n_queued_read</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd_bus_get_name_machine_id</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd_bus_get_name_creds</refentrytitle><manvolnum>3</manvolnum></citerefentry>, <citerefentry><refentrytitle>sd_bus_get_name_creds</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd_bus_get_name_machine_id</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd_bus_get_owner_creds</refentrytitle><manvolnum>3</manvolnum></citerefentry>, <citerefentry><refentrytitle>sd_bus_get_owner_creds</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd_bus_get_property</refentrytitle><manvolnum>3</manvolnum></citerefentry>, <citerefentry><refentrytitle>sd_bus_get_property</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd_bus_get_property_trivial</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd_bus_get_property_string</refentrytitle><manvolnum>3</manvolnum></citerefentry>, <citerefentry><refentrytitle>sd_bus_get_property_string</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd_bus_get_property_strv</refentrytitle><manvolnum>3</manvolnum></citerefentry>, <citerefentry><refentrytitle>sd_bus_get_property_strv</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd_bus_get_property_trivial</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd_bus_get_scope</refentrytitle><manvolnum>3</manvolnum></citerefentry>, <citerefentry><refentrytitle>sd_bus_get_scope</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd_bus_get_tid</refentrytitle><manvolnum>3</manvolnum></citerefentry>, <citerefentry><refentrytitle>sd_bus_get_tid</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd_bus_get_unique_name</refentrytitle><manvolnum>3</manvolnum></citerefentry>, <citerefentry><refentrytitle>sd_bus_get_unique_name</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd_bus_interface_name_is_valid</refentrytitle><manvolnum>3</manvolnum></citerefentry>, <citerefentry><refentrytitle>sd_bus_interface_name_is_valid</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd_bus_is_monitor</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd_bus_is_bus_client</refentrytitle><manvolnum>3</manvolnum></citerefentry>, <citerefentry><refentrytitle>sd_bus_is_bus_client</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd_bus_is_monitor</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd_bus_is_server</refentrytitle><manvolnum>3</manvolnum></citerefentry>, <citerefentry><refentrytitle>sd_bus_is_server</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd_bus_list_names</refentrytitle><manvolnum>3</manvolnum></citerefentry>, <citerefentry><refentrytitle>sd_bus_list_names</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd_bus_message_append</refentrytitle><manvolnum>3</manvolnum></citerefentry>, <citerefentry><refentrytitle>sd_bus_message_append</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
@ -128,12 +128,13 @@
<citerefentry><refentrytitle>sd_bus_message_read_array</refentrytitle><manvolnum>3</manvolnum></citerefentry>, <citerefentry><refentrytitle>sd_bus_message_read_array</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd_bus_message_read_basic</refentrytitle><manvolnum>3</manvolnum></citerefentry>, <citerefentry><refentrytitle>sd_bus_message_read_basic</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd_bus_message_read_strv</refentrytitle><manvolnum>3</manvolnum></citerefentry>, <citerefentry><refentrytitle>sd_bus_message_read_strv</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd_bus_message_reply</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd_bus_message_rewind</refentrytitle><manvolnum>3</manvolnum></citerefentry>, <citerefentry><refentrytitle>sd_bus_message_rewind</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd_bus_message_seal</refentrytitle><manvolnum>3</manvolnum></citerefentry>, <citerefentry><refentrytitle>sd_bus_message_seal</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd_bus_message_set_allow_interactive_authorization</refentrytitle><manvolnum>3</manvolnum></citerefentry>, <citerefentry><refentrytitle>sd_bus_message_set_allow_interactive_authorization</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd_bus_message_set_destination</refentrytitle><manvolnum>3</manvolnum></citerefentry>, <citerefentry><refentrytitle>sd_bus_message_set_destination</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd_bus_message_set_sender</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd_bus_message_set_expect_reply</refentrytitle><manvolnum>3</manvolnum></citerefentry>, <citerefentry><refentrytitle>sd_bus_message_set_expect_reply</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd_bus_message_set_sender</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd_bus_message_skip</refentrytitle><manvolnum>3</manvolnum></citerefentry>, <citerefentry><refentrytitle>sd_bus_message_skip</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd_bus_message_verify_type</refentrytitle><manvolnum>3</manvolnum></citerefentry>, <citerefentry><refentrytitle>sd_bus_message_verify_type</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd_bus_negotiate_fds</refentrytitle><manvolnum>3</manvolnum></citerefentry>, <citerefentry><refentrytitle>sd_bus_negotiate_fds</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
@ -142,9 +143,8 @@
<citerefentry><refentrytitle>sd_bus_process</refentrytitle><manvolnum>3</manvolnum></citerefentry>, <citerefentry><refentrytitle>sd_bus_process</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd_bus_query_sender_creds</refentrytitle><manvolnum>3</manvolnum></citerefentry>, <citerefentry><refentrytitle>sd_bus_query_sender_creds</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd_bus_query_sender_privilege</refentrytitle><manvolnum>3</manvolnum></citerefentry>, <citerefentry><refentrytitle>sd_bus_query_sender_privilege</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd_bus_reply_method_return</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd_bus_reply_method_error</refentrytitle><manvolnum>3</manvolnum></citerefentry>, <citerefentry><refentrytitle>sd_bus_reply_method_error</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd_bus_reply</refentrytitle><manvolnum>3</manvolnum></citerefentry>, <citerefentry><refentrytitle>sd_bus_reply_method_return</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd_bus_request_name</refentrytitle><manvolnum>3</manvolnum></citerefentry>, <citerefentry><refentrytitle>sd_bus_request_name</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd_bus_send</refentrytitle><manvolnum>3</manvolnum></citerefentry>, <citerefentry><refentrytitle>sd_bus_send</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd_bus_send_to</refentrytitle><manvolnum>3</manvolnum></citerefentry>, <citerefentry><refentrytitle>sd_bus_send_to</refentrytitle><manvolnum>3</manvolnum></citerefentry>,

View File

@ -19,7 +19,6 @@
<refnamediv> <refnamediv>
<refname>sd_bus_reply_method_return</refname> <refname>sd_bus_reply_method_return</refname>
<refname>sd_bus_reply_method_returnv</refname> <refname>sd_bus_reply_method_returnv</refname>
<refname>sd_bus_reply</refname>
<refpurpose>Reply to a D-Bus method call</refpurpose> <refpurpose>Reply to a D-Bus method call</refpurpose>
</refnamediv> </refnamediv>
@ -41,12 +40,6 @@
<paramdef>const char *<parameter>types</parameter></paramdef> <paramdef>const char *<parameter>types</parameter></paramdef>
<paramdef>va_list <parameter>ap</parameter></paramdef> <paramdef>va_list <parameter>ap</parameter></paramdef>
</funcprototype> </funcprototype>
<funcprototype>
<funcdef>int sd_bus_reply</funcdef>
<paramdef>const sd_bus_message *<parameter>call</parameter></paramdef>
<paramdef>sd_bus_message *<parameter>m</parameter></paramdef>
</funcprototype>
</funcsynopsis> </funcsynopsis>
</refsynopsisdiv> </refsynopsisdiv>
@ -59,12 +52,6 @@
<citerefentry><refentrytitle>sd_bus_message_append</refentrytitle><manvolnum>3</manvolnum></citerefentry>. <citerefentry><refentrytitle>sd_bus_message_append</refentrytitle><manvolnum>3</manvolnum></citerefentry>.
If no reply is expected to <parameter>call</parameter>, this function succeeds without sending a If no reply is expected to <parameter>call</parameter>, this function succeeds without sending a
reply.</para> reply.</para>
<para><function>sd_bus_reply()</function> takes a complete bus message object created with either
<citerefentry><refentrytitle>sd_bus_message_new_method_return</refentrytitle><manvolnum>3</manvolnum></citerefentry>
or
<citerefentry><refentrytitle>sd_bus_message_new_method_error</refentrytitle><manvolnum>3</manvolnum></citerefentry>
and sends it as a reply to the <parameter>call</parameter> message.</para>
</refsect1> </refsect1>
<refsect1> <refsect1>

View File

@ -19,6 +19,7 @@
<refnamediv> <refnamediv>
<refname>sd_bus_send</refname> <refname>sd_bus_send</refname>
<refname>sd_bus_send_to</refname> <refname>sd_bus_send_to</refname>
<refname>sd_bus_message_send</refname>
<refpurpose>Queue a D-Bus message for transfer</refpurpose> <refpurpose>Queue a D-Bus message for transfer</refpurpose>
</refnamediv> </refnamediv>
@ -41,6 +42,11 @@
<paramdef>const char *<parameter>destination</parameter></paramdef> <paramdef>const char *<parameter>destination</parameter></paramdef>
<paramdef>uint64_t *<parameter>cookie</parameter></paramdef> <paramdef>uint64_t *<parameter>cookie</parameter></paramdef>
</funcprototype> </funcprototype>
<funcprototype>
<funcdef>int sd_bus_message_send</funcdef>
<paramdef>sd_bus_message *<parameter>m</parameter></paramdef>
</funcprototype>
</funcsynopsis> </funcsynopsis>
</refsynopsisdiv> </refsynopsisdiv>
@ -76,6 +82,10 @@
call fails. call fails.
<citerefentry><refentrytitle>sd_bus_process</refentrytitle><manvolnum>3</manvolnum></citerefentry> should <citerefentry><refentrytitle>sd_bus_process</refentrytitle><manvolnum>3</manvolnum></citerefentry> should
be invoked to write out any queued message data to the transport.</para> be invoked to write out any queued message data to the transport.</para>
<para><function>sd_bus_message_send()</function> is the same as <function>sd_bus_send()</function> but
without the first and last argument. It's equivalent to
<function>sd_bus_message_send(sd_bus_message_get_bus(m), m, NULL)</function>.</para>
</refsect1> </refsect1>
<refsect1> <refsect1>

View File

@ -1044,12 +1044,12 @@ IPv6Token=prefixstable:2002:da8:1::</programlisting></para>
<varlistentry> <varlistentry>
<term><varname>Broadcast=</varname></term> <term><varname>Broadcast=</varname></term>
<listitem> <listitem>
<para>The broadcast address, which must be in the format <para>Takes an IPv4 address or boolean value. The address must be in the format described in
described in
<citerefentry project='man-pages'><refentrytitle>inet_pton</refentrytitle><manvolnum>3</manvolnum></citerefentry>. <citerefentry project='man-pages'><refentrytitle>inet_pton</refentrytitle><manvolnum>3</manvolnum></citerefentry>.
This key only applies to IPv4 addresses. If it is not If set to true, then the IPv4 broadcast address will be derived from the
given, it is derived from the <varname>Address=</varname> <varname>Address=</varname> setting. If set to false, then the broadcast address will not
key.</para> be set. Defaults to true, except for wireguard interfaces, where it default to false.
</para>
</listitem> </listitem>
</varlistentry> </varlistentry>
<varlistentry> <varlistentry>
@ -1554,6 +1554,13 @@ IPv6Token=prefixstable:2002:da8:1::</programlisting></para>
times. If an empty string is assigned, then the all previous assignments are cleared.</para> times. If an empty string is assigned, then the all previous assignments are cleared.</para>
</listitem> </listitem>
</varlistentry> </varlistentry>
<varlistentry>
<term><varname>NextHop=</varname></term>
<listitem>
<para>Specifies the nexthop id. Takes an unsigned integer in the range 1…4294967295.
If set, the corresponding [NextHop] section must be configured. Defaults to unset.</para>
</listitem>
</varlistentry>
</variablelist> </variablelist>
</refsect1> </refsect1>

View File

@ -740,7 +740,7 @@ global:
LIBSYSTEMD_248 { LIBSYSTEMD_248 {
global: global:
sd_bus_open_user_machine; sd_bus_open_user_machine;
sd_bus_reply; sd_bus_message_send;
sd_event_source_set_ratelimit; sd_event_source_set_ratelimit;
sd_event_source_get_ratelimit; sd_event_source_get_ratelimit;

View File

@ -9,6 +9,14 @@
#include "bus-type.h" #include "bus-type.h"
#include "string-util.h" #include "string-util.h"
_public_ int sd_bus_message_send(sd_bus_message *reply) {
assert_return(reply, -EINVAL);
assert_return(reply->bus, -EINVAL);
assert_return(!bus_pid_changed(reply->bus), -ECHILD);
return sd_bus_send(reply->bus, reply, NULL);
}
_public_ int sd_bus_emit_signalv( _public_ int sd_bus_emit_signalv(
sd_bus *bus, sd_bus *bus,
const char *path, const char *path,
@ -198,7 +206,7 @@ _public_ int sd_bus_reply_method_returnv(
return r; return r;
} }
return sd_bus_reply(call, m); return sd_bus_message_send(m);
} }
_public_ int sd_bus_reply_method_return( _public_ int sd_bus_reply_method_return(
@ -239,7 +247,7 @@ _public_ int sd_bus_reply_method_error(
if (r < 0) if (r < 0)
return r; return r;
return sd_bus_reply(call, m); return sd_bus_message_send(m);
} }
_public_ int sd_bus_reply_method_errorfv( _public_ int sd_bus_reply_method_errorfv(

View File

@ -2604,20 +2604,6 @@ _public_ int sd_bus_get_timeout(sd_bus *bus, uint64_t *timeout_usec) {
} }
} }
int sd_bus_reply(const sd_bus_message *call, sd_bus_message *reply) {
assert_return(call, -EINVAL);
assert_return(call->sealed, -EPERM);
assert_return(call->header->type == SD_BUS_MESSAGE_METHOD_CALL, -EINVAL);
assert_return(call->bus, -EINVAL);
assert_return(!bus_pid_changed(call->bus), -ECHILD);
assert_return(reply, -EINVAL);
assert_return(
IN_SET(reply->header->type, SD_BUS_MESSAGE_METHOD_RETURN, SD_BUS_MESSAGE_METHOD_ERROR),
-EINVAL);
return sd_bus_send(call->bus, reply, NULL);
}
static int process_timeout(sd_bus *bus) { static int process_timeout(sd_bus *bus) {
_cleanup_(sd_bus_error_free) sd_bus_error error_buffer = SD_BUS_ERROR_NULL; _cleanup_(sd_bus_error_free) sd_bus_error error_buffer = SD_BUS_ERROR_NULL;
_cleanup_(sd_bus_message_unrefp) sd_bus_message* m = NULL; _cleanup_(sd_bus_message_unrefp) sd_bus_message* m = NULL;

View File

@ -57,6 +57,7 @@ int address_new(Address **ret) {
.scope = RT_SCOPE_UNIVERSE, .scope = RT_SCOPE_UNIVERSE,
.cinfo.ifa_prefered = CACHE_INFO_INFINITY_LIFE_TIME, .cinfo.ifa_prefered = CACHE_INFO_INFINITY_LIFE_TIME,
.cinfo.ifa_valid = CACHE_INFO_INFINITY_LIFE_TIME, .cinfo.ifa_valid = CACHE_INFO_INFINITY_LIFE_TIME,
.set_broadcast = -1,
.duplicate_address_detection = ADDRESS_FAMILY_IPV6, .duplicate_address_detection = ADDRESS_FAMILY_IPV6,
}; };
@ -153,6 +154,20 @@ static bool address_may_have_broadcast(const Address *a) {
a->prefixlen <= 30; a->prefixlen <= 30;
} }
static bool address_may_set_broadcast(const Address *a, const Link *link) {
assert(a);
assert(link);
if (!address_may_have_broadcast(a))
return false;
if (a->set_broadcast >= 0)
return a->set_broadcast;
/* Typical configuration for wireguard does not set broadcast. */
return !streq_ptr(link->kind, "wireguard");
}
static uint32_t address_prefix(const Address *a) { static uint32_t address_prefix(const Address *a) {
assert(a); assert(a);
@ -887,7 +902,7 @@ int address_configure(
r = netlink_message_append_in_addr_union(req, IFA_ADDRESS, address->family, &address->in_addr_peer); r = netlink_message_append_in_addr_union(req, IFA_ADDRESS, address->family, &address->in_addr_peer);
if (r < 0) if (r < 0)
return log_link_error_errno(link, r, "Could not append IFA_ADDRESS attribute: %m"); return log_link_error_errno(link, r, "Could not append IFA_ADDRESS attribute: %m");
} else if (address_may_have_broadcast(address)) { } else if (address_may_set_broadcast(address, link)) {
r = sd_netlink_message_append_in_addr(req, IFA_BROADCAST, &address->broadcast); r = sd_netlink_message_append_in_addr(req, IFA_BROADCAST, &address->broadcast);
if (r < 0) if (r < 0)
return log_link_error_errno(link, r, "Could not append IFA_BROADCAST attribute: %m"); return log_link_error_errno(link, r, "Could not append IFA_BROADCAST attribute: %m");
@ -1467,6 +1482,25 @@ int config_parse_broadcast(
return 0; return 0;
} }
if (isempty(rvalue)) {
/* The broadcast address will be calculated based on Address=, and set if the link is
* not a wireguard interface. Here, we do not check or set n->family. */
n->broadcast = (struct in_addr) {};
n->set_broadcast = -1;
TAKE_PTR(n);
return 0;
}
r = parse_boolean(rvalue);
if (r >= 0) {
/* The broadcast address will be calculated based on Address=. Here, we do not check or
* set n->family. */
n->broadcast = (struct in_addr) {};
n->set_broadcast = r;
TAKE_PTR(n);
return 0;
}
if (n->family == AF_INET6) { if (n->family == AF_INET6) {
log_syntax(unit, LOG_WARNING, filename, line, 0, log_syntax(unit, LOG_WARNING, filename, line, 0,
"Broadcast is not valid for IPv6 addresses, ignoring assignment: %s", rvalue); "Broadcast is not valid for IPv6 addresses, ignoring assignment: %s", rvalue);
@ -1479,8 +1513,14 @@ int config_parse_broadcast(
"Broadcast is invalid, ignoring assignment: %s", rvalue); "Broadcast is invalid, ignoring assignment: %s", rvalue);
return 0; return 0;
} }
if (in4_addr_is_null(&u.in)) {
log_syntax(unit, LOG_WARNING, filename, line, 0,
"Broadcast cannot be ANY address, ignoring assignment: %s", rvalue);
return 0;
}
n->broadcast = u.in; n->broadcast = u.in;
n->set_broadcast = true;
n->family = AF_INET; n->family = AF_INET;
TAKE_PTR(n); TAKE_PTR(n);
@ -1835,7 +1875,7 @@ static int address_section_verify(Address *address) {
} }
if (address_may_have_broadcast(address)) { if (address_may_have_broadcast(address)) {
if (address->broadcast.s_addr == 0) if (address->broadcast.s_addr == 0 && address->set_broadcast != 0)
address->broadcast.s_addr = address->in_addr.in.s_addr | htobe32(0xfffffffflu >> address->prefixlen); address->broadcast.s_addr = address->in_addr.in.s_addr | htobe32(0xfffffffflu >> address->prefixlen);
} else if (address->broadcast.s_addr != 0) { } else if (address->broadcast.s_addr != 0) {
log_warning("%s: broadcast address is set for IPv6 address or IPv4 address with prefixlength larger than 30. " log_warning("%s: broadcast address is set for IPv6 address or IPv4 address with prefixlength larger than 30. "

View File

@ -30,6 +30,7 @@ typedef struct Address {
uint32_t flags; uint32_t flags;
char *label; char *label;
int set_broadcast;
struct in_addr broadcast; struct in_addr broadcast;
struct ifa_cacheinfo cinfo; struct ifa_cacheinfo cinfo;

View File

@ -894,6 +894,8 @@ Manager* manager_free(Manager *m) {
m->routes = set_free(m->routes); m->routes = set_free(m->routes);
m->routes_foreign = set_free(m->routes_foreign); m->routes_foreign = set_free(m->routes_foreign);
m->nexthops_by_id = hashmap_free(m->nexthops_by_id);
sd_event_source_unref(m->speed_meter_event_source); sd_event_source_unref(m->speed_meter_event_source);
sd_event_unref(m->event); sd_event_unref(m->event);

View File

@ -61,6 +61,9 @@ struct Manager {
Set *rules; Set *rules;
Set *rules_foreign; Set *rules_foreign;
/* Manage nexthops by id. */
Hashmap *nexthops_by_id;
/* Manager stores routes without RTA_OIF attribute. */ /* Manager stores routes without RTA_OIF attribute. */
Set *routes; Set *routes;
Set *routes_foreign; Set *routes_foreign;

View File

@ -185,6 +185,7 @@ Route.QuickAck, config_parse_route_boolean,
Route.FastOpenNoCookie, config_parse_route_boolean, 0, 0 Route.FastOpenNoCookie, config_parse_route_boolean, 0, 0
Route.TTLPropagate, config_parse_route_boolean, 0, 0 Route.TTLPropagate, config_parse_route_boolean, 0, 0
Route.MultiPathRoute, config_parse_multipath_route, 0, 0 Route.MultiPathRoute, config_parse_multipath_route, 0, 0
Route.NextHop, config_parse_route_nexthop, 0, 0
NextHop.Id, config_parse_nexthop_id, 0, 0 NextHop.Id, config_parse_nexthop_id, 0, 0
NextHop.Gateway, config_parse_nexthop_gateway, 0, 0 NextHop.Gateway, config_parse_nexthop_gateway, 0, 0
NextHop.Family, config_parse_nexthop_family, 0, 0 NextHop.Family, config_parse_nexthop_family, 0, 0

View File

@ -28,6 +28,9 @@ NextHop *nexthop_free(NextHop *nexthop) {
if (nexthop->link) { if (nexthop->link) {
set_remove(nexthop->link->nexthops, nexthop); set_remove(nexthop->link->nexthops, nexthop);
set_remove(nexthop->link->nexthops_foreign, nexthop); set_remove(nexthop->link->nexthops_foreign, nexthop);
if (nexthop->link->manager && nexthop->id > 0)
hashmap_remove(nexthop->link->manager->nexthops_by_id, UINT32_TO_PTR(nexthop->id));
} }
return mfree(nexthop); return mfree(nexthop);
@ -129,6 +132,23 @@ DEFINE_HASH_OPS_WITH_KEY_DESTRUCTOR(
nexthop_compare_func, nexthop_compare_func,
nexthop_free); nexthop_free);
int manager_get_nexthop_by_id(Manager *manager, uint32_t id, NextHop **ret) {
NextHop *nh;
assert(manager);
if (id == 0)
return -EINVAL;
nh = hashmap_get(manager->nexthops_by_id, UINT32_TO_PTR(id));
if (!nh)
return -ENOENT;
if (ret)
*ret = nh;
return 0;
}
static int nexthop_get(Link *link, const NextHop *in, NextHop **ret) { static int nexthop_get(Link *link, const NextHop *in, NextHop **ret) {
NextHop *existing; NextHop *existing;
@ -221,14 +241,18 @@ static int nexthop_update(Link *link, NextHop *nexthop, const NextHop *in) {
int r; int r;
assert(link); assert(link);
assert(link->manager);
assert(nexthop); assert(nexthop);
assert(in); assert(in);
assert(in->id > 0); assert(in->id > 0);
/* Currently, this only updates ID. */ /* This updates nexthop ID if necessary, and register the nexthop to Manager. */
if (nexthop->id > 0) if (nexthop->id > 0) {
return nexthop->id == in->id ? 0 : -EINVAL; if (nexthop->id == in->id)
goto set_manager;
return -EINVAL;
}
nexthop = set_remove(link->nexthops, nexthop); nexthop = set_remove(link->nexthops, nexthop);
if (!nexthop) if (!nexthop)
@ -251,7 +275,8 @@ static int nexthop_update(Link *link, NextHop *nexthop, const NextHop *in) {
return r < 0 ? r : -EEXIST; return r < 0 ? r : -EEXIST;
} }
return 0; set_manager:
return hashmap_ensure_put(&link->manager->nexthops_by_id, NULL, UINT32_TO_PTR(nexthop->id), nexthop);
} }
static void log_nexthop_debug(const NextHop *nexthop, uint32_t id, const char *str, const Link *link) { static void log_nexthop_debug(const NextHop *nexthop, uint32_t id, const char *str, const Link *link) {
@ -384,7 +409,7 @@ int link_set_nexthops(Link *link) {
if (link->nexthop_messages == 0) { if (link->nexthop_messages == 0) {
link->static_nexthops_configured = true; link->static_nexthops_configured = true;
/* Finaly, configure routes with gateways. */ /* Finally, configure routes with gateways. */
return link_set_routes_with_gateway(link); return link_set_routes_with_gateway(link);
} }

View File

@ -35,6 +35,7 @@ void network_drop_invalid_nexthops(Network *network);
int link_set_nexthops(Link *link); int link_set_nexthops(Link *link);
int manager_get_nexthop_by_id(Manager *manager, uint32_t id, NextHop **ret);
int manager_rtnl_process_nexthop(sd_netlink *rtnl, sd_netlink_message *message, Manager *m); int manager_rtnl_process_nexthop(sd_netlink *rtnl, sd_netlink_message *message, Manager *m);
CONFIG_PARSER_PROTOTYPE(config_parse_nexthop_id); CONFIG_PARSER_PROTOTYPE(config_parse_nexthop_id);

View File

@ -328,6 +328,7 @@ void route_hash_func(const Route *route, struct siphash *state) {
siphash24_compress(&route->initrwnd, sizeof(route->initrwnd), state); siphash24_compress(&route->initrwnd, sizeof(route->initrwnd), state);
siphash24_compress(&route->advmss, sizeof(route->advmss), state); siphash24_compress(&route->advmss, sizeof(route->advmss), state);
siphash24_compress(&route->nexthop_id, sizeof(route->nexthop_id), state);
break; break;
default: default:
@ -416,6 +417,10 @@ int route_compare_func(const Route *a, const Route *b) {
if (r != 0) if (r != 0)
return r; return r;
r = CMP(a->nexthop_id, b->nexthop_id);
if (r != 0)
return r;
return 0; return 0;
default: default:
/* treat any other address family as AF_UNSPEC */ /* treat any other address family as AF_UNSPEC */
@ -479,7 +484,7 @@ static int route_get(const Manager *manager, const Link *link, const Route *in,
return -ENOENT; return -ENOENT;
} }
static void route_copy(Route *dest, const Route *src, const MultipathRoute *m) { static void route_copy(Route *dest, const Route *src, const MultipathRoute *m, const NextHop *nh) {
assert(dest); assert(dest);
assert(src); assert(src);
@ -498,9 +503,14 @@ static void route_copy(Route *dest, const Route *src, const MultipathRoute *m) {
dest->initcwnd = src->initcwnd; dest->initcwnd = src->initcwnd;
dest->initrwnd = src->initrwnd; dest->initrwnd = src->initrwnd;
dest->lifetime = src->lifetime; dest->lifetime = src->lifetime;
dest->advmss= src->advmss; dest->advmss = src->advmss;
dest->nexthop_id = src->nexthop_id;
if (m) { if (nh) {
dest->gw_family = nh->family;
dest->gw = nh->gw;
dest->gw_weight = src->gw_weight;
} else if (m) {
dest->gw_family = m->gateway.family; dest->gw_family = m->gateway.family;
dest->gw = m->gateway.address; dest->gw = m->gateway.address;
dest->gw_weight = m->weight; dest->gw_weight = m->weight;
@ -523,7 +533,7 @@ static int route_add_internal(Manager *manager, Link *link, Set **routes, const
if (r < 0) if (r < 0)
return r; return r;
route_copy(route, in, NULL); route_copy(route, in, NULL, NULL);
r = set_ensure_put(routes, &route_hash_ops, route); r = set_ensure_put(routes, &route_hash_ops, route);
if (r < 0) if (r < 0)
@ -547,7 +557,7 @@ static int route_add_foreign(Manager *manager, Link *link, const Route *in, Rout
return route_add_internal(manager, link, link ? &link->routes_foreign : &manager->routes_foreign, in, ret); return route_add_internal(manager, link, link ? &link->routes_foreign : &manager->routes_foreign, in, ret);
} }
static int route_add(Manager *manager, Link *link, const Route *in, const MultipathRoute *m, Route **ret) { static int route_add(Manager *manager, Link *link, const Route *in, const MultipathRoute *m, const NextHop *nh, Route **ret) {
_cleanup_(route_freep) Route *tmp = NULL; _cleanup_(route_freep) Route *tmp = NULL;
bool is_new = false; bool is_new = false;
Route *route; Route *route;
@ -556,14 +566,21 @@ static int route_add(Manager *manager, Link *link, const Route *in, const Multip
assert(manager || link); assert(manager || link);
assert(in); assert(in);
if (m) { if (nh) {
r = route_new(&tmp);
if (r < 0)
return r;
route_copy(tmp, in, NULL, nh);
in = tmp;
} else if (m) {
assert(link && (m->ifindex == 0 || m->ifindex == link->ifindex)); assert(link && (m->ifindex == 0 || m->ifindex == link->ifindex));
r = route_new(&tmp); r = route_new(&tmp);
if (r < 0) if (r < 0)
return r; return r;
route_copy(tmp, in, m); route_copy(tmp, in, m, NULL);
in = tmp; in = tmp;
} }
@ -630,10 +647,11 @@ static void log_route_debug(const Route *route, const char *str, const Link *lin
(void) route_protocol_full_to_string_alloc(route->protocol, &proto); (void) route_protocol_full_to_string_alloc(route->protocol, &proto);
log_link_debug(link, log_link_debug(link,
"%s route: dst: %s, src: %s, gw: %s, prefsrc: %s, scope: %s, table: %s, proto: %s, type: %s", "%s route: dst: %s, src: %s, gw: %s, prefsrc: %s, scope: %s, table: %s, proto: %s, type: %s, nexthop: %"PRIu32,
str, strna(dst), strna(src), strna(gw), strna(prefsrc), str, strna(dst), strna(src), strna(gw), strna(prefsrc),
strna(scope), strna(table), strna(proto), strna(scope), strna(table), strna(proto),
strna(route_type_to_string(route->type))); strna(route_type_to_string(route->type)),
route->nexthop_id);
} }
} }
@ -722,7 +740,7 @@ static int route_set_netlink_message(const Route *route, sd_netlink_message *req
if (r < 0) if (r < 0)
return log_link_error_errno(link, r, "Could not set route type: %m"); return log_link_error_errno(link, r, "Could not set route type: %m");
if (!route_type_is_reject(route)) { if (!route_type_is_reject(route) && route->nexthop_id == 0) {
assert(link); /* Those routes must be attached to a specific link */ assert(link); /* Those routes must be attached to a specific link */
r = sd_netlink_message_append_u32(req, RTA_OIF, link->ifindex); r = sd_netlink_message_append_u32(req, RTA_OIF, link->ifindex);
@ -730,6 +748,12 @@ static int route_set_netlink_message(const Route *route, sd_netlink_message *req
return log_link_error_errno(link, r, "Could not append RTA_OIF attribute: %m"); return log_link_error_errno(link, r, "Could not append RTA_OIF attribute: %m");
} }
if (route->nexthop_id > 0) {
r = sd_netlink_message_append_u32(req, RTA_NH_ID, route->nexthop_id);
if (r < 0)
return log_link_error_errno(link, r, "Could not append RTA_NH_ID attribute: %m");
}
r = sd_netlink_message_append_u8(req, RTA_PREF, route->pref); r = sd_netlink_message_append_u8(req, RTA_PREF, route->pref);
if (r < 0) if (r < 0)
return log_link_error_errno(link, r, "Could not append RTA_PREF attribute: %m"); return log_link_error_errno(link, r, "Could not append RTA_PREF attribute: %m");
@ -893,7 +917,7 @@ int link_drop_foreign_routes(Link *link) {
continue; continue;
if (link_has_route(link, route)) if (link_has_route(link, route))
k = route_add(NULL, link, route, NULL, NULL); k = route_add(NULL, link, route, NULL, NULL, NULL);
else else
k = route_remove(route, NULL, link, NULL); k = route_remove(route, NULL, link, NULL);
if (k < 0 && r >= 0) if (k < 0 && r >= 0)
@ -947,16 +971,20 @@ static int route_expire_handler(sd_event_source *s, uint64_t usec, void *userdat
static int route_add_and_setup_timer(Link *link, const Route *route, const MultipathRoute *m, Route **ret) { static int route_add_and_setup_timer(Link *link, const Route *route, const MultipathRoute *m, Route **ret) {
_cleanup_(sd_event_source_unrefp) sd_event_source *expire = NULL; _cleanup_(sd_event_source_unrefp) sd_event_source *expire = NULL;
NextHop *nh = NULL;
Route *nr; Route *nr;
int r, k; int r, k;
assert(link); assert(link);
assert(link->manager);
assert(route); assert(route);
(void) manager_get_nexthop_by_id(link->manager, route->nexthop_id, &nh);
if (route_type_is_reject(route)) if (route_type_is_reject(route))
k = route_add(link->manager, NULL, route, NULL, &nr); k = route_add(link->manager, NULL, route, NULL, NULL, &nr);
else if (!m || m->ifindex == 0 || m->ifindex == link->ifindex) else if (!m || m->ifindex == 0 || m->ifindex == link->ifindex)
k = route_add(NULL, link, route, m, &nr); k = route_add(NULL, link, route, m, nh, &nr);
else { else {
Link *link_gw; Link *link_gw;
@ -964,7 +992,7 @@ static int route_add_and_setup_timer(Link *link, const Route *route, const Multi
if (r < 0) if (r < 0)
return log_link_error_errno(link, r, "Failed to get link with ifindex %d: %m", m->ifindex); return log_link_error_errno(link, r, "Failed to get link with ifindex %d: %m", m->ifindex);
k = route_add(NULL, link_gw, route, m, &nr); k = route_add(NULL, link_gw, route, m, NULL, &nr);
} }
if (k < 0) if (k < 0)
return log_link_error_errno(link, k, "Could not add route: %m"); return log_link_error_errno(link, k, "Could not add route: %m");
@ -1258,6 +1286,9 @@ static bool route_has_gateway(const Route *route) {
if (!ordered_set_isempty(route->multipath_routes)) if (!ordered_set_isempty(route->multipath_routes))
return true; return true;
if (route->nexthop_id > 0)
return true;
return false; return false;
} }
@ -1296,7 +1327,7 @@ int link_set_routes_with_gateway(Link *link) {
* the addresses now, let's not configure the routes either. */ * the addresses now, let's not configure the routes either. */
return 0; return 0;
/* Finaly, add routes that needs a gateway. */ /* Finally, add routes that needs a gateway. */
r = link_set_routes_internal(link, true); r = link_set_routes_internal(link, true);
if (r < 0) if (r < 0)
return r; return r;
@ -1356,13 +1387,30 @@ int link_set_routes(Link *link) {
static int process_route_one(Manager *manager, Link *link, uint16_t type, const Route *tmp, const MultipathRoute *m) { static int process_route_one(Manager *manager, Link *link, uint16_t type, const Route *tmp, const MultipathRoute *m) {
_cleanup_(route_freep) Route *nr = NULL; _cleanup_(route_freep) Route *nr = NULL;
Route *route = NULL; Route *route = NULL;
NextHop *nh = NULL;
int r; int r;
assert(manager); assert(manager);
assert(tmp); assert(tmp);
assert(IN_SET(type, RTM_NEWROUTE, RTM_DELROUTE)); assert(IN_SET(type, RTM_NEWROUTE, RTM_DELROUTE));
if (m) { (void) manager_get_nexthop_by_id(manager, tmp->nexthop_id, &nh);
if (nh) {
if (link && link != nh->link)
return log_link_warning_errno(link, SYNTHETIC_ERRNO(EINVAL),
"rtnl: received RTA_OIF and ifindex of nexthop corresponding to RTA_NH_ID do not match, ignoring.");
link = nh->link;
r = route_new(&nr);
if (r < 0)
return log_oom();
route_copy(nr, tmp, NULL, nh);
tmp = nr;
} else if (m) {
if (link) if (link)
return log_link_warning_errno(link, SYNTHETIC_ERRNO(EINVAL), return log_link_warning_errno(link, SYNTHETIC_ERRNO(EINVAL),
"rtnl: received route contains both RTA_OIF and RTA_MULTIPATH, ignoring."); "rtnl: received route contains both RTA_OIF and RTA_MULTIPATH, ignoring.");
@ -1381,7 +1429,7 @@ static int process_route_one(Manager *manager, Link *link, uint16_t type, const
if (r < 0) if (r < 0)
return log_oom(); return log_oom();
route_copy(nr, tmp, m); route_copy(nr, tmp, m, NULL);
tmp = nr; tmp = nr;
} }
@ -1573,6 +1621,12 @@ int manager_rtnl_process_route(sd_netlink *rtnl, sd_netlink_message *message, Ma
return 0; return 0;
} }
r = sd_netlink_message_read_u32(message, RTA_NH_ID, &tmp->nexthop_id);
if (r < 0 && r != -ENODATA) {
log_link_warning_errno(link, r, "rtnl: received route message with invalid nexthop id, ignoring: %m");
return 0;
}
r = sd_netlink_message_enter_container(message, RTA_METRICS); r = sd_netlink_message_enter_container(message, RTA_METRICS);
if (r < 0 && r != -ENODATA) { if (r < 0 && r != -ENODATA) {
log_link_error_errno(link, r, "rtnl: Could not enter RTA_METRICS container: %m"); log_link_error_errno(link, r, "rtnl: Could not enter RTA_METRICS container: %m");
@ -1966,6 +2020,59 @@ int config_parse_route_scope(
return 0; return 0;
} }
int config_parse_route_nexthop(
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) {
Network *network = userdata;
_cleanup_(route_free_or_set_invalidp) Route *n = NULL;
uint32_t id;
int r;
assert(filename);
assert(section);
assert(lvalue);
assert(rvalue);
assert(data);
r = route_new_static(network, filename, section_line, &n);
if (r == -ENOMEM)
return log_oom();
if (r < 0) {
log_syntax(unit, LOG_WARNING, filename, line, r,
"Failed to allocate route, ignoring assignment: %m");
return 0;
}
if (isempty(rvalue)) {
n->nexthop_id = 0;
TAKE_PTR(n);
return 0;
}
r = safe_atou32(rvalue, &id);
if (r < 0) {
log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to parse nexthop ID, ignoring assignment: %s", rvalue);
return 0;
}
if (id == 0) {
log_syntax(unit, LOG_WARNING, filename, line, 0, "Invalid nexthop ID, ignoring assignment: %s", rvalue);
return 0;
}
n->nexthop_id = id;
TAKE_PTR(n);
return 0;
}
int config_parse_route_table( int config_parse_route_table(
const char *unit, const char *unit,
const char *filename, const char *filename,
@ -2656,6 +2763,14 @@ static int route_section_verify(Route *route, Network *network) {
route->section->filename, route->section->line); route->section->filename, route->section->line);
} }
if (route->nexthop_id > 0 &&
(in_addr_is_set(route->gw_family, &route->gw) ||
!ordered_set_isempty(route->multipath_routes)))
return log_warning_errno(SYNTHETIC_ERRNO(EINVAL),
"%s: NextHopId= cannot be specified with Gateway= or MultiPathRoute=. "
"Ignoring [Route] section from line %u.",
route->section->filename, route->section->line);
return 0; return 0;
} }

View File

@ -44,6 +44,7 @@ typedef struct Route {
unsigned char pref; unsigned char pref;
unsigned flags; unsigned flags;
int gateway_onlink; int gateway_onlink;
uint32_t nexthop_id;
bool scope_set:1; bool scope_set:1;
bool table_set:1; bool table_set:1;
@ -105,3 +106,4 @@ CONFIG_PARSER_PROTOTYPE(config_parse_route_mtu);
CONFIG_PARSER_PROTOTYPE(config_parse_multipath_route); CONFIG_PARSER_PROTOTYPE(config_parse_multipath_route);
CONFIG_PARSER_PROTOTYPE(config_parse_tcp_advmss); CONFIG_PARSER_PROTOTYPE(config_parse_tcp_advmss);
CONFIG_PARSER_PROTOTYPE(config_parse_route_table_names); CONFIG_PARSER_PROTOTYPE(config_parse_route_table_names);
CONFIG_PARSER_PROTOTYPE(config_parse_route_nexthop);

View File

@ -201,7 +201,6 @@ int sd_bus_send(sd_bus *bus, sd_bus_message *m, uint64_t *cookie);
int sd_bus_send_to(sd_bus *bus, sd_bus_message *m, const char *destination, uint64_t *cookie); int sd_bus_send_to(sd_bus *bus, sd_bus_message *m, const char *destination, uint64_t *cookie);
int sd_bus_call(sd_bus *bus, sd_bus_message *m, uint64_t usec, sd_bus_error *ret_error, sd_bus_message **reply); int sd_bus_call(sd_bus *bus, sd_bus_message *m, uint64_t usec, sd_bus_error *ret_error, sd_bus_message **reply);
int sd_bus_call_async(sd_bus *bus, sd_bus_slot **slot, sd_bus_message *m, sd_bus_message_handler_t callback, void *userdata, uint64_t usec); int sd_bus_call_async(sd_bus *bus, sd_bus_slot **slot, sd_bus_message *m, sd_bus_message_handler_t callback, void *userdata, uint64_t usec);
int sd_bus_reply(const sd_bus_message *call, sd_bus_message *reply);
int sd_bus_get_fd(sd_bus *bus); int sd_bus_get_fd(sd_bus *bus);
int sd_bus_get_events(sd_bus *bus); int sd_bus_get_events(sd_bus *bus);
@ -355,6 +354,7 @@ int sd_bus_get_name_machine_id(sd_bus *bus, const char *name, sd_id128_t *machin
/* Convenience calls */ /* Convenience calls */
int sd_bus_message_send(sd_bus_message *m);
int sd_bus_call_methodv(sd_bus *bus, const char *destination, const char *path, const char *interface, const char *member, sd_bus_error *ret_error, sd_bus_message **reply, const char *types, va_list ap); int sd_bus_call_methodv(sd_bus *bus, const char *destination, const char *path, const char *interface, const char *member, sd_bus_error *ret_error, sd_bus_message **reply, const char *types, va_list ap);
int sd_bus_call_method(sd_bus *bus, const char *destination, const char *path, const char *interface, const char *member, sd_bus_error *ret_error, sd_bus_message **reply, const char *types, ...); int sd_bus_call_method(sd_bus *bus, const char *destination, const char *path, const char *interface, const char *member, sd_bus_error *ret_error, sd_bus_message **reply, const char *types, ...);
int sd_bus_call_method_asyncv(sd_bus *bus, sd_bus_slot **slot, const char *destination, const char *path, const char *interface, const char *member, sd_bus_message_handler_t callback, void *userdata, const char *types, va_list ap); int sd_bus_call_method_asyncv(sd_bus *bus, sd_bus_slot **slot, const char *destination, const char *path, const char *interface, const char *member, sd_bus_message_handler_t callback, void *userdata, const char *types, va_list ap);

View File

@ -166,6 +166,7 @@ Metric=
TTLPropagate= TTLPropagate=
MultiPathRoute= MultiPathRoute=
TCPAdvertisedMaximumSegmentSize= TCPAdvertisedMaximumSegmentSize=
NextHop=
[Network] [Network]
IPv6DuplicateAddressDetection= IPv6DuplicateAddressDetection=
IPMasquerade= IPMasquerade=

View File

@ -61,6 +61,10 @@ Scope=link
Address=2001:0db8:1:f101::1/64 Address=2001:0db8:1:f101::1/64
PreferredLifetime=0 PreferredLifetime=0
[Address]
Address=10.8.8.1/16
Broadcast=no
# test for ENOBUFS issue #17012 # test for ENOBUFS issue #17012
[Network] [Network]
Address=10.3.3.1/16 Address=10.3.3.1/16

View File

@ -25,3 +25,15 @@ Family=ipv4
[NextHop] [NextHop]
Gateway=192.168.5.2 Gateway=192.168.5.2
[Route]
NextHop=1
Destination=10.10.10.10
[Route]
NextHop=2
Destination=10.10.10.11
[Route]
NextHop=2
Destination=2001:1234:5:8f62::1

View File

@ -2,6 +2,7 @@
Name=wg98 Name=wg98
[Network] [Network]
Address=192.168.123.123/24
Address=fd8d:4d6d:3ccb:0500::1/64 Address=fd8d:4d6d:3ccb:0500::1/64
# nat64 via 1 # nat64 via 1

View File

@ -1220,6 +1220,14 @@ class NetworkdNetDevTests(unittest.TestCase, Utilities):
start_networkd() start_networkd()
self.wait_online(['wg99:carrier', 'wg98:routable', 'wg97:carrier']) self.wait_online(['wg99:carrier', 'wg98:routable', 'wg97:carrier'])
output = check_output('ip -4 address show dev wg98')
print(output)
self.assertIn('inet 192.168.123.123/24 scope global wg98', output)
output = check_output('ip -6 address show dev wg98')
print(output)
self.assertIn('inet6 fd8d:4d6d:3ccb:500::1/64 scope global', output)
if shutil.which('wg'): if shutil.which('wg'):
call('wg') call('wg')
@ -1833,6 +1841,7 @@ class NetworkdNetworkTests(unittest.TestCase, Utilities):
self.assertIn('inet 10.1.2.4/16 brd 10.1.255.255 scope global secondary dummy98', output) self.assertIn('inet 10.1.2.4/16 brd 10.1.255.255 scope global secondary dummy98', output)
self.assertIn('inet 10.2.2.4/16 brd 10.2.255.255 scope global dummy98', output) self.assertIn('inet 10.2.2.4/16 brd 10.2.255.255 scope global dummy98', output)
self.assertIn('inet 10.7.8.9/16 brd 10.7.255.255 scope link deprecated dummy98', output) self.assertIn('inet 10.7.8.9/16 brd 10.7.255.255 scope link deprecated dummy98', output)
self.assertIn('inet 10.8.8.1/16 scope global dummy98', output)
# test for ENOBUFS issue #17012 # test for ENOBUFS issue #17012
for i in range(1,254): for i in range(1,254):
@ -2805,6 +2814,18 @@ class NetworkdNetworkTests(unittest.TestCase, Utilities):
self.assertIn('id 4 dev veth99', output) self.assertIn('id 4 dev veth99', output)
self.assertRegex(output, r'id [0-9]* via 192.168.5.2 dev veth99') self.assertRegex(output, r'id [0-9]* via 192.168.5.2 dev veth99')
output = check_output('ip route show dev veth99 10.10.10.10')
print(output)
self.assertEqual('10.10.10.10 nhid 1 via 192.168.5.1 proto static', output)
output = check_output('ip route show dev veth99 10.10.10.11')
print(output)
self.assertEqual('10.10.10.11 nhid 2 via inet6 2001:1234:5:8f63::2 proto static', output)
output = check_output('ip -6 route show dev veth99 2001:1234:5:8f62::1')
print(output)
self.assertEqual('2001:1234:5:8f62::1 nhid 2 via 2001:1234:5:8f63::2 proto static metric 1024 pref medium', output)
def test_qdisc(self): def test_qdisc(self):
copy_unit_to_networkd_unit_path('25-qdisc-clsact-and-htb.network', '12-dummy.netdev', copy_unit_to_networkd_unit_path('25-qdisc-clsact-and-htb.network', '12-dummy.netdev',
'25-qdisc-ingress-netem-compat.network', '11-dummy.netdev') '25-qdisc-ingress-netem-compat.network', '11-dummy.netdev')