Compare commits

...

24 Commits

Author SHA1 Message Date
Yu Watanabe 69ec2fdd9c
Merge pull request #13807 from 1848/ip6gre_key_fix
networkd: Set key (IFLA_GRE_IKEY,IFLA_GRE_OKEY) on ip6gre interfaces.
2019-10-23 23:18:59 +09:00
pan93412 3dc9e2220f l10n(zh_TW): update translations 2019-10-23 16:15:46 +02:00
David Tardon 7976b9f098 run: add -u as a synonym for --unit
Other tools that do have --unit= option (journalctl and systemd-cgls)
already do this, so let's be consistent.
2019-10-23 22:06:32 +09:00
Yu Watanabe c0c8886141
Merge pull request #13825 from keszybz/nspawn-console-help
nspawn: fix handling of --console=help
2019-10-23 22:03:53 +09:00
Zbigniew Jędrzejewski-Szmek 510c4bb31f
Merge pull request #13142 from yuwata/network-wifi-ssid-support-nl80211
network: wifi ssid support with nl80211
2019-10-23 14:51:23 +02:00
Zbigniew Jędrzejewski-Szmek 7a25ba554a man: reorder description of nspawn --console
The default value was described at the end of two long paragraphs.
Make the first para self contained, and move the description of --console=pipe
into the second para.
2019-10-23 10:13:30 +02:00
Zbigniew Jędrzejewski-Szmek dce66ffedb nspawn: fix handling of --console=help
We shouldn't continue to run the container after printing help.
2019-10-23 09:35:36 +02:00
1848 21bba27d9b Added ip6gre example to man 2019-10-22 17:41:10 +02:00
1848 6ba0e7c8fe Set key (IFLA_GRE_IKEY,IFLA_GRE_OKEY) on ip6gre interfaces. 2019-10-20 00:25:58 +02:00
Yu Watanabe 277ba8d1ab network: add support matching based on BSSID= 2019-10-15 01:59:56 +09:00
Yu Watanabe 0894cfe41c network: also read BSSID 2019-10-15 01:59:13 +09:00
Yu Watanabe 8d968fdd99 network: support matching based on wifi SSID 2019-10-15 01:59:06 +09:00
Yu Watanabe ad932b156c network: introduce link_reconfigure()
Will be used in later commits.
2019-10-15 01:57:19 +09:00
Yu Watanabe 1a6bb31fae network: split link_free() into two parts 2019-10-15 01:57:19 +09:00
Yu Watanabe a1d736e25c sd-netlink: add nl80211 type systems 2019-10-15 01:57:19 +09:00
Yu Watanabe 31e78d1042 sd-netlink: introduce sd_genl_message_get_family() 2019-10-15 01:57:19 +09:00
Yu Watanabe 2be081ffd6 sd-netlink: support NLMSG_DONE 2019-10-15 01:57:19 +09:00
Yu Watanabe 4e8f0ef921 sd-netlink: save dynamic general netlink message type 2019-10-15 01:57:19 +09:00
Yu Watanabe 2cac03f71d sd-netlink: drop unnecessarily exported variables 2019-10-15 01:57:19 +09:00
Yu Watanabe 59d4103fd5 sd-netlink: introduce sd_netlink_message_read_string_strdup() 2019-10-15 01:57:19 +09:00
Yu Watanabe 6bf8e24bad sd-netlink: use structured initializer 2019-10-15 01:57:19 +09:00
Yu Watanabe ddcda37016 sd-netlink: drop unused variable 2019-10-15 01:57:19 +09:00
Yu Watanabe 338ff28d5f sd-netlink: add missing license identifier 2019-10-15 01:57:19 +09:00
Yu Watanabe 16a8f172b6 bus-util: make map_basic handle SD_BUS_TYPE_OBJECT_PATH type 2019-10-15 01:57:19 +09:00
33 changed files with 800 additions and 142 deletions

View File

@ -1296,30 +1296,32 @@
<varlistentry>
<term><option>--console=</option><replaceable>MODE</replaceable></term>
<listitem><para>Configures how to set up standard input, output and error output for the container payload, as
well as the <filename>/dev/console</filename> device for the container. Takes one of
<option>interactive</option>, <option>read-only</option>, <option>passive</option> or <option>pipe</option>. If
<option>interactive</option> a pseudo-TTY is allocated and made available as <filename>/dev/console</filename>
in the container. It is then bi-directionally connected to the standard input and output passed to
<command>systemd-nspawn</command>. <option>read-only</option> is similar but only the output of the container
is propagated and no input from the caller is read. In <option>passive</option> mode a pseudo TTY is allocated,
but it is not connected anywhere. Finally, in <option>pipe</option> mode no pseudo TTY is allocated, but the
passed standard input, output and error output file descriptors are passed on — as they are — to the container
payload. In this mode <filename>/dev/console</filename> will not exist in the container. Note that in this mode
the container payload generally cannot be a full init system as init systems tend to require
<filename>/dev/console</filename> to be available. On the other hand, in this mode container invocations can be
used within shell pipelines. This is because intermediary pseudo TTYs do not permit independent bidirectional
propagation of the end-of-file (EOF) condition, which is necessary for shell pipelines to work
correctly.</para>
<para>Note that the <option>pipe</option> mode should be used carefully, as passing arbitrary file descriptors
to less trusted container payloads might open up unwanted interfaces for access by the container payload. For
example, if a passed file descriptor refers to a TTY of some form, APIs such as <constant>TIOCSTI</constant>
may be used to synthesize input that might be used for escaping the container. Hence <option>pipe</option> mode
should only be used if the payload is sufficiently trusted or when the standard input/output/error output file
descriptors are known safe, for example pipes. Defaults to <option>interactive</option> if
<listitem><para>Configures how to set up standard input, output and error output for the container
payload, as well as the <filename>/dev/console</filename> device for the container. Takes one of
<option>interactive</option>, <option>read-only</option>, <option>passive</option>, or
<option>pipe</option>. If <option>interactive</option>, a pseudo-TTY is allocated and made available
as <filename>/dev/console</filename> in the container. It is then bi-directionally connected to the
standard input and output passed to <command>systemd-nspawn</command>. <option>read-only</option> is
similar but only the output of the container is propagated and no input from the caller is read. If
<option>passive</option>, a pseudo TTY is allocated, but it is not connected anywhere. Finally, in
<option>pipe</option> mode no pseudo TTY is allocated, but the standard input, output and error
output file descriptors passed to <command>systemd-nspawn</command> are passed on — as they are — to
the container payload, see the following paragraph. Defaults to <option>interactive</option> if
<command>systemd-nspawn</command> is invoked from a terminal, and <option>read-only</option>
otherwise.</para></listitem>
otherwise.</para>
<para>In <option>pipe</option> mode, <filename>/dev/console</filename> will not exist in the
container. This means that the container payload generally cannot be a full init system as init
systems tend to require <filename>/dev/console</filename> to be available. On the other hand, in this
mode container invocations can be used within shell pipelines. This is because intermediary pseudo
TTYs do not permit independent bidirectional propagation of the end-of-file (EOF) condition, which is
necessary for shell pipelines to work correctly. <emphasis>Note that the <option>pipe</option> mode
should be used carefully</emphasis>, as passing arbitrary file descriptors to less trusted container
payloads might open up unwanted interfaces for access by the container payload. For example, if a
passed file descriptor refers to a TTY of some form, APIs such as <constant>TIOCSTI</constant> may be
used to synthesize input that might be used for escaping the container. Hence <option>pipe</option>
mode should only be used if the payload is sufficiently trusted or when the standard
input/output/error output file descriptors are known safe, for example pipes.</para></listitem>
</varlistentry>
<varlistentry>

View File

@ -117,6 +117,7 @@
<varlistentry>
<term><option>--unit=</option></term>
<term><option>-u</option></term>
<listitem><para>Use this unit name instead of an automatically
generated one.</para></listitem>

View File

@ -2018,6 +2018,16 @@ Local=10.65.223.238
Remote=10.65.223.239</programlisting>
</example>
<example>
<title>/etc/systemd/network/25-ip6gre.netdev</title>
<programlisting>[NetDev]
Name=ip6gre-tun
Kind=ip6gre
[Tunnel]
Key=123</programlisting>
</example>
<example>
<title>/etc/systemd/network/25-vti.netdev</title>

View File

@ -153,6 +153,24 @@
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><varname>SSID=</varname></term>
<listitem>
<para>A whitespace-separated list of shell-style globs matching the SSID of the currently
connected wireless LAN. If the list is prefixed with a "!", the test is inverted.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><varname>BSSID=</varname></term>
<listitem>
<para>A whitespace-separated list of hardware address of the currently connected wireless
LAN. Use full colon-, hyphen- or dot-delimited hexadecimal. See the example in
<varname>MACAddress=</varname>. This option may appear more than one, in which case the
lists are merged. If the empty string is assigned to this option, the list of BSSID defined
prior to this is reset.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><varname>Host=</varname></term>
<listitem>

View File

@ -2,20 +2,21 @@
#
# Traditional Chinese translation for systemd.
# Jeff Huang <s8321414@gmail.com>, 2015, 2016.
# pan93412 <pan93412@gmail.com>, 2019.
msgid ""
msgstr ""
"Project-Id-Version: \n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2019-05-24 23:59+0800\n"
"PO-Revision-Date: 2019-05-25 00:38+0800\n"
"POT-Creation-Date: 2019-10-23 19:12+0800\n"
"PO-Revision-Date: 2019-10-23 19:19+0800\n"
"Last-Translator: pan93412 <pan93412@gmail.com>\n"
"Language-Team: chinese-l10n <chinese-l10n@googlegroups.com>\n"
"Language-Team: Chinese <chinese-l10n@googlegroups.com>\n"
"Language: zh_TW\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=n != 1;\n"
"X-Generator: Poedit 2.2.1\n"
"X-Generator: Lokalize 19.08.2\n"
#: src/core/org.freedesktop.systemd1.policy.in:22
msgid "Send passphrase back to system"
@ -50,7 +51,7 @@ msgstr "設定或取消設定系統及服務管理員環境變數"
msgid ""
"Authentication is required to set or unset system and service manager "
"environment variables."
msgstr "需要身份驗證,才能設定或取消設定系統及服務管理員的環境變數。"
msgstr "設定或取消設定系統及服務管理員的環境變數需要身份驗證。"
#: src/core/org.freedesktop.systemd1.policy.in:64
msgid "Reload the systemd state"
@ -76,7 +77,7 @@ msgstr "設定靜態主機名稱"
msgid ""
"Authentication is required to set the statically configured local host name, "
"as well as the pretty host name."
msgstr "需要身份驗證,才能設定靜態預先設定或 pretty 本地主機名稱。"
msgstr "設定靜態預先設定或 pretty 本地主機名稱需要身份驗證。"
#: src/hostname/org.freedesktop.hostname1.policy:41
msgid "Set machine information"
@ -84,7 +85,7 @@ msgstr "設定機器資訊"
#: src/hostname/org.freedesktop.hostname1.policy:42
msgid "Authentication is required to set local machine information."
msgstr "需要身份驗證,才能設定本地機器資訊。"
msgstr "設定本地機器資訊需要身份驗證。"
#: src/hostname/org.freedesktop.hostname1.policy:51
msgid "Get product UUID"
@ -332,7 +333,7 @@ msgstr "在應用程式阻止時停止系統"
msgid ""
"Authentication is required for halting the system while an application asked "
"to inhibit it."
msgstr "需要身份驗證,才能在應用程式阻止時停止系統。"
msgstr "在應用程式阻止時停止系統需要身份驗證。"
#: src/login/org.freedesktop.login1.policy:257
msgid "Suspend the system"
@ -413,7 +414,7 @@ msgstr "設定內核中的重新啟動 \"reason (原因)\""
#: src/login/org.freedesktop.login1.policy:342
msgid "Authentication is required to set the reboot \"reason\" in the kernel."
msgstr "需要身份驗證,才能設定內核中的重新啟動 \"reason (原因)\"。"
msgstr "設定內核中的重新啟動 \"reason (原因)\"需要身份驗證。"
#: src/login/org.freedesktop.login1.policy:352
msgid "Indicate to the firmware to boot to setup interface"
@ -433,7 +434,7 @@ msgstr "引導開機載入器啟動開機載入選單"
msgid ""
"Authentication is required to indicate to the boot loader to boot to the "
"boot loader menu."
msgstr "需要身份驗證,才能引導開機載入器啟動開機載入器選單。"
msgstr "引導開機載入器啟動開機載入器選單需要身份驗證。"
#: src/login/org.freedesktop.login1.policy:374
msgid "Indicate to the boot loader to boot a specific entry"
@ -443,7 +444,7 @@ msgstr "引導開機載入器啟動指定項目"
msgid ""
"Authentication is required to indicate to the boot loader to boot into a "
"specific boot loader entry."
msgstr "需要身份驗證,才能引導開機載入器啟動指定的開機載入器項目。"
msgstr "引導開機載入器啟動指定的開機載入器項目需要身份驗證。"
#: src/login/org.freedesktop.login1.policy:385
msgid "Set a wall message"
@ -451,7 +452,7 @@ msgstr "設定 wall 訊息"
#: src/login/org.freedesktop.login1.policy:386
msgid "Authentication is required to set a wall message"
msgstr "需要身份驗證,才能設定 wall 訊息"
msgstr "設定 wall 訊息需要身份驗證"
#: src/machine/org.freedesktop.machine1.policy:22
msgid "Log into a local container"
@ -521,13 +522,125 @@ msgid ""
"images."
msgstr "管理本機虛擬機器及容器映像需要驗證。"
#: src/network/org.freedesktop.network1.policy:22
msgid "Set NTP servers"
msgstr "設定 NTP 伺服器"
#: src/network/org.freedesktop.network1.policy:23
msgid "Authentication is required to set NTP servers."
msgstr "設定 NTP 伺服器需要身份驗證。"
#: src/network/org.freedesktop.network1.policy:33
#: src/resolve/org.freedesktop.resolve1.policy:44
msgid "Set DNS servers"
msgstr "設定 DNS 伺服器"
#: src/network/org.freedesktop.network1.policy:34
#: src/resolve/org.freedesktop.resolve1.policy:45
msgid "Authentication is required to set DNS servers."
msgstr "設定 DNS 伺服器需要身份驗證。"
#: src/network/org.freedesktop.network1.policy:44
#: src/resolve/org.freedesktop.resolve1.policy:55
msgid "Set domains"
msgstr "設定網域"
#: src/network/org.freedesktop.network1.policy:45
#: src/resolve/org.freedesktop.resolve1.policy:56
msgid "Authentication is required to set domains."
msgstr "設定網域需要身份驗證。"
#: src/network/org.freedesktop.network1.policy:55
#: src/resolve/org.freedesktop.resolve1.policy:66
msgid "Set default route"
msgstr "設定預設路由"
#: src/network/org.freedesktop.network1.policy:56
#: src/resolve/org.freedesktop.resolve1.policy:67
msgid "Authentication is required to set default route."
msgstr "設定預設路由需要身份驗證。"
#: src/network/org.freedesktop.network1.policy:66
#: src/resolve/org.freedesktop.resolve1.policy:77
msgid "Enable/disable LLMNR"
msgstr "啟用/停用 LLMNR"
#: src/network/org.freedesktop.network1.policy:67
#: src/resolve/org.freedesktop.resolve1.policy:78
msgid "Authentication is required to enable or disable LLMNR."
msgstr "啟用或停用 LLMNR 需要身份驗證。"
#: src/network/org.freedesktop.network1.policy:77
#: src/resolve/org.freedesktop.resolve1.policy:88
msgid "Enable/disable multicast DNS"
msgstr "啟用/停用 多點 DNS"
#: src/network/org.freedesktop.network1.policy:78
#: src/resolve/org.freedesktop.resolve1.policy:89
msgid "Authentication is required to enable or disable multicast DNS."
msgstr "啟用或停用 多點 DNS 需要身份驗證。"
#: src/network/org.freedesktop.network1.policy:88
#: src/resolve/org.freedesktop.resolve1.policy:99
msgid "Enable/disable DNS over TLS"
msgstr "啟用/停用 DNS over TLS"
#: src/network/org.freedesktop.network1.policy:89
#: src/resolve/org.freedesktop.resolve1.policy:100
msgid "Authentication is required to enable or disable DNS over TLS."
msgstr "啟用或停用 DNS over LTS 需要身份驗證。"
#: src/network/org.freedesktop.network1.policy:99
#: src/resolve/org.freedesktop.resolve1.policy:110
msgid "Enable/disable DNSSEC"
msgstr "啟用/停用 DNSSEC"
#: src/network/org.freedesktop.network1.policy:100
#: src/resolve/org.freedesktop.resolve1.policy:111
msgid "Authentication is required to enable or disable DNSSEC."
msgstr "啟用或停用 DNSSEC 需要身份驗證。"
#: src/network/org.freedesktop.network1.policy:110
#: src/resolve/org.freedesktop.resolve1.policy:121
msgid "Set DNSSEC Negative Trust Anchors"
msgstr "設定 DNSSEC Negative Trust Anchors"
#: src/network/org.freedesktop.network1.policy:111
#: src/resolve/org.freedesktop.resolve1.policy:122
msgid "Authentication is required to set DNSSEC Negative Trust Anchors."
msgstr "設定 DNSSEC Negative Trust Anchors 需要身份驗證。"
#: src/network/org.freedesktop.network1.policy:121
msgid "Revert NTP settings"
msgstr "還原 NTP 設定"
#: src/network/org.freedesktop.network1.policy:122
msgid "Authentication is required to reset NTP settings."
msgstr "重設 NTP 設定需要身份驗證。"
#: src/network/org.freedesktop.network1.policy:132
msgid "Revert DNS settings"
msgstr "還原 DNS 設定"
#: src/network/org.freedesktop.network1.policy:133
msgid "Authentication is required to reset DNS settings."
msgstr "重設 DNS 設定需要身份驗證。"
#: src/network/org.freedesktop.network1.policy:143
msgid "Renew dynamic addresses"
msgstr "重新產生動態位址"
#: src/network/org.freedesktop.network1.policy:144
msgid "Authentication is required to renew dynamic addresses."
msgstr "重新產生動態位址需要身份驗證。"
#: src/portable/org.freedesktop.portable1.policy:13
msgid "Inspect a portable service image"
msgstr "檢查可攜式服務映像"
#: src/portable/org.freedesktop.portable1.policy:14
msgid "Authentication is required to inspect a portable service image."
msgstr "需要身份驗證,才能檢查可攜式服務映像。"
msgstr "檢查可攜式服務映像需要身份驗證。"
#: src/portable/org.freedesktop.portable1.policy:23
msgid "Attach or detach a portable service image"
@ -536,7 +649,7 @@ msgstr "連結或取消連結可攜式服務映像"
#: src/portable/org.freedesktop.portable1.policy:24
msgid ""
"Authentication is required to attach or detach a portable service image."
msgstr "需要身份驗證,才能連結或取消連結可攜式服務映像。"
msgstr "連結或取消連結可攜式服務映像需要身份驗證。"
#: src/portable/org.freedesktop.portable1.policy:34
msgid "Delete or modify portable service image"
@ -545,7 +658,7 @@ msgstr "刪除或修改可攜式服務映像"
#: src/portable/org.freedesktop.portable1.policy:35
msgid ""
"Authentication is required to delete or modify a portable service image."
msgstr "需要身份驗證,才能刪除或修改可攜式服務映像。"
msgstr "刪除或修改可攜式服務映像需要身份驗證。"
#: src/resolve/org.freedesktop.resolve1.policy:22
msgid "Register a DNS-SD service"
@ -553,7 +666,7 @@ msgstr "註冊 DNS-SD 服務"
#: src/resolve/org.freedesktop.resolve1.policy:23
msgid "Authentication is required to register a DNS-SD service"
msgstr "需要身份驗證,才能註冊 DNS-SD 服務"
msgstr "註冊 DNS-SD 服務需要身份驗證"
#: src/resolve/org.freedesktop.resolve1.policy:33
msgid "Unregister a DNS-SD service"
@ -561,7 +674,15 @@ msgstr "取消註冊 DNS-SD 服務"
#: src/resolve/org.freedesktop.resolve1.policy:34
msgid "Authentication is required to unregister a DNS-SD service"
msgstr "需要身份驗證,才能取消註冊 DNS-SD 服務"
msgstr "取消註冊 DNS-SD 服務需要身份驗證"
#: src/resolve/org.freedesktop.resolve1.policy:132
msgid "Revert name resolution settings"
msgstr "還原名稱解析設定"
#: src/resolve/org.freedesktop.resolve1.policy:133
msgid "Authentication is required to reset name resolution settings."
msgstr "重設名稱解析設定需要身份驗證。"
#: src/timedate/org.freedesktop.timedate1.policy:22
msgid "Set system time"
@ -599,35 +720,41 @@ msgid ""
"shall be enabled."
msgstr "控制網路時間同步是否啟用需要驗證。"
#: src/core/dbus-unit.c:317
#: src/core/dbus-unit.c:354
msgid "Authentication is required to start '$(unit)'."
msgstr "啟動 '$(unit)' 需要驗證。"
#: src/core/dbus-unit.c:318
#: src/core/dbus-unit.c:355
msgid "Authentication is required to stop '$(unit)'."
msgstr "停止 '$(unit)' 需要驗證。"
#: src/core/dbus-unit.c:319
#: src/core/dbus-unit.c:356
msgid "Authentication is required to reload '$(unit)'."
msgstr "重新載入 '$(unit)' 需要驗證。"
#: src/core/dbus-unit.c:320 src/core/dbus-unit.c:321
#: src/core/dbus-unit.c:357 src/core/dbus-unit.c:358
msgid "Authentication is required to restart '$(unit)'."
msgstr "重新啟動 '$(unit)' 需要驗證。"
#: src/core/dbus-unit.c:493
#: src/core/dbus-unit.c:530
msgid ""
"Authentication is required to send a UNIX signal to the processes of "
"'$(unit)'."
msgstr "需要身份驗證,才能傳送 UNIX 信號至「$(unit)」的程序。"
msgstr "傳送 UNIX 信號至「$(unit)」的程序需要身份驗證。"
#: src/core/dbus-unit.c:524
#: src/core/dbus-unit.c:561
msgid "Authentication is required to reset the \"failed\" state of '$(unit)'."
msgstr "重置 '$(unit)' 的「失敗」狀態需要驗證。"
#: src/core/dbus-unit.c:557
#: src/core/dbus-unit.c:594
msgid "Authentication is required to set properties on '$(unit)'."
msgstr "在 '$(unit)' 上設定屬性需要驗證。"
#: src/core/dbus-unit.c:703
msgid ""
"Authentication is required to delete files and directories associated with "
"'$(unit)'."
msgstr "刪除與 '$(unit)' 相關的檔案及目錄需要身份驗證。"
#~ msgid "Authentication is required to kill '$(unit)'."
#~ msgstr "砍除 '$(unit)' 需要驗證。"

View File

@ -142,9 +142,13 @@ bool net_match_config(Set *match_mac,
char * const *match_types,
char * const *match_names,
char * const *match_property,
char * const *match_ssid,
Set *match_bssid,
sd_device *device,
const struct ether_addr *dev_mac,
const char *dev_name) {
const char *dev_name,
const char *ssid,
const struct ether_addr *bssid) {
const char *dev_path = NULL, *dev_driver = NULL, *dev_type = NULL, *mac_str;
@ -178,6 +182,12 @@ bool net_match_config(Set *match_mac,
if (!net_condition_test_property(match_property, device))
return false;
if (!net_condition_test_strv(match_ssid, ssid))
return false;
if (match_bssid && (!bssid || !set_contains(match_bssid, bssid)))
return false;
return true;
}

View File

@ -20,9 +20,13 @@ bool net_match_config(Set *match_mac,
char * const *match_type,
char * const *match_name,
char * const *match_property,
char * const *match_ssid,
Set *match_bssid,
sd_device *device,
const struct ether_addr *dev_mac,
const char *dev_name);
const char *dev_name,
const char *ssid,
const struct ether_addr *bssid);
CONFIG_PARSER_PROTOTYPE(config_parse_net_condition);
CONFIG_PARSER_PROTOTYPE(config_parse_hwaddr);

View File

@ -71,6 +71,7 @@ libsystemd_sources = files('''
sd-hwdb/hwdb-util.h
sd-hwdb/sd-hwdb.c
sd-netlink/generic-netlink.c
sd-netlink/generic-netlink.h
sd-netlink/netlink-internal.h
sd-netlink/netlink-message.c
sd-netlink/netlink-slot.c

View File

@ -1,8 +1,12 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#include <linux/genetlink.h>
#include "sd-netlink.h"
#include "netlink-internal.h"
#include "alloc-util.h"
#include "generic-netlink.h"
#include "netlink-internal.h"
typedef struct {
const char* name;
@ -15,6 +19,7 @@ static const genl_family genl_families[] = {
[SD_GENL_FOU] = { .name = "fou", .version = 1 },
[SD_GENL_L2TP] = { .name = "l2tp", .version = 1 },
[SD_GENL_MACSEC] = { .name = "macsec", .version = 1 },
[SD_GENL_NL80211] = { .name = "nl80211", .version = 1 },
};
int sd_genl_socket_open(sd_netlink **ret) {
@ -23,12 +28,12 @@ int sd_genl_socket_open(sd_netlink **ret) {
static int lookup_id(sd_netlink *nl, sd_genl_family family, uint16_t *id);
static int genl_message_new(sd_netlink *nl, sd_genl_family family, uint16_t nlmsg_type, uint8_t cmd, sd_netlink_message **ret) {
int r;
struct genlmsghdr *genl;
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL;
const NLType *genl_cmd_type, *nl_type;
const NLTypeSystem *type_system;
struct genlmsghdr *genl;
size_t size;
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL;
int r;
assert_return(nl->protocol == NETLINK_GENERIC, -EINVAL);
@ -67,21 +72,33 @@ static int genl_message_new(sd_netlink *nl, sd_genl_family family, uint16_t nlms
}
int sd_genl_message_new(sd_netlink *nl, sd_genl_family family, uint8_t cmd, sd_netlink_message **ret) {
uint16_t id;
int r;
uint16_t id = GENL_ID_CTRL;
if (family != SD_GENL_ID_CTRL) {
r = lookup_id(nl, family, &id);
if (r < 0)
return r;
}
r = lookup_id(nl, family, &id);
if (r < 0)
return r;
return genl_message_new(nl, family, id, cmd, ret);
}
static int lookup_id(sd_netlink *nl, sd_genl_family family, uint16_t *id) {
int r;
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL, *reply = NULL;
uint16_t u;
void *v;
int r;
if (family == SD_GENL_ID_CTRL) {
*id = GENL_ID_CTRL;
return 0;
}
v = hashmap_get(nl->genl_family_to_nlmsg_type, INT_TO_PTR(family));
if (v) {
*id = PTR_TO_UINT(v);
return 0;
}
r = sd_genl_message_new(nl, SD_GENL_ID_CTRL, CTRL_CMD_GETFAMILY, &req);
if (r < 0)
@ -95,5 +112,66 @@ static int lookup_id(sd_netlink *nl, sd_genl_family family, uint16_t *id) {
if (r < 0)
return r;
return sd_netlink_message_read_u16(reply, CTRL_ATTR_FAMILY_ID, id);
r = sd_netlink_message_read_u16(reply, CTRL_ATTR_FAMILY_ID, &u);
if (r < 0)
return r;
r = hashmap_ensure_allocated(&nl->genl_family_to_nlmsg_type, NULL);
if (r < 0)
return r;
r = hashmap_ensure_allocated(&nl->nlmsg_type_to_genl_family, NULL);
if (r < 0)
return r;
r = hashmap_put(nl->genl_family_to_nlmsg_type, INT_TO_PTR(family), UINT_TO_PTR(u));
if (r < 0)
return r;
r = hashmap_put(nl->nlmsg_type_to_genl_family, UINT_TO_PTR(u), INT_TO_PTR(family));
if (r < 0)
return r;
*id = u;
return 0;
}
int nlmsg_type_to_genl_family(sd_netlink *nl, uint16_t type, sd_genl_family *ret) {
void *p;
assert_return(nl, -EINVAL);
assert_return(nl->protocol == NETLINK_GENERIC, -EINVAL);
assert(ret);
if (type == NLMSG_ERROR)
*ret = SD_GENL_ERROR;
else if (type == NLMSG_DONE)
*ret = SD_GENL_DONE;
else if (type == GENL_ID_CTRL)
*ret = SD_GENL_ID_CTRL;
else {
p = hashmap_get(nl->nlmsg_type_to_genl_family, UINT_TO_PTR(type));
if (!p)
return -EOPNOTSUPP;
*ret = PTR_TO_INT(p);
}
return 0;
}
int sd_genl_message_get_family(sd_netlink *nl, sd_netlink_message *m, sd_genl_family *family) {
uint16_t type;
int r;
assert_return(m, -EINVAL);
assert_return(nl, -EINVAL);
assert_return(nl->protocol == NETLINK_GENERIC, -EINVAL);
assert_return(family, -EINVAL);
r = sd_netlink_message_get_type(m, &type);
if (r < 0)
return r;
return nlmsg_type_to_genl_family(nl, type, family);
}

View File

@ -0,0 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
#include "sd-netlink.h"
int nlmsg_type_to_genl_family(sd_netlink *nl, uint16_t type, sd_genl_family *ret);

View File

@ -98,6 +98,9 @@ struct sd_netlink {
sd_event_source *time_event_source;
sd_event_source *exit_event_source;
sd_event *event;
Hashmap *genl_family_to_nlmsg_type;
Hashmap *nlmsg_type_to_genl_family;
};
struct netlink_attribute {
@ -116,8 +119,6 @@ struct netlink_container {
struct sd_netlink_message {
unsigned n_ref;
sd_netlink *rtnl;
int protocol;
struct nlmsghdr *hdr;

View File

@ -31,13 +31,15 @@ int message_new_empty(sd_netlink *rtnl, sd_netlink_message **ret) {
buses and their queued messages. See sd-bus.
*/
m = new0(sd_netlink_message, 1);
m = new(sd_netlink_message, 1);
if (!m)
return -ENOMEM;
m->n_ref = 1;
m->protocol = rtnl->protocol;
m->sealed = false;
*m = (sd_netlink_message) {
.n_ref = 1,
.protocol = rtnl->protocol,
.sealed = false,
};
*ret = m;
@ -47,15 +49,12 @@ int message_new_empty(sd_netlink *rtnl, sd_netlink_message **ret) {
int message_new(sd_netlink *rtnl, sd_netlink_message **ret, uint16_t type) {
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL;
const NLType *nl_type;
const NLTypeSystem *type_system_root;
size_t size;
int r;
assert_return(rtnl, -EINVAL);
type_system_root = type_system_get_root(rtnl->protocol);
r = type_system_get_type(type_system_root, &nl_type, type);
r = type_system_root_get_type(rtnl, &nl_type, type);
if (r < 0)
return r;
@ -616,6 +615,32 @@ int sd_netlink_message_read(sd_netlink_message *m, unsigned short type, size_t s
return r;
}
int sd_netlink_message_read_string_strdup(sd_netlink_message *m, unsigned short type, char **data) {
void *attr_data;
char *str;
int r;
assert_return(m, -EINVAL);
r = message_attribute_has_type(m, NULL, type, NETLINK_TYPE_STRING);
if (r < 0)
return r;
r = netlink_message_read_internal(m, type, &attr_data, NULL);
if (r < 0)
return r;
if (data) {
str = strndup(attr_data, r);
if (!str)
return -ENOMEM;
*data = str;
}
return 0;
}
int sd_netlink_message_read_string(sd_netlink_message *m, unsigned short type, const char **data) {
int r;
void *attr_data;
@ -997,22 +1022,20 @@ int sd_netlink_message_get_errno(sd_netlink_message *m) {
return err->error;
}
int sd_netlink_message_rewind(sd_netlink_message *m) {
int sd_netlink_message_rewind(sd_netlink_message *m, sd_netlink *genl) {
const NLType *nl_type;
const NLTypeSystem *type_system_root;
uint16_t type;
size_t size;
unsigned i;
int r;
assert_return(m, -EINVAL);
assert_return(genl || m->protocol != NETLINK_GENERIC, -EINVAL);
/* don't allow appending to message once parsed */
if (!m->sealed)
rtnl_message_seal(m);
type_system_root = type_system_get_root(m->protocol);
for (i = 1; i <= m->n_containers; i++)
m->containers[i].attributes = mfree(m->containers[i].attributes);
@ -1024,7 +1047,7 @@ int sd_netlink_message_rewind(sd_netlink_message *m) {
assert(m->hdr);
r = type_system_get_type(type_system_root, &nl_type, m->hdr->nlmsg_type);
r = type_system_root_get_type(genl, &nl_type, m->hdr->nlmsg_type);
if (r < 0)
return r;

View File

@ -313,14 +313,11 @@ int socket_read_message(sd_netlink *rtnl) {
size_t len;
int r;
unsigned i = 0;
const NLTypeSystem *type_system_root;
assert(rtnl);
assert(rtnl->rbuffer);
assert(rtnl->rbuffer_allocated >= sizeof(struct nlmsghdr));
type_system_root = type_system_get_root(rtnl->protocol);
/* read nothing, just get the pending message size */
r = socket_recv_message(rtnl->fd, &iov, NULL, true);
if (r <= 0)
@ -381,7 +378,7 @@ int socket_read_message(sd_netlink *rtnl) {
}
/* check that we support this message type */
r = type_system_get_type(type_system_root, &nl_type, new_msg->nlmsg_type);
r = type_system_root_get_type(rtnl, &nl_type, new_msg->nlmsg_type);
if (r < 0) {
if (r == -EOPNOTSUPP)
log_debug("sd-netlink: ignored message with unknown type: %i",
@ -407,7 +404,7 @@ int socket_read_message(sd_netlink *rtnl) {
return -ENOMEM;
/* seal and parse the top-level message */
r = sd_netlink_message_rewind(m);
r = sd_netlink_message_rewind(m, rtnl);
if (r < 0)
return r;

View File

@ -20,13 +20,18 @@
#include <linux/if_tunnel.h>
#include <linux/nexthop.h>
#include <linux/l2tp.h>
#include <linux/nl80211.h>
#include <linux/veth.h>
#include <linux/wireguard.h>
#include "sd-netlink.h"
#include "generic-netlink.h"
#include "hashmap.h"
#include "macro.h"
#include "missing.h"
#include "netlink-internal.h"
#include "netlink-types.h"
#include "sd-netlink.h"
#include "string-table.h"
#include "util.h"
@ -984,24 +989,60 @@ static const NLTypeSystem genl_macsec_device_type_system = {
.types = genl_macsec,
};
static const NLType genl_nl80211_types[] = {
[NL80211_ATTR_IFINDEX] = { .type = NETLINK_TYPE_U32 },
[NL80211_ATTR_MAC] = { .type = NETLINK_TYPE_ETHER_ADDR },
[NL80211_ATTR_SSID] = { .type = NETLINK_TYPE_STRING },
};
static const NLTypeSystem genl_nl80211_type_system = {
.count = ELEMENTSOF(genl_nl80211_types),
.types = genl_nl80211_types,
};
static const NLType genl_nl80211_cmds[] = {
[NL80211_CMD_GET_WIPHY] = { .type = NETLINK_TYPE_NESTED, .type_system = &genl_nl80211_type_system },
[NL80211_CMD_SET_WIPHY] = { .type = NETLINK_TYPE_NESTED, .type_system = &genl_nl80211_type_system },
[NL80211_CMD_NEW_WIPHY] = { .type = NETLINK_TYPE_NESTED, .type_system = &genl_nl80211_type_system },
[NL80211_CMD_DEL_WIPHY] = { .type = NETLINK_TYPE_NESTED, .type_system = &genl_nl80211_type_system },
[NL80211_CMD_GET_INTERFACE] = { .type = NETLINK_TYPE_NESTED, .type_system = &genl_nl80211_type_system },
[NL80211_CMD_SET_INTERFACE] = { .type = NETLINK_TYPE_NESTED, .type_system = &genl_nl80211_type_system },
[NL80211_CMD_NEW_INTERFACE] = { .type = NETLINK_TYPE_NESTED, .type_system = &genl_nl80211_type_system },
[NL80211_CMD_DEL_INTERFACE] = { .type = NETLINK_TYPE_NESTED, .type_system = &genl_nl80211_type_system },
[NL80211_CMD_GET_STATION] = { .type = NETLINK_TYPE_NESTED, .type_system = &genl_nl80211_type_system },
[NL80211_CMD_SET_STATION] = { .type = NETLINK_TYPE_NESTED, .type_system = &genl_nl80211_type_system },
[NL80211_CMD_NEW_STATION] = { .type = NETLINK_TYPE_NESTED, .type_system = &genl_nl80211_type_system },
[NL80211_CMD_DEL_STATION] = { .type = NETLINK_TYPE_NESTED, .type_system = &genl_nl80211_type_system },
};
static const NLTypeSystem genl_nl80211_cmds_type_system = {
.count = ELEMENTSOF(genl_nl80211_cmds),
.types = genl_nl80211_cmds,
};
static const NLType genl_families[] = {
[SD_GENL_ID_CTRL] = { .type = NETLINK_TYPE_NESTED, .type_system = &genl_ctrl_id_ctrl_type_system },
[SD_GENL_WIREGUARD] = { .type = NETLINK_TYPE_NESTED, .type_system = &genl_wireguard_type_system },
[SD_GENL_FOU] = { .type = NETLINK_TYPE_NESTED, .type_system = &genl_fou_cmds_type_system},
[SD_GENL_FOU] = { .type = NETLINK_TYPE_NESTED, .type_system = &genl_fou_cmds_type_system },
[SD_GENL_L2TP] = { .type = NETLINK_TYPE_NESTED, .type_system = &genl_l2tp_tunnel_session_type_system },
[SD_GENL_MACSEC] = { .type = NETLINK_TYPE_NESTED, .type_system = &genl_macsec_device_type_system },
[SD_GENL_NL80211] = { .type = NETLINK_TYPE_NESTED, .type_system = &genl_nl80211_cmds_type_system },
};
/* Mainly used when sending message */
const NLTypeSystem genl_family_type_system_root = {
.count = ELEMENTSOF(genl_families),
.types = genl_families,
};
static const NLType genl_types[] = {
[NLMSG_ERROR] = { .type = NETLINK_TYPE_NESTED, .type_system = &empty_type_system, .size = sizeof(struct nlmsgerr) },
[GENL_ID_CTRL] = { .type = NETLINK_TYPE_NESTED, .type_system = &genl_get_family_type_system, .size = sizeof(struct genlmsghdr) },
[SD_GENL_ERROR] = { .type = NETLINK_TYPE_NESTED, .type_system = &empty_type_system, .size = sizeof(struct nlmsgerr) },
[SD_GENL_DONE] = { .type = NETLINK_TYPE_NESTED, .type_system = &empty_type_system },
[SD_GENL_ID_CTRL] = { .type = NETLINK_TYPE_NESTED, .type_system = &genl_get_family_type_system, .size = sizeof(struct genlmsghdr) },
[SD_GENL_NL80211] = { .type = NETLINK_TYPE_NESTED, .type_system = &genl_nl80211_type_system, .size = sizeof(struct genlmsghdr) },
};
/* Mainly used when message received */
const NLTypeSystem genl_type_system_root = {
.count = ELEMENTSOF(genl_types),
.types = genl_types,
@ -1049,6 +1090,31 @@ const NLTypeSystem *type_system_get_root(int protocol) {
}
}
int type_system_root_get_type(sd_netlink *nl, const NLType **ret, uint16_t type) {
sd_genl_family family;
const NLType *nl_type;
int r;
if (!nl || nl->protocol != NETLINK_GENERIC)
return type_system_get_type(&rtnl_type_system_root, ret, type);
r = nlmsg_type_to_genl_family(nl, type, &family);
if (r < 0)
return r;
if (family >= genl_type_system_root.count)
return -EOPNOTSUPP;
nl_type = &genl_type_system_root.types[family];
if (nl_type->type == NETLINK_TYPE_UNSPEC)
return -EOPNOTSUPP;
*ret = nl_type;
return 0;
}
int type_system_get_type(const NLTypeSystem *type_system, const NLType **ret, uint16_t type) {
const NLType *nl_type;

View File

@ -36,8 +36,6 @@ struct NLTypeSystemUnion {
const NLTypeSystem *type_systems;
};
extern const NLTypeSystem rtnl_type_system_root;
extern const NLTypeSystem genl_type_system_root;
extern const NLTypeSystem genl_family_type_system_root;
uint16_t type_get_type(const NLType *type);
@ -47,6 +45,7 @@ void type_get_type_system_union(const NLType *type, const NLTypeSystemUnion **re
const NLTypeSystem* type_system_get_root(int protocol);
uint16_t type_system_get_count(const NLTypeSystem *type_system);
int type_system_root_get_type(sd_netlink *nl, const NLType **ret, uint16_t type);
int type_system_get_type(const NLTypeSystem *type_system, const NLType **ret, uint16_t type);
int type_system_get_type_system(const NLTypeSystem *type_system, const NLTypeSystem **ret, uint16_t type);
int type_system_get_type_system_union(const NLTypeSystem *type_system, const NLTypeSystemUnion **ret, uint16_t type);

View File

@ -178,6 +178,9 @@ static sd_netlink *netlink_free(sd_netlink *rtnl) {
hashmap_free(rtnl->broadcast_group_refs);
hashmap_free(rtnl->genl_family_to_nlmsg_type);
hashmap_free(rtnl->nlmsg_type_to_genl_family);
safe_close(rtnl->fd);
return mfree(rtnl);
}

View File

@ -26,7 +26,7 @@ static void test_message_link_bridge(sd_netlink *rtnl) {
assert_se(sd_netlink_message_append_u32(message, IFLA_BRPORT_COST, 10) >= 0);
assert_se(sd_netlink_message_close_container(message) >= 0);
assert_se(sd_netlink_message_rewind(message) >= 0);
assert_se(sd_netlink_message_rewind(message, NULL) >= 0);
assert_se(sd_netlink_message_enter_container(message, IFLA_PROTINFO) >= 0);
assert_se(sd_netlink_message_read_u32(message, IFLA_BRPORT_COST, &cost) >= 0);
@ -49,7 +49,7 @@ static void test_link_configure(sd_netlink *rtnl, int ifindex) {
assert_se(sd_netlink_message_append_u32(message, IFLA_MTU, mtu) >= 0);
assert_se(sd_netlink_call(rtnl, message, 0, NULL) == 1);
assert_se(sd_netlink_message_rewind(message) >= 0);
assert_se(sd_netlink_message_rewind(message, NULL) >= 0);
assert_se(sd_netlink_message_read_string(message, IFLA_IFNAME, &name_out) >= 0);
assert_se(streq(name, name_out));
@ -153,7 +153,7 @@ static void test_route(sd_netlink *rtnl) {
return;
}
assert_se(sd_netlink_message_rewind(req) >= 0);
assert_se(sd_netlink_message_rewind(req, NULL) >= 0);
assert_se(sd_netlink_message_read_in_addr(req, RTA_GATEWAY, &addr_data) >= 0);
assert_se(addr_data.s_addr == addr.s_addr);
@ -439,7 +439,7 @@ static void test_container(sd_netlink *rtnl) {
assert_se(sd_netlink_message_close_container(m) >= 0);
assert_se(sd_netlink_message_close_container(m) == -EINVAL);
assert_se(sd_netlink_message_rewind(m) >= 0);
assert_se(sd_netlink_message_rewind(m, NULL) >= 0);
assert_se(sd_netlink_message_enter_container(m, IFLA_LINKINFO) >= 0);
assert_se(sd_netlink_message_read_string(m, IFLA_INFO_KIND, &string_data) >= 0);
@ -530,7 +530,7 @@ static void test_array(void) {
assert_se(sd_netlink_message_close_container(m) >= 0);
rtnl_message_seal(m);
assert_se(sd_netlink_message_rewind(m) >= 0);
assert_se(sd_netlink_message_rewind(m, genl) >= 0);
assert_se(sd_netlink_message_enter_container(m, CTRL_ATTR_MCAST_GROUPS) >= 0);
for (unsigned i = 0; i < 10; i++) {

View File

@ -103,6 +103,8 @@ sources = files('''
networkd-speed-meter.h
networkd-util.c
networkd-util.h
networkd-wifi.c
networkd-wifi.h
'''.split())
systemd_networkd_sources = files('networkd.c')

View File

@ -226,6 +226,10 @@ static int netdev_gre_erspan_fill_message_create(NetDev *netdev, Link *link, sd_
}
static int netdev_ip6gre_fill_message_create(NetDev *netdev, Link *link, sd_netlink_message *m) {
uint32_t ikey = 0;
uint32_t okey = 0;
uint16_t iflags = 0;
uint16_t oflags = 0;
Tunnel *t;
int r;
@ -267,6 +271,38 @@ static int netdev_ip6gre_fill_message_create(NetDev *netdev, Link *link, sd_netl
if (r < 0)
return log_netdev_error_errno(netdev, r, "Could not append IFLA_GRE_FLAGS attribute: %m");
if (t->key != 0) {
ikey = okey = htobe32(t->key);
iflags |= GRE_KEY;
oflags |= GRE_KEY;
}
if (t->ikey != 0) {
ikey = htobe32(t->ikey);
iflags |= GRE_KEY;
}
if (t->okey != 0) {
okey = htobe32(t->okey);
oflags |= GRE_KEY;
}
r = sd_netlink_message_append_u32(m, IFLA_GRE_IKEY, ikey);
if (r < 0)
return log_netdev_error_errno(netdev, r, "Could not append IFLA_GRE_IKEY attribute: %m");
r = sd_netlink_message_append_u32(m, IFLA_GRE_OKEY, okey);
if (r < 0)
return log_netdev_error_errno(netdev, r, "Could not append IFLA_GRE_OKEY attribute: %m");
r = sd_netlink_message_append_u16(m, IFLA_GRE_IFLAGS, iflags);
if (r < 0)
return log_netdev_error_errno(netdev, r, "Could not append IFLA_GRE_IFLAGS attribute: %m");
r = sd_netlink_message_append_u16(m, IFLA_GRE_OFLAGS, oflags);
if (r < 0)
return log_netdev_error_errno(netdev, r, "Could not append IFLA_GRE_OFLAGS, attribute: %m");
return r;
}

View File

@ -33,6 +33,7 @@
#include "networkd-neighbor.h"
#include "networkd-radv.h"
#include "networkd-routing-policy-rule.h"
#include "networkd-wifi.h"
#include "set.h"
#include "socket-util.h"
#include "stdio-util.h"
@ -661,6 +662,25 @@ void link_dns_settings_clear(Link *link) {
link->dnssec_negative_trust_anchors = set_free_free(link->dnssec_negative_trust_anchors);
}
static void link_free_engines(Link *link) {
if (!link)
return;
link->dhcp_server = sd_dhcp_server_unref(link->dhcp_server);
link->dhcp_client = sd_dhcp_client_unref(link->dhcp_client);
link->dhcp_lease = sd_dhcp_lease_unref(link->dhcp_lease);
link->dhcp_routes = set_free(link->dhcp_routes);
link->lldp = sd_lldp_unref(link->lldp);
ndisc_flush(link);
link->ipv4ll = sd_ipv4ll_unref(link->ipv4ll);
link->dhcp6_client = sd_dhcp6_client_unref(link->dhcp6_client);
link->ndisc = sd_ndisc_unref(link->ndisc);
link->radv = sd_radv_unref(link->radv);
}
static Link *link_free(Link *link) {
Address *address;
@ -686,27 +706,14 @@ static Link *link_free(Link *link) {
address_free(address);
}
sd_dhcp_server_unref(link->dhcp_server);
sd_dhcp_client_unref(link->dhcp_client);
sd_dhcp_lease_unref(link->dhcp_lease);
set_free(link->dhcp_routes);
link_lldp_emit_stop(link);
link_free_engines(link);
free(link->lease_file);
sd_lldp_unref(link->lldp);
free(link->lldp_file);
ndisc_flush(link);
sd_ipv4ll_unref(link->ipv4ll);
sd_dhcp6_client_unref(link->dhcp6_client);
sd_ndisc_unref(link->ndisc);
sd_radv_unref(link->radv);
free(link->ifname);
free(link->kind);
free(link->ssid);
(void) unlink(link->state_file);
free(link->state_file);
@ -2850,6 +2857,78 @@ static int link_configure_duid(Link *link) {
return 0;
}
int link_reconfigure(Link *link) {
Network *network;
int r;
if (IN_SET(link->state, LINK_STATE_PENDING, LINK_STATE_LINGER))
return 0;
r = network_get(link->manager, link->sd_device, link->ifname,
&link->mac, link->ssid, &link->bssid, &network);
if (r == -ENOENT) {
link_enter_unmanaged(link);
return 0;
} else if (r == 0 && network->unmanaged) {
link_enter_unmanaged(link);
return 0;
} else if (r < 0)
return r;
if (link->network == network)
return 0;
log_link_info(link, "Re-configuring with %s", network->filename);
/* Dropping old .network file */
r = link_stop_clients(link, false);
if (r < 0) {
link_enter_failed(link);
return r;
}
if (link_dhcp4_server_enabled(link))
(void) sd_dhcp_server_stop(link->dhcp_server);
r = link_drop_config(link);
if (r < 0)
return r;
if (!IN_SET(link->state, LINK_STATE_UNMANAGED, LINK_STATE_PENDING)) {
log_link_debug(link, "State is %s, dropping config", link_state_to_string(link->state));
r = link_drop_foreign_config(link);
if (r < 0)
return r;
}
link_free_carrier_maps(link);
link_free_engines(link);
link->network = network_unref(link->network);
/* Then, apply new .network file */
r = network_apply(network, link);
if (r < 0)
return r;
r = link_new_carrier_maps(link);
if (r < 0)
return r;
link_set_state(link, LINK_STATE_INITIALIZED);
/* link_configure_duid() returns 0 if it requests product UUID. In that case,
* link_configure() is called later asynchronously. */
r = link_configure_duid(link);
if (r <= 0)
return r;
r = link_configure(link);
if (r < 0)
return r;
return 0;
}
static int link_initialized_and_synced(Link *link) {
Network *network;
int r;
@ -2875,8 +2954,12 @@ static int link_initialized_and_synced(Link *link) {
return r;
if (!link->network) {
r = wifi_get_info(link);
if (r < 0)
return r;
r = network_get(link->manager, link->sd_device, link->ifname,
&link->mac, &network);
&link->mac, link->ssid, &link->bssid, &network);
if (r == -ENOENT) {
link_enter_unmanaged(link);
return 0;
@ -3250,6 +3333,15 @@ static int link_carrier_gained(Link *link) {
assert(link);
r = wifi_get_info(link);
if (r < 0)
return r;
if (r > 0) {
r = link_reconfigure(link);
if (r < 0)
return r;
}
if (IN_SET(link->state, LINK_STATE_CONFIGURING, LINK_STATE_CONFIGURED)) {
r = link_acquire_conf(link);
if (r < 0) {

View File

@ -55,6 +55,10 @@ typedef struct Link {
uint32_t mtu;
sd_device *sd_device;
/* wlan */
char *ssid;
struct ether_addr bssid;
unsigned flags;
uint8_t kernel_operstate;
@ -204,6 +208,8 @@ uint32_t link_get_ipv6_accept_ra_route_table(Link *link);
int link_request_set_routes(Link *link);
int link_request_set_nexthop(Link *link);
int link_reconfigure(Link *link);
#define ADDRESS_FMT_VAL(address) \
be32toh((address).s_addr) >> 24, \
(be32toh((address).s_addr) >> 16) & 0xFFu, \

View File

@ -29,6 +29,8 @@ Match.MACAddress, config_parse_hwaddrs,
Match.Path, config_parse_match_strv, 0, offsetof(Network, match_path)
Match.Driver, config_parse_match_strv, 0, offsetof(Network, match_driver)
Match.Type, config_parse_match_strv, 0, offsetof(Network, match_type)
Match.SSID, config_parse_match_strv, 0, offsetof(Network, match_ssid)
Match.BSSID, config_parse_hwaddrs, 0, offsetof(Network, match_bssid)
Match.Name, config_parse_match_ifnames, 0, offsetof(Network, match_name)
Match.Property, config_parse_match_property, 0, offsetof(Network, match_property)
Match.Host, config_parse_net_condition, CONDITION_HOST, offsetof(Network, conditions)

View File

@ -159,7 +159,7 @@ int network_verify(Network *network) {
if (set_isempty(network->match_mac) && strv_isempty(network->match_path) &&
strv_isempty(network->match_driver) && strv_isempty(network->match_type) &&
strv_isempty(network->match_name) && strv_isempty(network->match_property) &&
!network->conditions)
strv_isempty(network->match_ssid) && !network->conditions)
log_warning("%s: No valid settings found in the [Match] section. "
"The file will match all interfaces. "
"If that is intended, please add Name=* in the [Match] section.",
@ -547,6 +547,8 @@ static Network *network_free(Network *network) {
strv_free(network->match_type);
strv_free(network->match_name);
strv_free(network->match_property);
strv_free(network->match_ssid);
set_free_free(network->match_bssid);
condition_free_list(network->conditions);
free(network->description);
@ -655,7 +657,7 @@ int network_get_by_name(Manager *manager, const char *name, Network **ret) {
int network_get(Manager *manager, sd_device *device,
const char *ifname, const struct ether_addr *address,
Network **ret) {
const char *ssid, const struct ether_addr *bssid, Network **ret) {
Network *network;
Iterator i;
@ -665,7 +667,8 @@ int network_get(Manager *manager, sd_device *device,
ORDERED_HASHMAP_FOREACH(network, manager->networks, i)
if (net_match_config(network->match_mac, network->match_path, network->match_driver,
network->match_type, network->match_name, network->match_property,
device, address, ifname)) {
network->match_ssid, network->match_bssid,
device, address, ifname, ssid, bssid)) {
if (network->match_name && device) {
const char *attr;
uint8_t name_assign_type = NET_NAME_UNKNOWN;

View File

@ -63,6 +63,8 @@ struct Network {
char **match_type;
char **match_name;
char **match_property;
char **match_ssid;
Set *match_bssid;
LIST_HEAD(Condition, conditions);
char *description;
@ -286,7 +288,8 @@ int network_load_one(Manager *manager, const char *filename);
int network_verify(Network *network);
int network_get_by_name(Manager *manager, const char *name, Network **ret);
int network_get(Manager *manager, sd_device *device, const char *ifname, const struct ether_addr *mac, Network **ret);
int network_get(Manager *manager, sd_device *device, const char *ifname, const struct ether_addr *mac,
const char *ssid, const struct ether_addr *bssid, Network **ret);
int network_apply(Network *network, Link *link);
void network_apply_anonymize_if_set(Network *network);

142
src/network/networkd-wifi.c Normal file
View File

@ -0,0 +1,142 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#include <net/ethernet.h>
#include <linux/nl80211.h>
#include "sd-bus.h"
#include "bus-util.h"
#include "netlink-internal.h"
#include "netlink-util.h"
#include "networkd-link.h"
#include "networkd-manager.h"
#include "networkd-wifi.h"
#include "string-util.h"
static int wifi_get_ssid(Link *link) {
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL, *reply = NULL;
_cleanup_free_ char *ssid = NULL;
sd_genl_family family;
int r;
r = sd_genl_message_new(link->manager->genl, SD_GENL_NL80211, NL80211_CMD_GET_INTERFACE, &m);
if (r < 0)
return log_link_error_errno(link, r, "Failed to create generic netlink message: %m");
r = sd_netlink_message_append_u32(m, NL80211_ATTR_IFINDEX, link->ifindex);
if (r < 0)
return log_link_error_errno(link, r, "Could not append NL80211_ATTR_IFINDEX attribute: %m");
r = sd_netlink_call(link->manager->genl, m, 0, &reply);
if (r < 0)
return log_link_error_errno(link, r, "Failed to request information about wifi interface: %m");
if (!reply)
return 0;
r = sd_netlink_message_get_errno(reply);
if (r < 0)
return log_link_warning_errno(link, r, "Failed to get information about wifi interface: %m");
r = sd_genl_message_get_family(link->manager->genl, reply, &family);
if (r < 0)
return log_link_warning_errno(link, r, "Failed to determine genl family: %m");
if (family != SD_GENL_NL80211) {
log_link_debug(link, "Received message of unexpected genl family %u, ignoring.", family);
return 0;
}
r = sd_netlink_message_read_string_strdup(reply, NL80211_ATTR_SSID, &ssid);
if (r < 0 && r != -ENODATA)
return log_link_warning_errno(link, r, "Failed to get NL80211_ATTR_SSID attribute: %m");
free_and_replace(link->ssid, ssid);
return r == -ENODATA ? 0 : 1;
}
static int wifi_get_bssid(Link *link) {
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL, *reply = NULL;
struct ether_addr mac = {};
sd_genl_family family;
int r;
assert(link);
assert(link->manager);
assert(link->manager->genl);
r = sd_genl_message_new(link->manager->genl, SD_GENL_NL80211, NL80211_CMD_GET_STATION, &m);
if (r < 0)
return log_link_error_errno(link, r, "Failed to create generic netlink message: %m");
r = sd_netlink_message_set_flags(m, NLM_F_REQUEST | NLM_F_ACK | NLM_F_DUMP);
if (r < 0)
return log_link_error_errno(link, r, "Failed to set dump flag: %m");
r = sd_netlink_message_append_u32(m, NL80211_ATTR_IFINDEX, link->ifindex);
if (r < 0)
return log_link_error_errno(link, r, "Could not append NL80211_ATTR_IFINDEX attribute: %m");
r = sd_netlink_call(link->manager->genl, m, 0, &reply);
if (r < 0)
return log_link_error_errno(link, r, "Failed to request information about wifi station: %m");
if (!reply)
return 0;
r = sd_netlink_message_get_errno(reply);
if (r < 0)
return log_link_error_errno(link, r, "Failed to get information about wifi station: %m");
r = sd_genl_message_get_family(link->manager->genl, reply, &family);
if (r < 0)
return log_link_warning_errno(link, r, "Failed to determine genl family: %m");
if (family != SD_GENL_NL80211) {
log_link_debug(link, "Received message of unexpected genl family %u, ignoring.", family);
return 0;
}
r = sd_netlink_message_read_ether_addr(reply, NL80211_ATTR_MAC, &mac);
if (r < 0 && r != -ENODATA)
return log_link_warning_errno(link, r, "Failed to get NL80211_ATTR_MAC attribute: %m");
r = memcmp(&link->bssid, &mac, sizeof(mac));
if (r == 0)
return 0;
memcpy(&link->bssid, &mac, sizeof(mac));
return 1;
}
int wifi_get_info(Link *link) {
char buf[ETHER_ADDR_TO_STRING_MAX];
const char *type;
int r, s;
assert(link);
if (!link->sd_device)
return 0;
r = sd_device_get_devtype(link->sd_device, &type);
if (r == -ENOENT)
return 0;
else if (r < 0)
return r;
if (!streq(type, "wlan"))
return 0;
r = wifi_get_ssid(link);
if (r < 0)
return r;
s = wifi_get_bssid(link);
if (s < 0)
return s;
if (r > 0 || s > 0) {
if (link->ssid)
log_link_info(link, "Connected WiFi access point: %s (%s)",
link->ssid, ether_addr_to_string(&link->bssid, buf));
return 1;
}
return 0;
}

View File

@ -0,0 +1,8 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
#include "sd-bus.h"
typedef struct Link Link;
int wifi_get_info(Link *link);

View File

@ -125,7 +125,7 @@ static void test_network_get(Manager *manager, sd_device *loopback) {
/* let's assume that the test machine does not have a .network file
that applies to the loopback device... */
assert_se(network_get(manager, loopback, "lo", &mac, &network) == -ENOENT);
assert_se(network_get(manager, loopback, "lo", &mac, NULL, NULL, &network) == -ENOENT);
assert_se(!network);
}

View File

@ -261,6 +261,30 @@ STATIC_DESTRUCTOR_REGISTER(arg_seccomp, seccomp_releasep);
STATIC_DESTRUCTOR_REGISTER(arg_cpu_set, cpu_set_reset);
STATIC_DESTRUCTOR_REGISTER(arg_sysctl, strv_freep);
static int handle_arg_console(const char *arg) {
if (streq(arg, "help")) {
puts("interactive\n"
"read-only\n"
"passive\n"
"pipe");
return 0;
}
if (streq(arg, "interactive"))
arg_console_mode = CONSOLE_INTERACTIVE;
else if (streq(arg, "read-only"))
arg_console_mode = CONSOLE_READ_ONLY;
else if (streq(arg, "passive"))
arg_console_mode = CONSOLE_PASSIVE;
else if (streq(arg, "pipe"))
arg_console_mode = CONSOLE_PIPE;
else
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Unknown console mode: %s", optarg);
arg_settings_mask |= SETTING_CONSOLE_MODE;
return 1;
}
static int help(void) {
_cleanup_free_ char *link = NULL;
int r;
@ -1389,29 +1413,16 @@ static int parse_argv(int argc, char *argv[]) {
break;
case ARG_CONSOLE:
if (streq(optarg, "interactive"))
arg_console_mode = CONSOLE_INTERACTIVE;
else if (streq(optarg, "read-only"))
arg_console_mode = CONSOLE_READ_ONLY;
else if (streq(optarg, "passive"))
arg_console_mode = CONSOLE_PASSIVE;
else if (streq(optarg, "pipe"))
arg_console_mode = CONSOLE_PIPE;
else if (streq(optarg, "help"))
puts("interactive\n"
"read-only\n"
"passive\n"
"pipe");
else
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Unknown console mode: %s", optarg);
arg_settings_mask |= SETTING_CONSOLE_MODE;
r = handle_arg_console(optarg);
if (r <= 0)
return r;
break;
case 'P':
case ARG_PIPE:
arg_console_mode = CONSOLE_PIPE;
arg_settings_mask |= SETTING_CONSOLE_MODE;
r = handle_arg_console("pipe");
if (r <= 0)
return r;
break;
case ARG_NO_PAGER:

View File

@ -92,7 +92,7 @@ static int help(void) {
" -H --host=[USER@]HOST Operate on remote host\n"
" -M --machine=CONTAINER Operate on local container\n"
" --scope Run this as scope rather than service\n"
" --unit=UNIT Run under the specified unit name\n"
" -u --unit=UNIT Run under the specified unit name\n"
" -p --property=NAME=VALUE Set service or scope unit property\n"
" --description=TEXT Description for unit\n"
" --slice=SLICE Run in the specified slice\n"
@ -158,7 +158,6 @@ static int parse_argv(int argc, char *argv[]) {
ARG_USER,
ARG_SYSTEM,
ARG_SCOPE,
ARG_UNIT,
ARG_DESCRIPTION,
ARG_SLICE,
ARG_SEND_SIGHUP,
@ -190,7 +189,7 @@ static int parse_argv(int argc, char *argv[]) {
{ "user", no_argument, NULL, ARG_USER },
{ "system", no_argument, NULL, ARG_SYSTEM },
{ "scope", no_argument, NULL, ARG_SCOPE },
{ "unit", required_argument, NULL, ARG_UNIT },
{ "unit", required_argument, NULL, 'u' },
{ "description", required_argument, NULL, ARG_DESCRIPTION },
{ "slice", required_argument, NULL, ARG_SLICE },
{ "remain-after-exit", no_argument, NULL, 'r' },
@ -234,7 +233,7 @@ static int parse_argv(int argc, char *argv[]) {
assert(argc >= 0);
assert(argv);
while ((c = getopt_long(argc, argv, "+hrH:M:E:p:tPqGdS", options, NULL)) >= 0)
while ((c = getopt_long(argc, argv, "+hrH:M:E:p:tPqGdSu:", options, NULL)) >= 0)
switch (c) {
@ -260,7 +259,7 @@ static int parse_argv(int argc, char *argv[]) {
arg_scope = true;
break;
case ARG_UNIT:
case 'u':
arg_unit = optarg;
break;

View File

@ -1103,7 +1103,8 @@ static int map_basic(sd_bus *bus, const char *member, sd_bus_message *m, unsigne
switch (type) {
case SD_BUS_TYPE_STRING: {
case SD_BUS_TYPE_STRING:
case SD_BUS_TYPE_OBJECT_PATH: {
const char **p = userdata;
const char *s;

View File

@ -35,11 +35,14 @@ typedef struct sd_netlink_message sd_netlink_message;
typedef struct sd_netlink_slot sd_netlink_slot;
typedef enum sd_gen_family {
SD_GENL_ERROR,
SD_GENL_DONE,
SD_GENL_ID_CTRL,
SD_GENL_WIREGUARD,
SD_GENL_FOU,
SD_GENL_L2TP,
SD_GENL_MACSEC,
SD_GENL_NL80211,
} sd_genl_family;
/* callback */
@ -95,6 +98,7 @@ int sd_netlink_message_open_container_union(sd_netlink_message *m, unsigned shor
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_strdup(sd_netlink_message *m, unsigned short type, char **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);
@ -110,7 +114,7 @@ int sd_netlink_message_exit_container(sd_netlink_message *m);
int sd_netlink_message_open_array(sd_netlink_message *m, uint16_t type);
int sd_netlink_message_cancel_array(sd_netlink_message *m);
int sd_netlink_message_rewind(sd_netlink_message *m);
int sd_netlink_message_rewind(sd_netlink_message *m, sd_netlink *genl);
sd_netlink_message *sd_netlink_message_next(sd_netlink_message *m);
@ -201,6 +205,7 @@ int sd_rtnl_message_routing_policy_rule_get_flags(sd_netlink_message *m, unsigne
/* genl */
int sd_genl_socket_open(sd_netlink **nl);
int sd_genl_message_new(sd_netlink *nl, sd_genl_family family, uint8_t cmd, sd_netlink_message **m);
int sd_genl_message_get_family(sd_netlink *nl, sd_netlink_message *m, sd_genl_family *family);
/* slot */
sd_netlink_slot *sd_netlink_slot_ref(sd_netlink_slot *nl);

View File

@ -242,8 +242,8 @@ int link_config_get(link_config_ctx *ctx, sd_device *device, link_config **ret)
LIST_FOREACH(links, link, ctx->links) {
if (net_match_config(link->match_mac, link->match_path, link->match_driver,
link->match_type, link->match_name, link->match_property,
device, NULL, NULL)) {
link->match_type, link->match_name, link->match_property, NULL, NULL,
device, NULL, NULL, NULL, NULL)) {
if (link->match_name && !strv_contains(link->match_name, "*")) {
unsigned name_assign_type = NET_NAME_UNKNOWN;

View File

@ -19,6 +19,8 @@ Type=
Driver=
Architecture=
Path=
SSID=
BSSID=
Name=
Property=
Virtualization=