; A list of (major-mode . ((var1 . value1) (var2 . value2)))
; Mode can be nil, which gives default values.
-; Note that we set a line width of 119 for .c and XML files, but for everything
+; Note that we set a line width of 109 for .c and XML files, but for everything
; else (such as journal catalog files, unit files, README files) we stick to a
; more conservative 79 characters.
; NOTE: If you update this file make sure to update .vimrc and .editorconfig,
; too.
-((c-mode . ((fill-column . 119)
+((c-mode . ((fill-column . 109)
(c-basic-offset . 8)
(eval . (c-set-offset 'substatement-open 0))
(eval . (c-set-offset 'statement-case-open 0))
(eval . (c-set-offset 'arglist-intro '++))
(eval . (c-set-offset 'arglist-close 0))))
(nxml-mode . ((nxml-child-indent . 2)
- (fill-column . 119)))
+ (fill-column . 109)))
(meson-mode . ((meson-indent-basic . 8)))
(sh-mode . ((sh-basic-offset . 8)
(sh-indentation . 8)))
after_prepare:
- pip3 install meson
- export PATH="$HOME/.local/bin/:$PATH"
+ python:
+ python_setup:
+ version: 3
after_script:
- $CI_MANAGERS/fedora.sh CLEANUP
+ - name: Debian Testing
+ language: bash
+ env:
+ - DEBIAN_RELEASE="testing"
+ - CONT_NAME="systemd-debian-$DEBIAN_RELEASE"
+ - DOCKER_EXEC="docker exec -ti $CONT_NAME"
+ before_install:
+ - sudo apt-get -y -o Dpkg::Options::="--force-confnew" install docker-ce
+ - docker --version
+ install:
+ - $CI_MANAGERS/debian.sh SETUP
+ script:
+ - set -e
+ - $CI_MANAGERS/debian.sh RUN
+ - set +e
+ after_script:
+ - $CI_MANAGERS/debian.sh CLEANUP
+
- stage: Coverity
language: bash
env:
" You should consider setting 'set secure' as well, which is highly
" recommended!
-" Note that we set a line width of 119 for .c and XML files, but for everything
+" Note that we set a line width of 109 for .c and XML files, but for everything
" else (such as journal catalog files, unit files, README files) we stick to a
" more conservative 79 characters.
set expandtab
set makeprg=GCC_COLORS=\ make
set tw=79
-au BufRead,BufNewFile *.xml set tw=119 shiftwidth=2 smarttab
-au FileType c set tw=119
+au BufRead,BufNewFile *.xml set tw=109 shiftwidth=2 smarttab
+au FileType c set tw=109
<a href="https://in.waw.pl/systemd-github-state/systemd-systemd-issues.svg"><img align="right" src="https://in.waw.pl/systemd-github-state/systemd-systemd-issues-small.svg" alt="Count of open issues over time"></a>
<a href="https://in.waw.pl/systemd-github-state/systemd-systemd-pull-requests.svg"><img align="right" src="https://in.waw.pl/systemd-github-state/systemd-systemd-pull-requests-small.svg" alt="Count of open pull requests over time"></a>
-[![Build Status](https://semaphoreci.com/api/v1/projects/28a5a3ca-3c56-4078-8b5e-7ed6ef912e14/443470/shields_badge.svg)](https://semaphoreci.com/systemd/systemd)<br/>
+[![Semaphore CI Build Status](https://semaphoreci.com/api/v1/projects/28a5a3ca-3c56-4078-8b5e-7ed6ef912e14/443470/shields_badge.svg)](https://semaphoreci.com/systemd/systemd)<br/>
[![Coverity Scan Status](https://scan.coverity.com/projects/350/badge.svg)](https://scan.coverity.com/projects/350)<br/>
[![CII Best Practices](https://bestpractices.coreinfrastructure.org/projects/1369/badge)](https://bestpractices.coreinfrastructure.org/projects/1369)<br/>
-[![Build Status](https://travis-ci.org/systemd/systemd.svg?branch=master)](https://travis-ci.org/systemd/systemd)<br/>
-[![Language Grade: C/C++](https://img.shields.io/lgtm/grade/cpp/g/systemd/systemd.svg?logo=lgtm&logoWidth=18)](https://lgtm.com/projects/g/systemd/systemd/context:cpp)
+[![Travis CI Build Status](https://travis-ci.org/systemd/systemd.svg?branch=master)](https://travis-ci.org/systemd/systemd)<br/>
+[![Language Grade: C/C++](https://img.shields.io/lgtm/grade/cpp/g/systemd/systemd.svg?logo=lgtm&logoWidth=18)](https://lgtm.com/projects/g/systemd/systemd/context:cpp)<br/>
+[![CentOS CI Build Status](https://ci.centos.org/buildStatus/icon?job=systemd-pr-build)](https://ci.centos.org/job/systemd-pr-build/)
## Details
Features:
+* when importing an fs tree with machined, optionally apply userns-rec-chown
+
+* when importing an fs tree with machined, complain if image is not an OS
+
* when we fork off generators and such, lower LIMIT_NOFILE soft limit to 1K
+* Maybe introduce a helper safe_exec() or so, which is to execve() which
+ safe_fork() is to fork(). And then make revert the RLIMIT_NOFILE soft limit
+ to 1K implicitly, unless explicitly opted-out.
+
* rework seccomp/nnp logic that that even if User= is used in combination with
a seccomp option we don't have to set NNP. For that, change uid first whil
keeping CAP_SYS_ADMIN, then apply seccomp, the drop cap.
- Don't break code lines too eagerly. We do **not** force line breaks at 80ch,
all of today's screens should be much larger than that. But then again, don't
- overdo it, ~119ch should be enough really. The `.editorconfig`, `.vimrc` and
+ overdo it, ~109ch should be enough really. The `.editorconfig`, `.vimrc` and
`.dir-locals.el` files contained in the repository will set this limit up for
you automatically, if you let them (as well as a few other things).
sensor:modalias:acpi:BMA250E*:dmi:bvnAmericanMegatrendsInc.:bvr3BAIR1014:bd10/24/2014:svnTobefilledbyO.E.M.:pnTobefilledbyO.E.M.:pvrTobefilledbyO.E.M.:rvnAMICorporation:rnAptioCRB:rvrTobefilledbyO.E.M.:cvnToBeFilledByO.E.M.:ct3:cvrToBeFilledByO.E.M.:
ACCEL_MOUNT_MATRIX=0, 1, 0; 1, 0, 0; 0, 0, 1
+# Point of View TAB-P1005W-232 (v2.0)
+sensor:modalias:acpi:KIOX000A*:dmi:*:rvnPOV:rnI102A:*
+ ACCEL_MOUNT_MATRIX=1, 0, 0; 0, -1, 0; 0, 0, 1
+
+#########################################
+# Prowise
+#########################################
+sensor:modalias:acpi:SMO8500*:dmi:*:svnProwise:pnPT301:*
+ ACCEL_MOUNT_MATRIX=-1, 0, 0; 0, 1, 0; 0, 0, 1
+
#########################################
# Teclast
#########################################
COMMENTLINE = pythonStyleComment + EOL
EMPTYLINE = LineEnd()
text_eol = lambda name: Regex(r'[^\n]+')(name) + EOL
-# text_eol = lambda name: Word(printables + ' ' + '®üäßçõãİó ײ⁶´‐“\u200E\u200B')(name) + EOL
def klass_grammar():
klass_line = Literal('C ').suppress() + NUM2('klass') + text_eol('text')
#!/usr/bin/env python3
-# -*- Mode: python; coding: utf-8; indent-tabs-mode: nil -*- */
-# SPDX-License-Identifier: MIT
+# SPDX-License-Identifier: MIT
#
# This file is distributed under the MIT license, see below.
#
import os
try:
- from pyparsing import (Word, White, Literal, ParserElement, Regex,
- LineStart, LineEnd,
+ from pyparsing import (Word, White, Literal, ParserElement, Regex, LineEnd,
OneOrMore, Combine, Or, Optional, Suppress, Group,
nums, alphanums, printables,
stringEnd, pythonStyleComment, QuotedString,
(eval . (c-set-offset 'arglist-intro '++))
(eval . (c-set-offset 'arglist-close 0))))
(nxml-mode . ((nxml-child-indent . 2)
- (fill-column . 119)))
+ (fill-column . 109)))
(meson-mode . ((meson-indent-basic . 8)))
(nil . ((indent-tabs-mode . nil)
(tab-width . 8)
<listitem><para>Structured system log messages via the native
Journal API, see
- <citerefentry><refentrytitle>sd_journal_print</refentrytitle><manvolnum>4</manvolnum></citerefentry></para></listitem>
+ <citerefentry><refentrytitle>sd_journal_print</refentrytitle><manvolnum>3</manvolnum></citerefentry></para></listitem>
<listitem><para>Standard output and standard error of service units. For further details see
below.</para></listitem>
<citerefentry><refentrytitle>sd-journal</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
<citerefentry><refentrytitle>systemd-coredump</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
<citerefentry project='die-net'><refentrytitle>setfacl</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
- <citerefentry><refentrytitle>sd_journal_print</refentrytitle><manvolnum>4</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_journal_print</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
<command>pydoc systemd.journal</command>
</para>
</refsect1>
for details.</para></listitem>
</varlistentry>
- <varlistentry>
+ <varlistentry id='device-timeout'>
<term><option>x-systemd.device-timeout=</option></term>
<listitem><para>Configure how long systemd should wait for a
<varlistentry>
<term><option>x-systemd.makefs</option></term>
- <listitem><para>The file system or swap structure will be initialized
+ <listitem><para>The file system will be initialized
on the device. If the device is not "empty", i.e. it contains any signature,
the operation will be skipped. It is hence expected that this option
remains set even after the device has been initalized.</para>
applicable to SIT tunnels.</para>
</listitem>
</varlistentry>
+ <varlistentry>
+ <term><varname>ISATAP=</varname></term>
+ <listitem>
+ <para>Takes a boolean. If set, configures the tunnel as Intra-Site Automatic Tunnel Addressing Protocol (ISATAP) tunnel.
+ Only applicable to SIT tunnels. When unset, the kernel's default will be used.</para>
+ </listitem>
+ </varlistentry>
<varlistentry>
<term><varname>SerializeTunneledPackets=</varname></term>
<listitem>
</variablelist>
</refsect1>
+ <refsect1>
+ <title>[Neighbor] Section Options</title>
+ <para>A <literal>[Neighbor]</literal> section accepts the
+ following keys. The neighbor section adds a permanent, static
+ entry to the neighbor table (IPv6) or ARP table (IPv4) for
+ the given hardware address on the links matched for the network.
+ Specify several <literal>[Neighbor]</literal> sections to configure
+ several static neighbors.</para>
+
+ <variablelist class='network-directives'>
+ <varlistentry>
+ <term><varname>Address=</varname></term>
+ <listitem>
+ <para>The IP address of the neighbor.</para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><varname>MACAddress=</varname></term>
+ <listitem>
+ <para>The hardware address of the neighbor.</para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+ </refsect1>
+
<refsect1>
<title>[IPv6AddressLabel] Section Options</title>
Defaults to unset.</para>
</listitem>
</varlistentry>
+ <varlistentry>
+ <term><varname>InvertRule=</varname></term>
+ <listitem>
+ <para>A boolean. Specifies wheather the rule to be inverted. Defaults to false.</para>
+ </listitem>
+ </varlistentry>
</variablelist>
</refsect1>
</para>
</listitem>
</varlistentry>
+ <varlistentry>
+ <term><varname>MulticastToUnicast=</varname></term>
+ <listitem>
+ <para>Takes a boolean. Multicast to unicast works on top of the multicast snooping feature of
+ the bridge. Which means unicast copies are only delivered to hosts which are interested in it.
+ When unset, the kernel's default will be used.
+ </para>
+ </listitem>
+ </varlistentry>
<varlistentry>
<term><varname>HairPin=</varname></term>
<listitem>
SPDX-License-Identifier: LGPL-2.1+
-->
-<refentry id="systemd.swap">
+<refentry id="systemd.swap"
+ xmlns:xi="http://www.w3.org/2001/XInclude">
+
<refentryinfo>
<title>systemd.swap</title>
<productname>systemd</productname>
successfully.</para>
</listitem>
</varlistentry>
+
+ <xi:include href="systemd.mount.xml" xpointer="device-timeout" />
+
+ <varlistentry>
+ <term><option>x-systemd.makefs</option></term>
+
+ <listitem><para>The swap structure will be initialized on the device. If the device is not
+ "empty", i.e. it contains any signature, the operation will be skipped. It is hence expected
+ that this option remains set even after the device has been initalized.</para>
+
+ <para>Note that this option can only be used in <filename>/etc/fstab</filename>, and will be
+ ignored when part of the <varname>Options=</varname> setting in a unit file.</para>
+
+ <para>See
+ <citerefentry><refentrytitle>systemd-mkswap@.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>
+ and the discussion of
+ <citerefentry project='man-pages'><refentrytitle>wipefs</refentrytitle><manvolnum>8</manvolnum></citerefentry>
+ in <citerefentry><refentrytitle>systemd.mount</refentrytitle><manvolnum>5</manvolnum></citerefentry>.
+ </para></listitem>
+ </varlistentry>
</variablelist>
</refsect1>
<varlistentry>
<term><varname>JobTimeoutSec=</varname></term>
<term><varname>JobRunningTimeoutSec=</varname></term>
- <term><varname>JobTimeoutAction=</varname></term>
- <term><varname>JobTimeoutRebootArgument=</varname></term>
<listitem><para>When a job for this unit is queued, a time-out <varname>JobTimeoutSec=</varname> may be
configured. Similarly, <varname>JobRunningTimeoutSec=</varname> starts counting when the queued job is actually
no effect on the unit itself, only on the job that might be pending for it. Or in other words: unit-specific
timeouts are useful to abort unit state changes, and revert them. The job timeout set with this option however
is useful to abort only the job waiting for the unit state to change.</para>
+ </listitem>
+ </varlistentry>
- <para><varname>JobTimeoutAction=</varname> optionally configures an additional action to take when the time-out
- is hit. It takes the same values as <varname>StartLimitAction=</varname>. Defaults to <option>none</option>.
+ <varlistentry>
+ <term><varname>JobTimeoutAction=</varname></term>
+ <term><varname>JobTimeoutRebootArgument=</varname></term>
+
+ <listitem><para><varname>JobTimeoutAction=</varname> optionally configures an additional action to take when
+ the time-out is hit, see description of <varname>JobTimeoutSec=</varname> and
+ <varname>JobRunningTimeoutSec=</varname> above. It takes the same values as
+ <varname>StartLimitAction=</varname>. Defaults to <option>none</option>.
<varname>JobTimeoutRebootArgument=</varname> configures an optional reboot string to pass to the
- <citerefentry><refentrytitle>reboot</refentrytitle><manvolnum>2</manvolnum></citerefentry>
- system call.</para></listitem>
+ <citerefentry><refentrytitle>reboot</refentrytitle><manvolnum>2</manvolnum></citerefentry> system call.
+ </para></listitem>
</varlistentry>
<varlistentry>
machinectl list --no-legend --no-pager | { while read a b; do echo " $a"; done; };
}
+__get_services() {
+ systemctl list-units --no-legend --no-pager -t service --all $1 | \
+ { while read -r a b c; do [[ $b == "loaded" ]]; echo " $a"; done }
+}
+
_systemd_analyze() {
- local i verb comps
+ local i verb comps mode
local cur=${COMP_WORDS[COMP_CWORD]} prev=${COMP_WORDS[COMP_CWORD-1]}
local -A OPTS=(
[SECCOMP_FILTER]='syscall-filter'
[SERVICE_WATCHDOGS]='service-watchdogs'
[CAT_CONFIG]='cat-config'
+ [SECURITY]='security'
)
local CONFIGS='systemd/bootchart.conf systemd/coredump.conf systemd/journald.conf
comps="$CONFIGS $( compgen -A file -- "$cur" )"
compopt -o filenames
fi
+
+ elif __contains_word "$verb" ${VERBS[SECURITY]}; then
+ if [[ $cur = -* ]]; then
+ comps='--help --version --no-pager --system --user -H --host -M --machine'
+ else
+ if __contains_word "--user" ${COMP_WORDS[*]}; then
+ mode=--user
+ else
+ mode=--system
+ fi
+ comps=$( __get_services $mode )
+ fi
fi
COMPREPLY=( $(compgen -W '$comps' -- "$cur") )
if (!joined)
return log_oom();
- r = safe_fork("(activate)", FORK_RESET_SIGNALS|FORK_DEATHSIG|FORK_LOG, &child_pid);
+ r = safe_fork("(activate)", FORK_RESET_SIGNALS|FORK_DEATHSIG|FORK_RLIMIT_NOFILE_SAFE|FORK_LOG, &child_pid);
if (r < 0)
return r;
if (r == 0) {
#include "arphrd-list.h"
#include "macro.h"
+#include "missing_network.h"
static const struct arphrd_name* lookup_arphrd(register const char *str, register GPERF_LEN_TYPE len);
if (f) {
PROTECT_ERRNO;
- assert_se(fclose_nointr(f) != EBADF);
+ assert_se(fclose_nointr(f) != -EBADF);
}
return NULL;
#!/bin/sh
set -eu
-$1 -E -dM -include sys/socket.h - </dev/null | \
+$1 -E -dM -include sys/socket.h -include "$2" -include "$3" - </dev/null | \
grep -Ev 'AF_UNSPEC|AF_MAX' | \
awk '/^#define[ \t]+AF_[^ \t]+[ \t]+[AP]F_[^ \t]/ { print $2; }'
#!/bin/sh
set -eu
-$1 -dM -include net/if_arp.h - </dev/null | \
+$1 -dM -include net/if_arp.h -include "$2" -include "$3" - </dev/null | \
awk '/^#define[ \t]+ARPHRD_[^ \t]+[ \t]+[^ \t]/ { print $2; }' | \
sed -e 's/ARPHRD_//'
#pragma once
#include <assert.h>
+#include <errno.h>
#include <inttypes.h>
#include <stdbool.h>
#include <sys/param.h>
memfd-util.h
mempool.c
mempool.h
+ missing.h
+ missing_audit.h
missing_btrfs.h
missing_btrfs_tree.h
missing_capability.h
+ missing_drm.h
missing_ethtool.h
+ missing_fcntl.h
missing_fib_rules.h
missing_fou.h
+ missing_fs.h
missing_if_bridge.h
missing_if_link.h
missing_if_tunnel.h
missing_input.h
missing_keyctl.h
missing_magic.h
+ missing_mman.h
missing_network.h
missing_prctl.h
+ missing_random.h
+ missing_resource.h
+ missing_sched.h
missing_securebits.h
+ missing_socket.h
missing_stat.h
+ missing_stdlib.h
missing_syscall.h
+ missing_timerfd.h
missing_type.h
missing_vxcan.h
mkdir-label.c
refcnt.h
replace-var.c
replace-var.h
+ rlimit-util.c
+ rlimit-util.h
rm-rf.c
rm-rf.h
selinux-util.c
xattr-util.h
'''.split())
-missing_h = files('missing.h')
+missing_audit_h = files('missing_audit.h')
+missing_capability_h = files('missing_capability.h')
+missing_network_h = files('missing_network.h')
+missing_socket_h = files('missing_socket.h')
generate_af_list = find_program('generate-af-list.sh')
af_list_txt = custom_target(
'af-list.txt',
output : 'af-list.txt',
- command : [generate_af_list, cpp],
+ command : [generate_af_list, cpp, config_h, missing_socket_h],
capture : true)
generate_arphrd_list = find_program('generate-arphrd-list.sh')
arphrd_list_txt = custom_target(
'arphrd-list.txt',
output : 'arphrd-list.txt',
- command : [generate_arphrd_list, cpp],
+ command : [generate_arphrd_list, cpp, config_h, missing_network_h],
capture : true)
generate_cap_list = find_program('generate-cap-list.sh')
cap_list_txt = custom_target(
'cap-list.txt',
output : 'cap-list.txt',
- command : [generate_cap_list, cpp, config_h, missing_h],
+ command : [generate_cap_list, cpp, config_h, missing_capability_h],
capture : true)
generate_errno_list = find_program('generate-errno-list.sh')
generated_gperf_headers += [target1, target2]
endforeach
-basic_sources += [missing_h] + generated_gperf_headers
+basic_sources += generated_gperf_headers
basic_gcrypt_sources = files(
'gcrypt-util.c',
'gcrypt-util.h')
/* Missing glibc definitions to access certain kernel APIs */
-#include <errno.h>
-#include <fcntl.h>
-#include <inttypes.h>
-#include <linux/audit.h>
-#include <linux/falloc.h>
-#include <linux/oom.h>
-#include <net/ethernet.h>
-#include <stdlib.h>
-#include <sys/resource.h>
-#include <sys/socket.h>
-#include <sys/syscall.h>
-#include <unistd.h>
-
-#if HAVE_AUDIT
-#include <libaudit.h>
-#endif
-
-#ifdef ARCH_MIPS
-#include <asm/sgidefs.h>
-#endif
-
-#if HAVE_LINUX_VM_SOCKETS_H
-#include <linux/vm_sockets.h>
-#else
-#define VMADDR_CID_ANY -1U
-struct sockaddr_vm {
- unsigned short svm_family;
- unsigned short svm_reserved1;
- unsigned int svm_port;
- unsigned int svm_cid;
- unsigned char svm_zero[sizeof(struct sockaddr) -
- sizeof(unsigned short) -
- sizeof(unsigned short) -
- sizeof(unsigned int) -
- sizeof(unsigned int)];
-};
-#endif /* !HAVE_LINUX_VM_SOCKETS_H */
-
-#ifndef RLIMIT_RTTIME
-#define RLIMIT_RTTIME 15
-#endif
-
-/* If RLIMIT_RTTIME is not defined, then we cannot use RLIMIT_NLIMITS as is */
-#define _RLIMIT_MAX (RLIMIT_RTTIME+1 > RLIMIT_NLIMITS ? RLIMIT_RTTIME+1 : RLIMIT_NLIMITS)
-
-#ifndef F_LINUX_SPECIFIC_BASE
-#define F_LINUX_SPECIFIC_BASE 1024
-#endif
-
-#ifndef F_SETPIPE_SZ
-#define F_SETPIPE_SZ (F_LINUX_SPECIFIC_BASE + 7)
-#endif
-
-#ifndef F_GETPIPE_SZ
-#define F_GETPIPE_SZ (F_LINUX_SPECIFIC_BASE + 8)
-#endif
-
-#ifndef F_ADD_SEALS
-#define F_ADD_SEALS (F_LINUX_SPECIFIC_BASE + 9)
-#define F_GET_SEALS (F_LINUX_SPECIFIC_BASE + 10)
-
-#define F_SEAL_SEAL 0x0001 /* prevent further seals from being set */
-#define F_SEAL_SHRINK 0x0002 /* prevent file from shrinking */
-#define F_SEAL_GROW 0x0004 /* prevent file from growing */
-#define F_SEAL_WRITE 0x0008 /* prevent writes */
-#endif
-
-#ifndef F_OFD_GETLK
-#define F_OFD_GETLK 36
-#define F_OFD_SETLK 37
-#define F_OFD_SETLKW 38
-#endif
-
-#ifndef MFD_ALLOW_SEALING
-#define MFD_ALLOW_SEALING 0x0002U
-#endif
-
-#ifndef MFD_CLOEXEC
-#define MFD_CLOEXEC 0x0001U
-#endif
-
-#ifndef IP_FREEBIND
-#define IP_FREEBIND 15
-#endif
-
-#ifndef OOM_SCORE_ADJ_MIN
-#define OOM_SCORE_ADJ_MIN (-1000)
-#endif
-
-#ifndef OOM_SCORE_ADJ_MAX
-#define OOM_SCORE_ADJ_MAX 1000
-#endif
-
-#ifndef AUDIT_SERVICE_START
-#define AUDIT_SERVICE_START 1130 /* Service (daemon) start */
-#endif
-
-#ifndef AUDIT_SERVICE_STOP
-#define AUDIT_SERVICE_STOP 1131 /* Service (daemon) stop */
-#endif
-
-#ifndef TIOCVHANGUP
-#define TIOCVHANGUP 0x5437
-#endif
-
-#ifndef IP_TRANSPARENT
-#define IP_TRANSPARENT 19
-#endif
-
-#ifndef SOL_NETLINK
-#define SOL_NETLINK 270
-#endif
-
-#ifndef NETLINK_LIST_MEMBERSHIPS
-#define NETLINK_LIST_MEMBERSHIPS 9
-#endif
-
-#ifndef SOL_SCTP
-#define SOL_SCTP 132
-#endif
-
-#ifndef GRND_NONBLOCK
-#define GRND_NONBLOCK 0x0001
-#endif
-
-#ifndef GRND_RANDOM
-#define GRND_RANDOM 0x0002
-#endif
-
-#ifndef FS_NOCOW_FL
-#define FS_NOCOW_FL 0x00800000
-#endif
-
-#ifndef CLONE_NEWCGROUP
-#define CLONE_NEWCGROUP 0x02000000
-#endif
-
-#ifndef MS_MOVE
-#define MS_MOVE 8192
-#endif
-
-#ifndef MS_REC
-#define MS_REC 16384
-#endif
-
-#ifndef MS_PRIVATE
-#define MS_PRIVATE (1<<18)
-#endif
-
-#ifndef MS_REC
-#define MS_REC (1<<19)
-#endif
-
-#ifndef MS_SHARED
-#define MS_SHARED (1<<20)
-#endif
-
-#ifndef MS_RELATIME
-#define MS_RELATIME (1<<21)
-#endif
-
-#ifndef MS_KERNMOUNT
-#define MS_KERNMOUNT (1<<22)
-#endif
-
-#ifndef MS_I_VERSION
-#define MS_I_VERSION (1<<23)
-#endif
-
-#ifndef MS_STRICTATIME
-#define MS_STRICTATIME (1<<24)
-#endif
-
-#ifndef MS_LAZYTIME
-#define MS_LAZYTIME (1<<25)
-#endif
-
-#ifndef SCM_SECURITY
-#define SCM_SECURITY 0x03
-#endif
-
-#ifndef DM_DEFERRED_REMOVE
-#define DM_DEFERRED_REMOVE (1 << 17)
-#endif
-
-#ifndef MAX_HANDLE_SZ
-#define MAX_HANDLE_SZ 128
-#endif
-
-#if ! HAVE_SECURE_GETENV
-# if HAVE___SECURE_GETENV
-# define secure_getenv __secure_getenv
-# else
-# error "neither secure_getenv nor __secure_getenv are available"
-# endif
-#endif
-
-#ifndef CIFS_MAGIC_NUMBER
-# define CIFS_MAGIC_NUMBER 0xFF534D42
-#endif
-
-#ifndef TFD_TIMER_CANCEL_ON_SET
-# define TFD_TIMER_CANCEL_ON_SET (1 << 1)
-#endif
-
-#ifndef SO_REUSEPORT
-# define SO_REUSEPORT 15
-#endif
-
-#ifndef SO_PEERGROUPS
-# define SO_PEERGROUPS 59
-#endif
-
-#ifndef DRM_IOCTL_SET_MASTER
-# define DRM_IOCTL_SET_MASTER _IO('d', 0x1e)
-#endif
-
-#ifndef DRM_IOCTL_DROP_MASTER
-# define DRM_IOCTL_DROP_MASTER _IO('d', 0x1f)
-#endif
-
-/* The precise definition of __O_TMPFILE is arch specific; use the
- * values defined by the kernel (note: some are hexa, some are octal,
- * duplicated as-is from the kernel definitions):
- * - alpha, parisc, sparc: each has a specific value;
- * - others: they use the "generic" value.
- */
-
-#ifndef __O_TMPFILE
-#if defined(__alpha__)
-#define __O_TMPFILE 0100000000
-#elif defined(__parisc__) || defined(__hppa__)
-#define __O_TMPFILE 0400000000
-#elif defined(__sparc__) || defined(__sparc64__)
-#define __O_TMPFILE 0x2000000
-#else
-#define __O_TMPFILE 020000000
-#endif
-#endif
-
-/* a horrid kludge trying to make sure that this will fail on old kernels */
-#ifndef O_TMPFILE
-#define O_TMPFILE (__O_TMPFILE | O_DIRECTORY)
-#endif
-
-#ifndef BPF_XOR
-#define BPF_XOR 0xa0
-#endif
-
-/* Note that LOOPBACK_IFINDEX is currently not exported by the
- * kernel/glibc, but hardcoded internally by the kernel. However, as
- * it is exported to userspace indirectly via rtnetlink and the
- * ioctls, and made use of widely we define it here too, in a way that
- * is compatible with the kernel's internal definition. */
-#ifndef LOOPBACK_IFINDEX
-#define LOOPBACK_IFINDEX 1
-#endif
-
-#ifndef MAX_AUDIT_MESSAGE_LENGTH
-#define MAX_AUDIT_MESSAGE_LENGTH 8970
-#endif
-
-#ifndef AUDIT_NLGRP_MAX
-#define AUDIT_NLGRP_READLOG 1
-#endif
-
-#ifndef RENAME_NOREPLACE
-#define RENAME_NOREPLACE (1 << 0)
-#endif
-
-#ifndef KCMP_FILE
-#define KCMP_FILE 0
-#endif
-
-#ifndef ETHERTYPE_LLDP
-#define ETHERTYPE_LLDP 0x88cc
-#endif
-
-#ifndef SOL_ALG
-#define SOL_ALG 279
-#endif
-
-#ifndef AF_VSOCK
-#define AF_VSOCK 40
-#endif
-
-#ifndef EXT4_IOC_RESIZE_FS
-# define EXT4_IOC_RESIZE_FS _IOW('f', 16, __u64)
-#endif
-
-#ifndef NS_GET_NSTYPE
-#define NS_GET_NSTYPE _IO(0xb7, 0x3)
-#endif
-
-#ifndef FALLOC_FL_KEEP_SIZE
-#define FALLOC_FL_KEEP_SIZE 0x01
-#endif
-
-#ifndef FALLOC_FL_PUNCH_HOLE
-#define FALLOC_FL_PUNCH_HOLE 0x02
-#endif
-
-#ifndef PF_KTHREAD
-#define PF_KTHREAD 0x00200000
-#endif
-
-/* The maximum thread/process name length including trailing NUL byte. This mimics the kernel definition of the same
- * name, which we need in userspace at various places but is not defined in userspace currently, neither under this
- * name nor any other. */
-#ifndef TASK_COMM_LEN
-#define TASK_COMM_LEN 16
-#endif
-
+#include "missing_audit.h"
#include "missing_btrfs_tree.h"
#include "missing_capability.h"
+#include "missing_drm.h"
+#include "missing_fcntl.h"
+#include "missing_fs.h"
#include "missing_input.h"
#include "missing_magic.h"
+#include "missing_mman.h"
#include "missing_network.h"
#include "missing_prctl.h"
+#include "missing_random.h"
+#include "missing_resource.h"
+#include "missing_sched.h"
+#include "missing_socket.h"
+#include "missing_stdlib.h"
+#include "missing_timerfd.h"
#include "missing_type.h"
#include "missing_syscall.h"
--- /dev/null
+/* SPDX-License-Identifier: LGPL-2.1+ */
+#pragma once
+
+#include <linux/audit.h>
+
+#if HAVE_AUDIT
+#include <libaudit.h>
+#endif
+
+#ifndef AUDIT_SERVICE_START
+#define AUDIT_SERVICE_START 1130 /* Service (daemon) start */
+#endif
+
+#ifndef AUDIT_SERVICE_STOP
+#define AUDIT_SERVICE_STOP 1131 /* Service (daemon) stop */
+#endif
+
+#ifndef MAX_AUDIT_MESSAGE_LENGTH
+#define MAX_AUDIT_MESSAGE_LENGTH 8970
+#endif
+
+#ifndef AUDIT_NLGRP_MAX
+#define AUDIT_NLGRP_READLOG 1
+#endif
--- /dev/null
+/* SPDX-License-Identifier: LGPL-2.1+ */
+#pragma once
+
+#ifndef DRM_IOCTL_SET_MASTER
+#define DRM_IOCTL_SET_MASTER _IO('d', 0x1e)
+#endif
+
+#ifndef DRM_IOCTL_DROP_MASTER
+#define DRM_IOCTL_DROP_MASTER _IO('d', 0x1f)
+#endif
--- /dev/null
+/* SPDX-License-Identifier: LGPL-2.1+ */
+#pragma once
+
+#include <fcntl.h>
+
+#ifndef F_LINUX_SPECIFIC_BASE
+#define F_LINUX_SPECIFIC_BASE 1024
+#endif
+
+#ifndef F_SETPIPE_SZ
+#define F_SETPIPE_SZ (F_LINUX_SPECIFIC_BASE + 7)
+#endif
+
+#ifndef F_GETPIPE_SZ
+#define F_GETPIPE_SZ (F_LINUX_SPECIFIC_BASE + 8)
+#endif
+
+#ifndef F_ADD_SEALS
+#define F_ADD_SEALS (F_LINUX_SPECIFIC_BASE + 9)
+#define F_GET_SEALS (F_LINUX_SPECIFIC_BASE + 10)
+
+#define F_SEAL_SEAL 0x0001 /* prevent further seals from being set */
+#define F_SEAL_SHRINK 0x0002 /* prevent file from shrinking */
+#define F_SEAL_GROW 0x0004 /* prevent file from growing */
+#define F_SEAL_WRITE 0x0008 /* prevent writes */
+#endif
+
+#ifndef F_OFD_GETLK
+#define F_OFD_GETLK 36
+#define F_OFD_SETLK 37
+#define F_OFD_SETLKW 38
+#endif
+
+#ifndef MAX_HANDLE_SZ
+#define MAX_HANDLE_SZ 128
+#endif
+
+/* The precise definition of __O_TMPFILE is arch specific; use the
+ * values defined by the kernel (note: some are hexa, some are octal,
+ * duplicated as-is from the kernel definitions):
+ * - alpha, parisc, sparc: each has a specific value;
+ * - others: they use the "generic" value.
+ */
+
+#ifndef __O_TMPFILE
+#if defined(__alpha__)
+#define __O_TMPFILE 0100000000
+#elif defined(__parisc__) || defined(__hppa__)
+#define __O_TMPFILE 0400000000
+#elif defined(__sparc__) || defined(__sparc64__)
+#define __O_TMPFILE 0x2000000
+#else
+#define __O_TMPFILE 020000000
+#endif
+#endif
+
+/* a horrid kludge trying to make sure that this will fail on old kernels */
+#ifndef O_TMPFILE
+#define O_TMPFILE (__O_TMPFILE | O_DIRECTORY)
+#endif
--- /dev/null
+/* SPDX-License-Identifier: LGPL-2.1+ */
+#pragma once
+
+/* linux/fs.h */
+#ifndef RENAME_NOREPLACE /* 0a7c3937a1f23f8cb5fc77ae01661e9968a51d0c (3.15) */
+#define RENAME_NOREPLACE (1 << 0)
+#endif
+
+/* linux/fs.h or sys/mount.h */
+#ifndef MS_MOVE
+#define MS_MOVE 8192
+#endif
+
+#ifndef MS_REC
+#define MS_REC 16384
+#endif
+
+#ifndef MS_PRIVATE
+#define MS_PRIVATE (1<<18)
+#endif
+
+#ifndef MS_SLAVE
+#define MS_SLAVE (1<<19)
+#endif
+
+#ifndef MS_SHARED
+#define MS_SHARED (1<<20)
+#endif
+
+#ifndef MS_RELATIME
+#define MS_RELATIME (1<<21)
+#endif
+
+#ifndef MS_KERNMOUNT
+#define MS_KERNMOUNT (1<<22)
+#endif
+
+#ifndef MS_I_VERSION
+#define MS_I_VERSION (1<<23)
+#endif
+
+#ifndef MS_STRICTATIME
+#define MS_STRICTATIME (1<<24)
+#endif
+
+#ifndef MS_LAZYTIME
+#define MS_LAZYTIME (1<<25)
+#endif
+
+/* Not exposed yet. Defined at fs/ext4/ext4.h */
+#ifndef EXT4_IOC_RESIZE_FS
+#define EXT4_IOC_RESIZE_FS _IOW('f', 16, __u64)
+#endif
+
+/* Not exposed yet. Defined at fs/cifs/cifsglob.h */
+#ifndef CIFS_MAGIC_NUMBER
+#define CIFS_MAGIC_NUMBER 0xFF534D42
+#endif
+
+/* linux/nsfs.h */
+#ifndef NS_GET_NSTYPE /* d95fa3c76a66b6d76b1e109ea505c55e66360f3c (4.11) */
+#define NS_GET_NSTYPE _IO(0xb7, 0x3)
+#endif
#pragma once
#include <linux/input.h>
+#include <linux/types.h>
/* linux@c7dc65737c9a607d3e6f8478659876074ad129b8 (3.12) */
#ifndef EVIOCREVOKE
/* linux@06a16293f71927f756dcf37558a79c0b05a91641 (4.4) */
#ifndef EVIOCSMASK
struct input_mask {
- uint32_t type;
- uint32_t codes_size;
- uint64_t codes_ptr;
+ __u32 type;
+ __u32 codes_size;
+ __u64 codes_ptr;
};
#define EVIOCGMASK _IOR('E', 0x92, struct input_mask)
--- /dev/null
+/* SPDX-License-Identifier: LGPL-2.1+ */
+#pragma once
+
+#include <sys/mman.h>
+
+#ifndef MFD_ALLOW_SEALING
+#define MFD_ALLOW_SEALING 0x0002U
+#endif
+
+#ifndef MFD_CLOEXEC
+#define MFD_CLOEXEC 0x0001U
+#endif
#include <linux/loop.h>
#include <linux/rtnetlink.h>
+#include <net/ethernet.h>
#include "missing_ethtool.h"
#include "missing_fib_rules.h"
#define IFA_F_MCAUTOJOIN 0x400
#endif
+/* if_arp.h */
+#ifndef ARPHRD_IP6GRE
+#define ARPHRD_IP6GRE 823
+#endif
+
/* if_bonding.h */
#ifndef BOND_XMIT_POLICY_ENCAP23
#define BOND_XMIT_POLICY_ENCAP23 3
#define NET_NAME_RENAMED 4
#endif
+/* netlink.h */
+#ifndef NETLINK_LIST_MEMBERSHIPS /* b42be38b2778eda2237fc759e55e3b698b05b315 (4.2) */
+#define NETLINK_LIST_MEMBERSHIPS 9
+#endif
+
/* rtnetlink.h */
#ifndef RTA_PREF
#define RTA_PREF 20
#ifndef RTA_EXPIRES
#define RTA_EXPIRES 23
#endif
+
+/* Note that LOOPBACK_IFINDEX is currently not exported by the
+ * kernel/glibc, but hardcoded internally by the kernel. However, as
+ * it is exported to userspace indirectly via rtnetlink and the
+ * ioctls, and made use of widely we define it here too, in a way that
+ * is compatible with the kernel's internal definition. */
+#ifndef LOOPBACK_IFINDEX
+#define LOOPBACK_IFINDEX 1
+#endif
+
+/* Not exposed yet. Similar values are defined in net/ethernet.h */
+#ifndef ETHERTYPE_LLDP
+#define ETHERTYPE_LLDP 0x88cc
+#endif
--- /dev/null
+/* SPDX-License-Identifier: LGPL-2.1+ */
+#pragma once
+
+#if USE_SYS_RANDOM_H
+# include <sys/random.h>
+#else
+# include <linux/random.h>
+#endif
+
+#ifndef GRND_NONBLOCK
+#define GRND_NONBLOCK 0x0001
+#endif
+
+#ifndef GRND_RANDOM
+#define GRND_RANDOM 0x0002
+#endif
--- /dev/null
+/* SPDX-License-Identifier: LGPL-2.1+ */
+#pragma once
+
+#include <sys/resource.h>
+
+#ifndef RLIMIT_RTTIME
+#define RLIMIT_RTTIME 15
+#endif
+
+/* If RLIMIT_RTTIME is not defined, then we cannot use RLIMIT_NLIMITS as is */
+#define _RLIMIT_MAX (RLIMIT_RTTIME+1 > RLIMIT_NLIMITS ? RLIMIT_RTTIME+1 : RLIMIT_NLIMITS)
--- /dev/null
+/* SPDX-License-Identifier: LGPL-2.1+ */
+#pragma once
+
+#include <sched.h>
+
+#ifndef CLONE_NEWCGROUP
+#define CLONE_NEWCGROUP 0x02000000
+#endif
+
+/* Not exposed yet. Defined at include/linux/sched.h */
+#ifndef PF_KTHREAD
+#define PF_KTHREAD 0x00200000
+#endif
+
+/* The maximum thread/process name length including trailing NUL byte. This mimics the kernel definition of the same
+ * name, which we need in userspace at various places but is not defined in userspace currently, neither under this
+ * name nor any other. */
+/* Not exposed yet. Defined at include/linux/sched.h */
+#ifndef TASK_COMM_LEN
+#define TASK_COMM_LEN 16
+#endif
--- /dev/null
+/* SPDX-License-Identifier: LGPL-2.1+ */
+#pragma once
+
+#include <sys/socket.h>
+
+#if HAVE_LINUX_VM_SOCKETS_H
+#include <linux/vm_sockets.h>
+#else
+#define VMADDR_CID_ANY -1U
+struct sockaddr_vm {
+ unsigned short svm_family;
+ unsigned short svm_reserved1;
+ unsigned int svm_port;
+ unsigned int svm_cid;
+ unsigned char svm_zero[sizeof(struct sockaddr) -
+ sizeof(unsigned short) -
+ sizeof(unsigned short) -
+ sizeof(unsigned int) -
+ sizeof(unsigned int)];
+};
+#endif /* !HAVE_LINUX_VM_SOCKETS_H */
+
+#ifndef AF_VSOCK
+#define AF_VSOCK 40
+#endif
+
+#ifndef SO_REUSEPORT
+#define SO_REUSEPORT 15
+#endif
+
+#ifndef SO_PEERGROUPS
+#define SO_PEERGROUPS 59
+#endif
+
+#ifndef SOL_NETLINK
+#define SOL_NETLINK 270
+#endif
+
+#ifndef SOL_ALG
+#define SOL_ALG 279
+#endif
+
+/* Not exposed yet. Defined in include/linux/socket.h. */
+#ifndef SOL_SCTP
+#define SOL_SCTP 132
+#endif
+
+/* Not exposed yet. Defined in include/linux/socket.h */
+#ifndef SCM_SECURITY
+#define SCM_SECURITY 0x03
+#endif
+
+/* netinet/in.h */
+#ifndef IP_FREEBIND
+#define IP_FREEBIND 15
+#endif
+
+#ifndef IP_TRANSPARENT
+#define IP_TRANSPARENT 19
+#endif
/* a528d35e8bfcc521d7cb70aaf03e1bd296c8493f (4.11) */
#if !HAVE_STRUCT_STATX
struct statx_timestamp {
- int64_t tv_sec;
- uint32_t tv_nsec;
- uint32_t __reserved;
+ __s64 tv_sec;
+ __u32 tv_nsec;
+ __s32 __reserved;
};
struct statx {
- uint32_t stx_mask;
- uint32_t stx_blksize;
- uint64_t stx_attributes;
- uint32_t stx_nlink;
- uint32_t stx_uid;
- uint32_t stx_gid;
- uint16_t stx_mode;
- uint16_t __spare0[1];
- uint64_t stx_ino;
- uint64_t stx_size;
- uint64_t stx_blocks;
- uint64_t stx_attributes_mask;
+ __u32 stx_mask;
+ __u32 stx_blksize;
+ __u64 stx_attributes;
+ __u32 stx_nlink;
+ __u32 stx_uid;
+ __u32 stx_gid;
+ __u16 stx_mode;
+ __u16 __spare0[1];
+ __u64 stx_ino;
+ __u64 stx_size;
+ __u64 stx_blocks;
+ __u64 stx_attributes_mask;
struct statx_timestamp stx_atime;
struct statx_timestamp stx_btime;
struct statx_timestamp stx_ctime;
struct statx_timestamp stx_mtime;
- uint32_t stx_rdev_major;
- uint32_t stx_rdev_minor;
- uint32_t stx_dev_major;
- uint32_t stx_dev_minor;
- uint64_t __spare2[14];
+ __u32 stx_rdev_major;
+ __u32 stx_rdev_minor;
+ __u32 stx_dev_major;
+ __u32 stx_dev_minor;
+ __u64 __spare2[14];
};
#endif
--- /dev/null
+/* SPDX-License-Identifier: LGPL-2.1+ */
+#pragma once
+
+#include <stdlib.h>
+
+/* stdlib.h */
+#if !HAVE_SECURE_GETENV
+# if HAVE___SECURE_GETENV
+# define secure_getenv __secure_getenv
+# else
+# error "neither secure_getenv nor __secure_getenv are available"
+# endif
+#endif
#include <fcntl.h>
#include <sys/syscall.h>
#include <sys/types.h>
+#include <unistd.h>
+
+#ifdef ARCH_MIPS
+#include <asm/sgidefs.h>
+#endif
#include "missing_keyctl.h"
#include "missing_stat.h"
+/* linux/kcmp.h */
+#ifndef KCMP_FILE /* 3f4994cfc15f38a3159c6e3a4b3ab2e1481a6b02 (3.19) */
+#define KCMP_FILE 0
+#endif
+
#if !HAVE_PIVOT_ROOT
static inline int missing_pivot_root(const char *new_root, const char *put_old) {
return syscall(__NR_pivot_root, new_root, put_old);
/* ======================================================================= */
#if !HAVE_KEYCTL
-static inline long missing_keyctl(int cmd, unsigned long arg2, unsigned long arg3, unsigned long arg4,unsigned long arg5) {
+static inline long missing_keyctl(int cmd, unsigned long arg2, unsigned long arg3, unsigned long arg4, unsigned long arg5) {
# ifdef __NR_keyctl
return syscall(__NR_keyctl, cmd, arg2, arg3, arg4, arg5);
# else
--- /dev/null
+/* SPDX-License-Identifier: LGPL-2.1+ */
+#pragma once
+
+#include <sys/timerfd.h>
+
+#ifndef TFD_TIMER_CANCEL_ON_SET
+#define TFD_TIMER_CANCEL_ON_SET (1 << 1)
+#endif
if ((flags & AT_EMPTY_PATH) && isempty(filename))
xsprintf(path, "/proc/self/fdinfo/%i", fd);
else {
- subfd = openat(fd, filename, O_CLOEXEC|O_PATH);
+ subfd = openat(fd, filename, O_CLOEXEC|O_PATH|(flags & AT_SYMLINK_FOLLOW ? 0 : O_NOFOLLOW));
if (subfd < 0)
return -errno;
#include <errno.h>
#include <inttypes.h>
+#include <linux/oom.h>
#include <locale.h>
#include <stdio.h>
#include <stdlib.h>
#include "missing.h"
#include "process-util.h"
#include "raw-clone.h"
+#include "rlimit-util.h"
#include "signal-util.h"
#include "stat-util.h"
#include "string-table.h"
}
}
+ if (flags & FORK_RLIMIT_NOFILE_SAFE) {
+ r = rlimit_nofile_safe();
+ if (r < 0) {
+ log_full_errno(prio, r, "Failed to lower RLIMIT_NOFILE's soft limit to 1K: %m");
+ _exit(EXIT_FAILURE);
+ }
+ }
+
if (ret_pid)
*ret_pid = getpid_cached();
safe_close_above_stdio(fd);
}
+ (void) rlimit_nofile_safe();
+
/* Count arguments */
va_start(ap, path);
for (n = 0; va_arg(ap, char*); n++)
int must_be_root(void);
typedef enum ForkFlags {
- FORK_RESET_SIGNALS = 1 << 0,
- FORK_CLOSE_ALL_FDS = 1 << 1,
- FORK_DEATHSIG = 1 << 2,
- FORK_NULL_STDIO = 1 << 3,
- FORK_REOPEN_LOG = 1 << 4,
- FORK_LOG = 1 << 5,
- FORK_WAIT = 1 << 6,
- FORK_NEW_MOUNTNS = 1 << 7,
- FORK_MOUNTNS_SLAVE = 1 << 8,
+ FORK_RESET_SIGNALS = 1 << 0, /* Reset all signal handlers and signal mask */
+ FORK_CLOSE_ALL_FDS = 1 << 1, /* Close all open file descriptors in the child, except for 0,1,2 */
+ FORK_DEATHSIG = 1 << 2, /* Set PR_DEATHSIG in the child */
+ FORK_NULL_STDIO = 1 << 3, /* Connect 0,1,2 to /dev/null */
+ FORK_REOPEN_LOG = 1 << 4, /* Reopen log connection */
+ FORK_LOG = 1 << 5, /* Log above LOG_DEBUG log level about failures */
+ FORK_WAIT = 1 << 6, /* Wait until child exited */
+ FORK_NEW_MOUNTNS = 1 << 7, /* Run child in its own mount namespace */
+ FORK_MOUNTNS_SLAVE = 1 << 8, /* Make child's mount namespace MS_SLAVE */
+ FORK_RLIMIT_NOFILE_SAFE = 1 << 9, /* Set RLIMIT_NOFILE soft limit to 1K for select() compat */
} ForkFlags;
int safe_fork_full(const char *name, const int except_fds[], size_t n_except_fds, ForkFlags flags, pid_t *ret_pid);
#include <elf.h>
#include <errno.h>
#include <fcntl.h>
-#include <linux/random.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdlib.h>
return 0;
}
+
+int rlimit_nofile_safe(void) {
+ struct rlimit rl;
+
+ /* Resets RLIMIT_NOFILE's soft limit FD_SETSIZE (i.e. 1024), for compatibility with software still using
+ * select() */
+
+ if (getrlimit(RLIMIT_NOFILE, &rl) < 0)
+ return log_debug_errno(errno, "Failed to query RLIMIT_NOFILE: %m");
+
+ if (rl.rlim_cur <= FD_SETSIZE)
+ return 0;
+
+ rl.rlim_cur = FD_SETSIZE;
+ if (setrlimit(RLIMIT_NOFILE, &rl) < 0)
+ return log_debug_errno(errno, "Failed to lower RLIMIT_NOFILE's soft limit to " RLIM_FMT ": %m", rl.rlim_cur);
+
+ return 1;
+}
#define RLIMIT_MAKE_CONST(lim) ((struct rlimit) { lim, lim })
int rlimit_nofile_bump(int limit);
+int rlimit_nofile_safe(void);
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
+#include <inttypes.h>
+#include <linux/netlink.h>
+#include <linux/if_infiniband.h>
+#include <linux/if_packet.h>
#include <netinet/ether.h>
#include <netinet/in.h>
#include <stdbool.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <sys/un.h>
-#include <linux/netlink.h>
-#include <linux/if_infiniband.h>
-#include <linux/if_packet.h>
#include "macro.h"
-#include "missing.h"
-#include "util.h"
+#include "missing_socket.h"
+#include "sparse-endian.h"
union sockaddr_union {
/* The minimal, abstract version */
#define ANSI_MAGENTA "\x1B[0;35m"
#define ANSI_CYAN "\x1B[0;36m"
#define ANSI_WHITE "\x1B[0;37m"
+#define ANSI_GREY "\x1B[0;2;37m"
/* Bold/highlighted */
#define ANSI_HIGHLIGHT_BLACK "\x1B[0;1;30m"
DEFINE_ANSI_FUNC(highlight_blue, HIGHLIGHT_BLUE);
DEFINE_ANSI_FUNC(highlight_magenta, HIGHLIGHT_MAGENTA);
DEFINE_ANSI_FUNC(normal, NORMAL);
+DEFINE_ANSI_FUNC(grey, GREY);
DEFINE_ANSI_FUNC_UNDERLINE(underline, UNDERLINE, NORMAL);
DEFINE_ANSI_FUNC_UNDERLINE(highlight_underline, HIGHLIGHT_UNDERLINE, HIGHLIGHT);
#include "io-util.h"
#include "log.h"
#include "macro.h"
-#include "missing.h"
+#include "missing_timerfd.h"
#include "parse-util.h"
#include "path-util.h"
#include "process-util.h"
#include "bus-error.h"
#include "bus-util.h"
#include "dbus-automount.h"
+#include "dbus-unit.h"
#include "fd-util.h"
#include "format-util.h"
#include "io-util.h"
AutomountState old_state;
assert(a);
+ if (a->state != state)
+ bus_unit_send_pending_change_signal(UNIT(a), false);
+
old_state = a->state;
a->state = state;
#include "bpf-program.h"
#include "fd-util.h"
#include "ip-address-access.h"
+#include "missing_syscall.h"
#include "unit.h"
enum {
#include "alloc-util.h"
#include "dbus-job.h"
+#include "dbus-unit.h"
#include "dbus.h"
#include "job.h"
#include "log.h"
assert(j);
+ /* Make sure that any change signal on the unit is reflected before we send out the change signal on the job */
+ bus_unit_send_pending_change_signal(j->unit, true);
+
if (j->in_dbus_queue) {
LIST_REMOVE(dbus_queue, j->manager->dbus_job_queue, j);
j->in_dbus_queue = false;
j->sent_dbus_new_signal = true;
}
+void bus_job_send_pending_change_signal(Job *j, bool including_new) {
+ assert(j);
+
+ if (!j->in_dbus_queue)
+ return;
+
+ if (!j->sent_dbus_new_signal && !including_new)
+ return;
+
+ if (MANAGER_IS_RELOADING(j->unit->manager))
+ return;
+
+ bus_job_send_change_signal(j);
+}
+
static int send_removed_signal(sd_bus *bus, void *userdata) {
_cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
_cleanup_free_ char *p = NULL;
if (!j->sent_dbus_new_signal)
bus_job_send_change_signal(j);
+ /* Make sure that any change signal on the unit is reflected before we send out the change signal on the job */
+ bus_unit_send_pending_change_signal(j->unit, true);
+
r = bus_foreach_bus(j->manager, j->bus_track, send_removed_signal, j);
if (r < 0)
log_debug_errno(r, "Failed to send job remove signal for %u: %m", j->id);
int bus_job_method_get_waiting_jobs(sd_bus_message *message, void *userdata, sd_bus_error *error);
void bus_job_send_change_signal(Job *j);
+void bus_job_send_pending_change_signal(Job *j, bool including_new);
void bus_job_send_removed_signal(Job *j);
int bus_job_coldplug_bus_track(Job *j);
SD_BUS_PROPERTY("AssertResult", "b", bus_property_get_bool, offsetof(Unit, assert_result), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
BUS_PROPERTY_DUAL_TIMESTAMP("ConditionTimestamp", offsetof(Unit, condition_timestamp), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
BUS_PROPERTY_DUAL_TIMESTAMP("AssertTimestamp", offsetof(Unit, assert_timestamp), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
- SD_BUS_PROPERTY("Conditions", "a(sbbsi)", property_get_conditions, offsetof(Unit, conditions), 0),
- SD_BUS_PROPERTY("Asserts", "a(sbbsi)", property_get_conditions, offsetof(Unit, asserts), 0),
+ SD_BUS_PROPERTY("Conditions", "a(sbbsi)", property_get_conditions, offsetof(Unit, conditions), SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION),
+ SD_BUS_PROPERTY("Asserts", "a(sbbsi)", property_get_conditions, offsetof(Unit, asserts), SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION),
SD_BUS_PROPERTY("LoadError", "(ss)", property_get_load_error, 0, SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("Transient", "b", bus_property_get_bool, offsetof(Unit, transient), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("Perpetual", "b", bus_property_get_bool, offsetof(Unit, perpetual), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("SuccessAction", "s", property_get_emergency_action, offsetof(Unit, success_action), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("SuccessActionExitStatus", "i", bus_property_get_int, offsetof(Unit, success_action_exit_status), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("RebootArgument", "s", NULL, offsetof(Unit, reboot_arg), SD_BUS_VTABLE_PROPERTY_CONST),
- SD_BUS_PROPERTY("InvocationID", "ay", bus_property_get_id128, offsetof(Unit, invocation_id), 0),
- SD_BUS_PROPERTY("CollectMode", "s", property_get_collect_mode, offsetof(Unit, collect_mode), 0),
+ SD_BUS_PROPERTY("InvocationID", "ay", bus_property_get_id128, offsetof(Unit, invocation_id), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
+ SD_BUS_PROPERTY("CollectMode", "s", property_get_collect_mode, offsetof(Unit, collect_mode), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("Refs", "as", property_get_refs, 0, 0),
SD_BUS_METHOD("Start", "s", "o", method_start, SD_BUS_VTABLE_UNPRIVILEGED),
u->sent_dbus_new_signal = true;
}
+void bus_unit_send_pending_change_signal(Unit *u, bool including_new) {
+
+ /* Sends out any pending change signals, but only if they really are pending. This call is used when we are
+ * about to change state in order to force out a PropertiesChanged signal beforehand if there was one pending
+ * so that clients can follow the full state transition */
+
+ if (!u->in_dbus_queue) /* If not enqueued, don't bother */
+ return;
+
+ if (!u->sent_dbus_new_signal && !including_new) /* If the unit was never announced, don't bother, it's fine if
+ * the unit appears in the new state right-away (except if the
+ * caller explicitly asked us to send it anyway) */
+ return;
+
+ if (MANAGER_IS_RELOADING(u->manager)) /* Don't generate unnecessary PropertiesChanged signals for the same unit
+ * when we are reloading. */
+ return;
+
+ bus_unit_send_change_signal(u);
+}
+
static int send_removed_signal(sd_bus *bus, void *userdata) {
_cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
_cleanup_free_ char *p = NULL;
if (!path)
return -ENOMEM;
+ /* Before we send the method reply, force out the announcement JobNew for this job */
+ bus_job_send_pending_change_signal(j, true);
+
return sd_bus_reply_method_return(message, "o", path);
}
extern const sd_bus_vtable bus_unit_cgroup_vtable[];
void bus_unit_send_change_signal(Unit *u);
+void bus_unit_send_pending_change_signal(Unit *u, bool including_new);
void bus_unit_send_removed_signal(Unit *u);
int bus_unit_method_start_generic(sd_bus_message *message, Unit *u, JobType job_type, bool reload_if_possible, sd_bus_error *error);
#include "alloc-util.h"
#include "bus-error.h"
#include "dbus-device.h"
+#include "dbus-unit.h"
#include "device-private.h"
#include "device-util.h"
#include "device.h"
DeviceState old_state;
assert(d);
+ if (d->state != state)
+ bus_unit_send_pending_change_signal(UNIT(d), false);
+
old_state = d->state;
d->state = state;
#include "cgroup-util.h"
#include "fdset.h"
#include "list.h"
-#include "missing.h"
+#include "missing_resource.h"
#include "namespace.h"
#include "nsflags.h"
job_add_to_gc_queue(j);
+ job_add_to_dbus_queue(j); /* announce this job to clients */
+ unit_add_to_dbus_queue(j->unit); /* The Job property of the unit has changed now */
+
return j;
}
else if (pid == 0) {
(void) setsid();
(void) make_console_stdio();
+ (void) rlimit_nofile_safe();
(void) execle("/bin/sh", "/bin/sh", NULL, environ);
log_emergency_errno(errno, "execle() failed: %m");
/* Reenable any blocked signals, especially important if we switch from initial ramdisk to init=... */
(void) reset_all_signal_handlers();
(void) reset_signal_mask();
+ (void) rlimit_nofile_safe();
if (switch_root_init) {
args[0] = switch_root_init;
#include "alloc-util.h"
#include "dbus-mount.h"
+#include "dbus-unit.h"
#include "device.h"
#include "escape.h"
#include "exit-status.h"
MOUNT_UNMOUNTING_SIGKILL);
}
-static bool mount_needs_network(const char *options, const char *fstype) {
- if (fstab_test_option(options, "_netdev\0"))
+static bool mount_is_network(const MountParameters *p) {
+ assert(p);
+
+ if (fstab_test_option(p->options, "_netdev\0"))
return true;
- if (fstype && fstype_is_network(fstype))
+ if (p->fstype && fstype_is_network(p->fstype))
return true;
return false;
}
-static bool mount_is_network(const MountParameters *p) {
- assert(p);
-
- return mount_needs_network(p->options, p->fstype);
-}
-
static bool mount_is_loop(const MountParameters *p) {
assert(p);
return fstab_test_option(p->options, "x-systemd.device-bound\0");
}
-static bool needs_quota(const MountParameters *p) {
+static bool mount_needs_quota(const MountParameters *p) {
assert(p);
- /* Quotas are not enabled on network filesystems,
- * but we want them, for example, on storage connected via iscsi */
+ /* Quotas are not enabled on network filesystems, but we want them, for example, on storage connected via
+ * iscsi. We hence don't use mount_is_network() here, as that would also return true for _netdev devices. */
if (p->fstype && fstype_is_network(p->fstype))
return false;
static void mount_parameters_done(MountParameters *p) {
assert(p);
- free(p->what);
- free(p->options);
- free(p->fstype);
-
- p->what = p->options = p->fstype = NULL;
+ p->what = mfree(p->what);
+ p->options = mfree(p->options);
+ p->fstype = mfree(p->fstype);
}
static void mount_done(Unit *u) {
}
static int mount_add_device_dependencies(Mount *m) {
- bool device_wants_mount = false;
+ bool device_wants_mount;
UnitDependencyMask mask;
MountParameters *p;
UnitDependency dep;
if (path_equal(m->where, "/"))
return 0;
- if (mount_is_auto(p) && !mount_is_automount(p) && MANAGER_IS_SYSTEM(UNIT(m)->manager))
- device_wants_mount = true;
+ device_wants_mount =
+ mount_is_auto(p) && !mount_is_automount(p) && MANAGER_IS_SYSTEM(UNIT(m)->manager);
/* Mount units from /proc/self/mountinfo are not bound to devices
* by default since they're subject to races when devices are
if (!p)
return 0;
- if (!needs_quota(p))
+ if (!mount_needs_quota(p))
return 0;
mask = m->from_fragment ? UNIT_DEPENDENCY_FILE : UNIT_DEPENDENCY_MOUNTINFO_IMPLICIT;
}
static int mount_add_default_dependencies(Mount *m) {
+ const char *after, *before;
UnitDependencyMask mask;
- int r;
MountParameters *p;
- const char *after;
+ int r;
assert(m);
return r;
after = SPECIAL_REMOTE_FS_PRE_TARGET;
- } else
+ before = SPECIAL_REMOTE_FS_TARGET;
+ } else {
after = SPECIAL_LOCAL_FS_PRE_TARGET;
+ before = SPECIAL_LOCAL_FS_TARGET;
+ }
+
+ r = unit_add_dependency_by_name(UNIT(m), UNIT_BEFORE, before, true, mask);
+ if (r < 0)
+ return r;
r = unit_add_dependency_by_name(UNIT(m), UNIT_AFTER, after, true, mask);
if (r < 0)
assert(m);
+ /* Note: this call might be called after we already have been loaded once (and even when it has already been
+ * activated), in case data from /proc/self/mountinfo has changed. This means all code here needs to be ready
+ * to run with an already set up unit. */
+
if (u->fragment_path)
m->from_fragment = true;
static int mount_load(Unit *u) {
Mount *m = MOUNT(u);
- int r;
+ int r, q, w;
assert(u);
assert(u->load_state == UNIT_STUB);
r = mount_load_root_mount(u);
- if (r < 0)
- return r;
if (m->from_proc_self_mountinfo || u->perpetual)
- r = unit_load_fragment_and_dropin_optional(u);
+ q = unit_load_fragment_and_dropin_optional(u);
else
- r = unit_load_fragment_and_dropin(u);
+ q = unit_load_fragment_and_dropin(u);
+
+ /* Add in some extras. Note we do this in all cases (even if we failed to load the unit) when announced by the
+ * kernel, because we need some things to be set up no matter what when the kernel establishes a mount and thus
+ * we need to update the state in our unit to track it. After all, consider that we don't allow changing the
+ * 'slice' field for a unit once it is active. */
+ if (u->load_state == UNIT_LOADED || m->from_proc_self_mountinfo || u->perpetual)
+ w = mount_add_extras(m);
+ else
+ w = 0;
+
if (r < 0)
return r;
-
- /* This is a new unit? Then let's add in some extras */
- if (u->load_state == UNIT_LOADED) {
- r = mount_add_extras(m);
- if (r < 0)
- return r;
- }
+ if (q < 0)
+ return q;
+ if (w < 0)
+ return w;
return mount_verify(m);
}
MountState old_state;
assert(m);
+ if (m->state != state)
+ bus_unit_send_pending_change_signal(UNIT(m), false);
+
old_state = m->state;
m->state = state;
(void) mkdir_p_label(m->where, m->directory_mode);
unit_warn_if_dir_nonempty(UNIT(m), m->where);
-
unit_warn_leftover_processes(UNIT(m));
m->control_command_id = MOUNT_EXEC_MOUNT;
mount_enter_dead_or_mounted(m, MOUNT_SUCCESS);
}
+static void mount_cycle_clear(Mount *m) {
+ assert(m);
+
+ /* Clear all state we shall forget for this new cycle */
+
+ m->result = MOUNT_SUCCESS;
+ m->reload_result = MOUNT_SUCCESS;
+ exec_command_reset_status_array(m->exec_command, _MOUNT_EXEC_COMMAND_MAX);
+ UNIT(m)->reset_accounting = true;
+}
+
static int mount_start(Unit *u) {
Mount *m = MOUNT(u);
int r;
if (r < 0)
return r;
- m->result = MOUNT_SUCCESS;
- m->reload_result = MOUNT_SUCCESS;
- exec_command_reset_status_array(m->exec_command, _MOUNT_EXEC_COMMAND_MAX);
-
- u->reset_accounting = true;
-
+ mount_cycle_clear(m);
mount_enter_mounting(m);
+
return 1;
}
(void) serialize_item(f, "state", mount_state_to_string(m->state));
(void) serialize_item(f, "result", mount_result_to_string(m->result));
(void) serialize_item(f, "reload-result", mount_result_to_string(m->reload_result));
+ (void) serialize_item_format(f, "n-retry-umount", "%u", m->n_retry_umount);
if (m->control_pid > 0)
(void) serialize_item_format(f, "control-pid", PID_FMT, m->control_pid);
static int mount_deserialize_item(Unit *u, const char *key, const char *value, FDSet *fds) {
Mount *m = MOUNT(u);
+ int r;
assert(u);
assert(key);
log_unit_debug(u, "Failed to parse state value: %s", value);
else
m->deserialized_state = state;
+
} else if (streq(key, "result")) {
MountResult f;
else if (f != MOUNT_SUCCESS)
m->reload_result = f;
+ } else if (streq(key, "n-retry-umount")) {
+
+ r = safe_atou(value, &m->n_retry_umount);
+ if (r < 0)
+ log_unit_debug(u, "Failed to parse n-retry-umount value: %s", value);
+
} else if (streq(key, "control-pid")) {
- pid_t pid;
- if (parse_pid(value, &pid) < 0)
+ if (parse_pid(value, &m->control_pid) < 0)
log_unit_debug(u, "Failed to parse control-pid value: %s", value);
- else
- m->control_pid = pid;
+
} else if (streq(key, "control-command")) {
MountExecCommand id;
return 0;
}
-typedef struct {
- bool is_mounted;
- bool just_mounted;
- bool just_changed;
-} MountSetupFlags;
+static int update_parameters_proc_self_mount_info(
+ Mount *m,
+ const char *what,
+ const char *options,
+ const char *fstype) {
+
+ MountParameters *p;
+ int r, q, w;
+
+ p = &m->parameters_proc_self_mountinfo;
+
+ r = free_and_strdup(&p->what, what);
+ if (r < 0)
+ return r;
+
+ q = free_and_strdup(&p->options, options);
+ if (q < 0)
+ return q;
+
+ w = free_and_strdup(&p->fstype, fstype);
+ if (w < 0)
+ return w;
+
+ return r > 0 || q > 0 || w > 0;
+}
static int mount_setup_new_unit(
- Unit *u,
+ Manager *m,
+ const char *name,
const char *what,
const char *where,
const char *options,
const char *fstype,
- MountSetupFlags *flags) {
-
- MountParameters *p;
+ MountProcFlags *ret_flags,
+ Unit **ret) {
- assert(u);
- assert(flags);
+ _cleanup_(unit_freep) Unit *u = NULL;
+ int r;
- u->source_path = strdup("/proc/self/mountinfo");
- MOUNT(u)->where = strdup(where);
- if (!u->source_path || !MOUNT(u)->where)
- return -ENOMEM;
+ assert(m);
+ assert(name);
+ assert(ret_flags);
+ assert(ret);
- /* Make sure to initialize those fields before mount_is_extrinsic(). */
- MOUNT(u)->from_proc_self_mountinfo = true;
- p = &MOUNT(u)->parameters_proc_self_mountinfo;
+ r = unit_new_for_name(m, sizeof(Mount), name, &u);
+ if (r < 0)
+ return r;
- p->what = strdup(what);
- p->options = strdup(options);
- p->fstype = strdup(fstype);
- if (!p->what || !p->options || !p->fstype)
- return -ENOMEM;
+ r = free_and_strdup(&u->source_path, "/proc/self/mountinfo");
+ if (r < 0)
+ return r;
- if (!mount_is_extrinsic(MOUNT(u))) {
- const char *target;
- int r;
+ r = free_and_strdup(&MOUNT(u)->where, where);
+ if (r < 0)
+ return r;
- target = mount_is_network(p) ? SPECIAL_REMOTE_FS_TARGET : SPECIAL_LOCAL_FS_TARGET;
- r = unit_add_dependency_by_name(u, UNIT_BEFORE, target, true, UNIT_DEPENDENCY_MOUNTINFO_IMPLICIT);
- if (r < 0)
- return r;
+ r = update_parameters_proc_self_mount_info(MOUNT(u), what, options, fstype);
+ if (r < 0)
+ return r;
- r = unit_add_dependency_by_name(u, UNIT_CONFLICTS, SPECIAL_UMOUNT_TARGET, true, UNIT_DEPENDENCY_MOUNTINFO_IMPLICIT);
- if (r < 0)
- return r;
- }
+ /* This unit was generated because /proc/self/mountinfo reported it. Remember this, so that by the time we load
+ * the unit file for it (and thus add in extra deps right after) we know what source to attributes the deps
+ * to.*/
+ MOUNT(u)->from_proc_self_mountinfo = true;
+ /* We have only allocated the stub now, let's enqueue this unit for loading now, so that everything else is
+ * loaded in now. */
unit_add_to_load_queue(u);
- flags->is_mounted = true;
- flags->just_mounted = true;
- flags->just_changed = true;
+ *ret_flags = MOUNT_PROC_IS_MOUNTED | MOUNT_PROC_JUST_MOUNTED | MOUNT_PROC_JUST_CHANGED;
+ *ret = TAKE_PTR(u);
return 0;
}
const char *where,
const char *options,
const char *fstype,
- MountSetupFlags *flags) {
+ MountProcFlags *ret_flags) {
- MountParameters *p;
- bool load_extras = false;
- int r1, r2, r3;
+ MountProcFlags flags = MOUNT_PROC_IS_MOUNTED;
+ int r;
assert(u);
assert(flags);
return -ENOMEM;
}
- /* Make sure to initialize those fields before mount_is_extrinsic(). */
- p = &MOUNT(u)->parameters_proc_self_mountinfo;
-
- r1 = free_and_strdup(&p->what, what);
- r2 = free_and_strdup(&p->options, options);
- r3 = free_and_strdup(&p->fstype, fstype);
- if (r1 < 0 || r2 < 0 || r3 < 0)
- return -ENOMEM;
-
- flags->just_changed = r1 > 0 || r2 > 0 || r3 > 0;
- flags->is_mounted = true;
- flags->just_mounted = !MOUNT(u)->from_proc_self_mountinfo || MOUNT(u)->just_mounted;
-
- MOUNT(u)->from_proc_self_mountinfo = true;
+ r = update_parameters_proc_self_mount_info(MOUNT(u), what, options, fstype);
+ if (r < 0)
+ return r;
+ if (r > 0)
+ flags |= MOUNT_PROC_JUST_CHANGED;
- if (!mount_is_extrinsic(MOUNT(u)) && mount_is_network(p)) {
- /* _netdev option may have shown up late, or on a
- * remount. Add remote-fs dependencies, even though
- * local-fs ones may already be there.
- *
- * Note: due to a current limitation (we don't track
- * in the dependency "Set*" objects who created a
- * dependency), we can only add deps, never lose them,
- * until the next full daemon-reload. */
- unit_add_dependency_by_name(u, UNIT_BEFORE, SPECIAL_REMOTE_FS_TARGET, true, UNIT_DEPENDENCY_MOUNTINFO_IMPLICIT);
- load_extras = true;
+ if (!MOUNT(u)->from_proc_self_mountinfo) {
+ flags |= MOUNT_PROC_JUST_MOUNTED;
+ MOUNT(u)->from_proc_self_mountinfo = true;
}
- if (u->load_state == UNIT_NOT_FOUND) {
+ if (IN_SET(u->load_state, UNIT_NOT_FOUND, UNIT_BAD_SETTING, UNIT_ERROR)) {
+ /* The unit was previously not found or otherwise not loaded. Now that the unit shows up in
+ * /proc/self/mountinfo we should reconsider it this, hence set it to UNIT_LOADED. */
u->load_state = UNIT_LOADED;
u->load_error = 0;
- /* Load in the extras later on, after we
- * finished initialization of the unit */
-
- /* FIXME: since we're going to load the unit later on, why setting load_extras=true ? */
- load_extras = true;
- flags->just_changed = true;
+ flags |= MOUNT_PROC_JUST_CHANGED;
}
- if (load_extras)
- return mount_add_extras(MOUNT(u));
+ if (FLAGS_SET(flags, MOUNT_PROC_JUST_CHANGED)) {
+ /* If things changed, then make sure that all deps are regenerated. Let's
+ * first remove all automatic deps, and then add in the new ones. */
+ unit_remove_dependencies(u, UNIT_DEPENDENCY_MOUNTINFO_IMPLICIT);
+
+ r = mount_add_extras(MOUNT(u));
+ if (r < 0)
+ return r;
+ }
+
+ *ret_flags = flags;
return 0;
}
bool set_flags) {
_cleanup_free_ char *e = NULL;
- MountSetupFlags flags;
+ MountProcFlags flags;
Unit *u;
int r;
r = unit_name_from_path(where, ".mount", &e);
if (r < 0)
- return r;
+ return log_error_errno(r, "Failed to generate unit name from path '%s': %m", where);
u = manager_get_unit(m, e);
- if (!u) {
- /* First time we see this mount point meaning that it's
- * not been initiated by a mount unit but rather by the
- * sysadmin having called mount(8) directly. */
- r = unit_new_for_name(m, sizeof(Mount), e, &u);
- if (r < 0)
- goto fail;
-
- r = mount_setup_new_unit(u, what, where, options, fstype, &flags);
- if (r < 0)
- unit_free(u);
- } else
+ if (u)
r = mount_setup_existing_unit(u, what, where, options, fstype, &flags);
-
+ else
+ /* First time we see this mount point meaning that it's not been initiated by a mount unit but rather
+ * by the sysadmin having called mount(8) directly. */
+ r = mount_setup_new_unit(m, e, what, where, options, fstype, &flags, &u);
if (r < 0)
- goto fail;
-
- if (set_flags) {
- MOUNT(u)->is_mounted = flags.is_mounted;
- MOUNT(u)->just_mounted = flags.just_mounted;
- MOUNT(u)->just_changed = flags.just_changed;
- }
+ return log_warning_errno(r, "Failed to set up mount unit: %m");
- if (flags.just_changed)
+ /* If the mount changed properties or state, let's notify our clients */
+ if (flags & (MOUNT_PROC_JUST_CHANGED|MOUNT_PROC_JUST_MOUNTED))
unit_add_to_dbus_queue(u);
+ if (set_flags)
+ MOUNT(u)->proc_flags = flags;
+
return 0;
-fail:
- return log_warning_errno(r, "Failed to set up mount unit: %m");
}
static int mount_load_proc_self_mountinfo(Manager *m, bool set_flags) {
_cleanup_(mnt_free_tablep) struct libmnt_table *t = NULL;
_cleanup_(mnt_free_iterp) struct libmnt_iter *i = NULL;
- int r = 0;
+ int r;
assert(m);
if (r < 0)
return log_error_errno(r, "Failed to parse /proc/self/mountinfo: %m");
- r = 0;
for (;;) {
struct libmnt_fs *fs;
const char *device, *path, *options, *fstype;
device_found_node(m, d, DEVICE_FOUND_MOUNT, DEVICE_FOUND_MOUNT);
- k = mount_setup_unit(m, d, p, options, fstype, set_flags);
- if (r == 0 && k < 0)
- r = k;
+ (void) mount_setup_unit(m, d, p, options, fstype, set_flags);
}
- return r;
+ return 0;
}
static void mount_shutdown(Manager *m) {
static bool mount_is_mounted(Mount *m) {
assert(m);
- return UNIT(m)->perpetual || m->is_mounted;
+ return UNIT(m)->perpetual || FLAGS_SET(m->proc_flags, MOUNT_PROC_IS_MOUNTED);
}
static void mount_enumerate(Manager *m) {
}
static int mount_dispatch_io(sd_event_source *source, int fd, uint32_t revents, void *userdata) {
- _cleanup_set_free_ Set *around = NULL, *gone = NULL;
+ _cleanup_set_free_free_ Set *around = NULL, *gone = NULL;
Manager *m = userdata;
const char *what;
Iterator i;
r = mount_load_proc_self_mountinfo(m, true);
if (r < 0) {
/* Reset flags, just in case, for later calls */
- LIST_FOREACH(units_by_type, u, m->units_by_type[UNIT_MOUNT]) {
- Mount *mount = MOUNT(u);
-
- mount->is_mounted = mount->just_mounted = mount->just_changed = false;
- }
+ LIST_FOREACH(units_by_type, u, m->units_by_type[UNIT_MOUNT])
+ MOUNT(u)->proc_flags = 0;
return 0;
}
/* Remember that this device might just have disappeared */
if (set_ensure_allocated(&gone, &path_hash_ops) < 0 ||
- set_put(gone, mount->parameters_proc_self_mountinfo.what) < 0)
+ set_put_strdup(gone, mount->parameters_proc_self_mountinfo.what) < 0)
log_oom(); /* we don't care too much about OOM here... */
}
switch (mount->state) {
case MOUNT_MOUNTED:
- /* This has just been unmounted by
- * somebody else, follow the state
- * change. */
- mount->result = MOUNT_SUCCESS; /* make sure we forget any earlier umount failures */
+ /* This has just been unmounted by somebody else, follow the state change. */
mount_enter_dead(mount, MOUNT_SUCCESS);
break;
break;
}
- } else if (mount->just_mounted || mount->just_changed) {
+ } else if (mount->proc_flags & (MOUNT_PROC_JUST_MOUNTED|MOUNT_PROC_JUST_CHANGED)) {
/* A mount point was added or changed */
/* This has just been mounted by somebody else, follow the state change, but let's
* generate a new invocation ID for this implicitly and automatically. */
- (void) unit_acquire_invocation_id(UNIT(mount));
+ (void) unit_acquire_invocation_id(u);
+ mount_cycle_clear(mount);
mount_enter_mounted(mount, MOUNT_SUCCESS);
break;
if (mount_is_mounted(mount) &&
mount->from_proc_self_mountinfo &&
mount->parameters_proc_self_mountinfo.what) {
+ /* Track devices currently used */
if (set_ensure_allocated(&around, &path_hash_ops) < 0 ||
- set_put(around, mount->parameters_proc_self_mountinfo.what) < 0)
+ set_put_strdup(around, mount->parameters_proc_self_mountinfo.what) < 0)
log_oom();
}
/* Reset the flags for later calls */
- mount->is_mounted = mount->just_mounted = mount->just_changed = false;
+ mount->proc_flags = 0;
}
SET_FOREACH(what, gone, i) {
char *fstype;
} MountParameters;
+/* Used while looking for mount points that vanished or got added from/to /proc/self/mountinfo */
+typedef enum MountProcFlags {
+ MOUNT_PROC_IS_MOUNTED = 1 << 0,
+ MOUNT_PROC_JUST_MOUNTED = 1 << 1,
+ MOUNT_PROC_JUST_CHANGED = 1 << 2,
+} MountProcFlags;
+
struct Mount {
Unit meta;
bool from_proc_self_mountinfo:1;
bool from_fragment:1;
- /* Used while looking for mount points that vanished or got
- * added from/to /proc/self/mountinfo */
- bool is_mounted:1;
- bool just_mounted:1;
- bool just_changed:1;
+ MountProcFlags proc_flags;
bool sloppy_options;
#include "bus-error.h"
#include "bus-util.h"
#include "dbus-path.h"
+#include "dbus-unit.h"
#include "fd-util.h"
#include "fs-util.h"
#include "glob-util.h"
PathState old_state;
assert(p);
+ if (p->state != state)
+ bus_unit_send_pending_change_signal(UNIT(p), false);
+
old_state = p->state;
p->state = state;
#include "alloc-util.h"
#include "dbus-scope.h"
+#include "dbus-unit.h"
#include "load-dropin.h"
#include "log.h"
#include "scope.h"
ScopeState old_state;
assert(s);
+ if (s->state != state)
+ bus_unit_send_pending_change_signal(UNIT(s), false);
+
old_state = s->state;
s->state = state;
#include "bus-kernel.h"
#include "bus-util.h"
#include "dbus-service.h"
+#include "dbus-unit.h"
#include "def.h"
#include "env-util.h"
#include "escape.h"
assert(s);
+ if (s->state != state)
+ bus_unit_send_pending_change_signal(UNIT(s), false);
+
table = s->type == SERVICE_IDLE ? state_translation_table_idle : state_translation_table;
old_state = s->state;
#include "parse-util.h"
#include "process-util.h"
#include "reboot-util.h"
+#include "rlimit-util.h"
#include "signal-util.h"
#include "string-util.h"
#include "switch-root.h"
arguments[2] = NULL;
execute_directories(dirs, DEFAULT_TIMEOUT_USEC, NULL, NULL, arguments, NULL);
+ (void) rlimit_nofile_safe();
+
if (can_initrd) {
r = switch_root_initramfs();
if (r >= 0) {
argv[0] = (char*) "/shutdown";
- setsid();
- make_console_stdio();
+ (void) setsid();
+ (void) make_console_stdio();
log_info("Successfully changed into root pivot.\n"
"Returning to initrd...");
#include "alloc-util.h"
#include "dbus-slice.h"
+#include "dbus-unit.h"
#include "log.h"
#include "serialize.h"
#include "slice.h"
SliceState old_state;
assert(t);
+ if (t->state != state)
+ bus_unit_send_pending_change_signal(UNIT(t), false);
+
old_state = t->state;
t->state = state;
#include "bus-util.h"
#include "copy.h"
#include "dbus-socket.h"
+#include "dbus-unit.h"
#include "def.h"
#include "exit-status.h"
#include "fd-util.h"
SocketState old_state;
assert(s);
+ if (s->state != state)
+ bus_unit_send_pending_change_signal(UNIT(s), false);
+
old_state = s->state;
s->state = state;
#include "alloc-util.h"
#include "dbus-swap.h"
+#include "dbus-unit.h"
#include "device-private.h"
#include "device-util.h"
#include "device.h"
return swap_set_devnode(s, p);
}
-static int swap_load(Unit *u) {
+static int swap_add_extras(Swap *s) {
int r;
- Swap *s = SWAP(u);
assert(s);
- assert(u->load_state == UNIT_STUB);
- /* Load a .swap file */
- if (SWAP(u)->from_proc_swaps)
- r = unit_load_fragment_and_dropin_optional(u);
- else
- r = unit_load_fragment_and_dropin(u);
+ if (UNIT(s)->fragment_path)
+ s->from_fragment = true;
+
+ if (!s->what) {
+ if (s->parameters_fragment.what)
+ s->what = strdup(s->parameters_fragment.what);
+ else if (s->parameters_proc_swaps.what)
+ s->what = strdup(s->parameters_proc_swaps.what);
+ else {
+ r = unit_name_to_path(UNIT(s)->id, &s->what);
+ if (r < 0)
+ return r;
+ }
+
+ if (!s->what)
+ return -ENOMEM;
+ }
+
+ path_simplify(s->what, false);
+
+ if (!UNIT(s)->description) {
+ r = unit_set_description(UNIT(s), s->what);
+ if (r < 0)
+ return r;
+ }
+
+ r = unit_require_mounts_for(UNIT(s), s->what, UNIT_DEPENDENCY_IMPLICIT);
if (r < 0)
return r;
- if (u->load_state == UNIT_LOADED) {
-
- if (UNIT(s)->fragment_path)
- s->from_fragment = true;
+ r = swap_add_device_dependencies(s);
+ if (r < 0)
+ return r;
- if (!s->what) {
- if (s->parameters_fragment.what)
- s->what = strdup(s->parameters_fragment.what);
- else if (s->parameters_proc_swaps.what)
- s->what = strdup(s->parameters_proc_swaps.what);
- else {
- r = unit_name_to_path(u->id, &s->what);
- if (r < 0)
- return r;
- }
+ r = swap_load_devnode(s);
+ if (r < 0)
+ return r;
- if (!s->what)
- return -ENOMEM;
- }
+ r = unit_patch_contexts(UNIT(s));
+ if (r < 0)
+ return r;
- path_simplify(s->what, false);
+ r = unit_add_exec_dependencies(UNIT(s), &s->exec_context);
+ if (r < 0)
+ return r;
- if (!UNIT(s)->description) {
- r = unit_set_description(u, s->what);
- if (r < 0)
- return r;
- }
+ r = unit_set_default_slice(UNIT(s));
+ if (r < 0)
+ return r;
- r = unit_require_mounts_for(UNIT(s), s->what, UNIT_DEPENDENCY_IMPLICIT);
- if (r < 0)
- return r;
+ r = swap_add_default_dependencies(s);
+ if (r < 0)
+ return r;
- r = swap_add_device_dependencies(s);
- if (r < 0)
- return r;
+ return 0;
+}
- r = swap_load_devnode(s);
- if (r < 0)
- return r;
+static int swap_load(Unit *u) {
+ Swap *s = SWAP(u);
+ int r, q;
- r = unit_patch_contexts(u);
- if (r < 0)
- return r;
+ assert(s);
+ assert(u->load_state == UNIT_STUB);
- r = unit_add_exec_dependencies(u, &s->exec_context);
- if (r < 0)
- return r;
+ /* Load a .swap file */
+ if (SWAP(u)->from_proc_swaps)
+ r = unit_load_fragment_and_dropin_optional(u);
+ else
+ r = unit_load_fragment_and_dropin(u);
- r = unit_set_default_slice(u);
- if (r < 0)
- return r;
+ /* Add in some extras, and do so either when we successfully loaded something or when /proc/swaps is already
+ * active. */
+ if (u->load_state == UNIT_LOADED || s->from_proc_swaps)
+ q = swap_add_extras(s);
+ else
+ q = 0;
- r = swap_add_default_dependencies(s);
- if (r < 0)
- return r;
- }
+ if (r < 0)
+ return r;
+ if (q < 0)
+ return q;
return swap_verify(s);
}
return log_unit_error_errno(u, r, "Failed to generate unit name from path: %m");
u = manager_get_unit(m, e);
-
if (u &&
SWAP(u)->from_proc_swaps &&
!path_equal(SWAP(u)->parameters_proc_swaps.what, what_proc_swaps))
}
}
+ /* The unit is definitely around now, mark it as loaded if it was previously referenced but could not be
+ * loaded. After all we can load it now, from the data in /proc/swaps. */
+ if (IN_SET(u->load_state, UNIT_NOT_FOUND, UNIT_BAD_SETTING, UNIT_ERROR)) {
+ u->load_state = UNIT_LOADED;
+ u->load_error = 0;
+ }
+
if (set_flags) {
SWAP(u)->is_active = true;
SWAP(u)->just_activated = !SWAP(u)->from_proc_swaps;
swap_setup_unit(m, devlink, device, prio, set_flags);
}
- return r;
+ return 0;
}
static void swap_set_state(Swap *s, SwapState state) {
assert(s);
+ if (s->state != state)
+ bus_unit_send_pending_change_signal(UNIT(s), false);
+
old_state = s->state;
s->state = state;
swap_enter_dead_or_active(s, SWAP_FAILURE_RESOURCES);
}
+static void swap_cycle_clear(Swap *s) {
+ assert(s);
+
+ s->result = SWAP_SUCCESS;
+ exec_command_reset_status_array(s->exec_command, _SWAP_EXEC_COMMAND_MAX);
+ UNIT(s)->reset_accounting = true;
+}
+
static int swap_start(Unit *u) {
Swap *s = SWAP(u), *other;
int r;
if (r < 0)
return r;
- s->result = SWAP_SUCCESS;
- exec_command_reset_status_array(s->exec_command, _SWAP_EXEC_COMMAND_MAX);
-
- u->reset_accounting = true;
-
+ swap_cycle_clear(s);
swap_enter_activating(s);
return 1;
}
static int swap_load_proc_swaps(Manager *m, bool set_flags) {
unsigned i;
- int r = 0;
assert(m);
device_found_node(m, d, DEVICE_FOUND_SWAP, DEVICE_FOUND_SWAP);
- k = swap_process_new(m, d, prio, set_flags);
- if (k < 0)
- r = k;
+ (void) swap_process_new(m, d, prio, set_flags);
}
- return r;
+ return 0;
}
static int swap_dispatch_io(sd_event_source *source, int fd, uint32_t revents, void *userdata) {
Swap *swap = SWAP(u);
if (!swap->is_active) {
- /* This has just been deactivated */
swap_unset_proc_swaps(swap);
switch (swap->state) {
case SWAP_ACTIVE:
+ /* This has just been deactivated */
swap_enter_dead(swap, SWAP_SUCCESS);
break;
case SWAP_DEAD:
case SWAP_FAILED:
- (void) unit_acquire_invocation_id(UNIT(swap));
+ (void) unit_acquire_invocation_id(u);
+ swap_cycle_clear(swap);
swap_enter_active(swap, SWAP_SUCCESS);
break;
/* SPDX-License-Identifier: LGPL-2.1+ */
#include "dbus-target.h"
+#include "dbus-unit.h"
#include "log.h"
#include "serialize.h"
#include "special.h"
TargetState old_state;
assert(t);
+ if (t->state != state)
+ bus_unit_send_pending_change_signal(UNIT(t), false);
+
old_state = t->state;
t->state = state;
#include "bus-error.h"
#include "bus-util.h"
#include "dbus-timer.h"
+#include "dbus-unit.h"
#include "fs-util.h"
#include "parse-util.h"
#include "random-util.h"
TimerState old_state;
assert(t);
+ if (t->state != state)
+ bus_unit_send_pending_change_signal(UNIT(t), false);
+
old_state = t->state;
t->state = state;
dual_timestamp_get(&u->condition_timestamp);
u->condition_result = unit_condition_test_list(u, u->conditions, condition_type_to_string);
+ unit_add_to_dbus_queue(u);
+
return u->condition_result;
}
dual_timestamp_get(&u->assert_timestamp);
u->assert_result = unit_condition_test_list(u, u->asserts, assert_type_to_string);
+ unit_add_to_dbus_queue(u);
+
return u->assert_result;
}
m = u->manager;
+ /* Let's enqueue the change signal early. In case this unit has a job associated we want that this unit is in
+ * the bus queue, so that any job change signal queued will force out the unit change signal first. */
+ unit_add_to_dbus_queue(u);
+
/* Update timestamps for state changes */
if (!MANAGER_IS_RELOADING(m)) {
dual_timestamp_get(&u->state_change_timestamp);
}
}
- unit_add_to_dbus_queue(u);
unit_add_to_gc_queue(u);
}
r = unit_ref_uid_gid(u, uid, gid);
if (r > 0)
- bus_unit_send_change_signal(u);
+ unit_add_to_dbus_queue(u);
}
int unit_set_invocation_id(Unit *u, sd_id128_t id) {
if (r < 0)
return log_unit_error_errno(u, r, "Failed to set invocation ID for unit: %m");
+ unit_add_to_dbus_queue(u);
return 0;
}
fork_name = strjoina("(", arg_debugger, ")");
- r = safe_fork(fork_name, FORK_RESET_SIGNALS|FORK_DEATHSIG|FORK_CLOSE_ALL_FDS|FORK_LOG, &pid);
+ r = safe_fork(fork_name, FORK_RESET_SIGNALS|FORK_DEATHSIG|FORK_CLOSE_ALL_FDS|FORK_RLIMIT_NOFILE_SAFE|FORK_LOG, &pid);
if (r < 0)
goto finish;
if (r == 0) {
fflush(stdout);
- r = safe_fork("(diff)", FORK_RESET_SIGNALS|FORK_DEATHSIG|FORK_CLOSE_ALL_FDS|FORK_LOG, &pid);
+ r = safe_fork("(diff)", FORK_RESET_SIGNALS|FORK_DEATHSIG|FORK_CLOSE_ALL_FDS|FORK_RLIMIT_NOFILE_SAFE|FORK_LOG, &pid);
if (r < 0)
return r;
if (r == 0) {
#include "path-util.h"
#include "proc-cmdline.h"
#include "process-util.h"
+#include "rlimit-util.h"
#include "signal-util.h"
#include "socket-util.h"
#include "special.h"
cmdline[i++] = device;
cmdline[i++] = NULL;
+ (void) rlimit_nofile_safe();
+
execv(cmdline[0], (char**) cmdline);
_exit(FSCK_OPERATIONAL_ERROR);
}
/* SPDX-License-Identifier: LGPL-2.1+ */
-#include <netinet/icmp6.h>
#include <arpa/inet.h>
+#include <netinet/icmp6.h>
+#include <unistd.h>
#include "alloc-util.h"
#include "icmp6-util.h"
#include "process-util.h"
#include "pull-common.h"
#include "pull-job.h"
+#include "rlimit-util.h"
#include "rm-rf.h"
#include "signal-util.h"
#include "siphash24.h"
_exit(EXIT_FAILURE);
}
+ (void) rlimit_nofile_safe();
+
cmd[k++] = strjoina("--homedir=", gpg_home);
/* We add the user keyring only to the command line
#include "hostname-util.h"
#include "log.h"
#include "logs-show.h"
+#include "main-func.h"
#include "microhttpd-util.h"
#include "os-util.h"
#include "parse-util.h"
static char *arg_key_pem = NULL;
static char *arg_cert_pem = NULL;
static char *arg_trust_pem = NULL;
-static char *arg_directory = NULL;
+static const char *arg_directory = NULL;
+
+STATIC_DESTRUCTOR_REGISTER(arg_key_pem, freep);
+STATIC_DESTRUCTOR_REGISTER(arg_cert_pem, freep);
+STATIC_DESTRUCTOR_REGISTER(arg_trust_pem, freep);
typedef struct RequestMeta {
sd_journal *journal;
return 1;
}
-int main(int argc, char *argv[]) {
- struct MHD_Daemon *d = NULL;
+static int run(int argc, char *argv[]) {
+ _cleanup_(MHD_stop_daemonp) struct MHD_Daemon *d = NULL;
+ struct MHD_OptionItem opts[] = {
+ { MHD_OPTION_NOTIFY_COMPLETED,
+ (intptr_t) request_meta_free, NULL },
+ { MHD_OPTION_EXTERNAL_LOGGER,
+ (intptr_t) microhttpd_logger, NULL },
+ { MHD_OPTION_END, 0, NULL },
+ { MHD_OPTION_END, 0, NULL },
+ { MHD_OPTION_END, 0, NULL },
+ { MHD_OPTION_END, 0, NULL },
+ { MHD_OPTION_END, 0, NULL },
+ };
+ int opts_pos = 2;
+
+ /* We force MHD_USE_ITC here, in order to make sure
+ * libmicrohttpd doesn't use shutdown() on our listening
+ * socket, which would break socket re-activation. See
+ *
+ * https://lists.gnu.org/archive/html/libmicrohttpd/2015-09/msg00014.html
+ * https://github.com/systemd/systemd/pull/1286
+ */
+
+ int flags =
+ MHD_USE_DEBUG |
+ MHD_USE_DUAL_STACK |
+ MHD_USE_ITC |
+ MHD_USE_POLL_INTERNAL_THREAD |
+ MHD_USE_THREAD_PER_CONNECTION;
int r, n;
log_setup_service();
r = parse_argv(argc, argv);
- if (r < 0)
- return EXIT_FAILURE;
- if (r == 0)
- return EXIT_SUCCESS;
+ if (r <= 0)
+ return r;
sigbus_install();
r = setup_gnutls_logger(NULL);
if (r < 0)
- return EXIT_FAILURE;
+ return r;
n = sd_listen_fds(1);
- if (n < 0) {
- log_error_errno(n, "Failed to determine passed sockets: %m");
- goto finish;
- } else if (n > 1) {
- log_error("Can't listen on more than one socket.");
- goto finish;
- } else {
- struct MHD_OptionItem opts[] = {
- { MHD_OPTION_NOTIFY_COMPLETED,
- (intptr_t) request_meta_free, NULL },
- { MHD_OPTION_EXTERNAL_LOGGER,
- (intptr_t) microhttpd_logger, NULL },
- { MHD_OPTION_END, 0, NULL },
- { MHD_OPTION_END, 0, NULL },
- { MHD_OPTION_END, 0, NULL },
- { MHD_OPTION_END, 0, NULL },
- { MHD_OPTION_END, 0, NULL }};
- int opts_pos = 2;
-
- /* We force MHD_USE_ITC here, in order to make sure
- * libmicrohttpd doesn't use shutdown() on our listening
- * socket, which would break socket re-activation. See
- *
- * https://lists.gnu.org/archive/html/libmicrohttpd/2015-09/msg00014.html
- * https://github.com/systemd/systemd/pull/1286
- */
-
- int flags =
- MHD_USE_DEBUG |
- MHD_USE_DUAL_STACK |
- MHD_USE_ITC |
- MHD_USE_POLL_INTERNAL_THREAD |
- MHD_USE_THREAD_PER_CONNECTION;
-
- if (n > 0)
- opts[opts_pos++] = (struct MHD_OptionItem)
- {MHD_OPTION_LISTEN_SOCKET, SD_LISTEN_FDS_START};
- if (arg_key_pem) {
- assert(arg_cert_pem);
- opts[opts_pos++] = (struct MHD_OptionItem)
- {MHD_OPTION_HTTPS_MEM_KEY, 0, arg_key_pem};
- opts[opts_pos++] = (struct MHD_OptionItem)
- {MHD_OPTION_HTTPS_MEM_CERT, 0, arg_cert_pem};
- flags |= MHD_USE_TLS;
- }
- if (arg_trust_pem) {
- assert(flags & MHD_USE_TLS);
- opts[opts_pos++] = (struct MHD_OptionItem)
- {MHD_OPTION_HTTPS_MEM_TRUST, 0, arg_trust_pem};
- }
-
- d = MHD_start_daemon(flags, 19531,
- NULL, NULL,
- request_handler, NULL,
- MHD_OPTION_ARRAY, opts,
- MHD_OPTION_END);
+ if (n < 0)
+ return log_error_errno(n, "Failed to determine passed sockets: %m");
+ if (n > 1)
+ return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Can't listen on more than one socket.");
+
+ if (n == 1)
+ opts[opts_pos++] = (struct MHD_OptionItem)
+ { MHD_OPTION_LISTEN_SOCKET, SD_LISTEN_FDS_START };
+
+ if (arg_key_pem) {
+ assert(arg_cert_pem);
+ opts[opts_pos++] = (struct MHD_OptionItem)
+ { MHD_OPTION_HTTPS_MEM_KEY, 0, arg_key_pem };
+ opts[opts_pos++] = (struct MHD_OptionItem)
+ { MHD_OPTION_HTTPS_MEM_CERT, 0, arg_cert_pem };
+ flags |= MHD_USE_TLS;
}
- if (!d) {
- log_error("Failed to start daemon!");
- goto finish;
+ if (arg_trust_pem) {
+ assert(flags & MHD_USE_TLS);
+ opts[opts_pos++] = (struct MHD_OptionItem)
+ { MHD_OPTION_HTTPS_MEM_TRUST, 0, arg_trust_pem };
}
- pause();
-
- r = EXIT_SUCCESS;
+ d = MHD_start_daemon(flags, 19531,
+ NULL, NULL,
+ request_handler, NULL,
+ MHD_OPTION_ARRAY, opts,
+ MHD_OPTION_END);
+ if (!d)
+ return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Failed to start daemon!");
-finish:
- if (d)
- MHD_stop_daemon(d);
+ pause();
- return r;
+ return 0;
}
+
+DEFINE_MAIN_FUNCTION(run);
#include "sd-daemon.h"
#include "conf-parser.h"
+#include "daemon-util.h"
#include "def.h"
#include "fd-util.h"
#include "fileio.h"
#include "journal-remote-write.h"
#include "journal-remote.h"
+#include "main-func.h"
#include "pretty-print.h"
#include "process-util.h"
#include "rlimit-util.h"
#define CERT_FILE CERTIFICATE_ROOT "/certs/journal-remote.pem"
#define TRUST_FILE CERTIFICATE_ROOT "/ca/trusted.pem"
-static char* arg_url = NULL;
-static char* arg_getter = NULL;
-static char* arg_listen_raw = NULL;
-static char* arg_listen_http = NULL;
-static char* arg_listen_https = NULL;
-static char** arg_files = NULL;
+static const char* arg_url = NULL;
+static const char* arg_getter = NULL;
+static const char* arg_listen_raw = NULL;
+static const char* arg_listen_http = NULL;
+static const char* arg_listen_https = NULL;
+static char** arg_files = NULL; /* Do not free this. */
static int arg_compress = true;
static int arg_seal = false;
static int http_socket = -1, https_socket = -1;
static char** arg_gnutls_log = NULL;
static JournalWriteSplitMode arg_split_mode = _JOURNAL_WRITE_SPLIT_INVALID;
-static char* arg_output = NULL;
+static const char* arg_output = NULL;
static char *arg_key = NULL;
static char *arg_cert = NULL;
static char *arg_trust = NULL;
static bool arg_trust_all = false;
+STATIC_DESTRUCTOR_REGISTER(arg_gnutls_log, strv_freep);
+STATIC_DESTRUCTOR_REGISTER(arg_key, freep);
+STATIC_DESTRUCTOR_REGISTER(arg_cert, freep);
+STATIC_DESTRUCTOR_REGISTER(arg_trust, freep);
+
static const char* const journal_write_split_mode_table[_JOURNAL_WRITE_SPLIT_MAX] = {
[JOURNAL_WRITE_SPLIT_NONE] = "none",
[JOURNAL_WRITE_SPLIT_HOST] = "host",
_exit(EXIT_FAILURE);
}
+ (void) rlimit_nofile_safe();
+
execvp(child, argv);
log_error_errno(errno, "Failed to exec child %s: %m", child);
_exit(EXIT_FAILURE);
}
if (arg_url) {
- const char *url;
- char *hostname;
+ const char *url, *hostname;
if (!strstr(arg_url, "/entries")) {
if (endswith(arg_url, "/"))
hostname = strndupa(hostname, strcspn(hostname, "/:"));
- r = journal_remote_add_source(s, fd, hostname, false);
+ r = journal_remote_add_source(s, fd, (char *) hostname, false);
if (r < 0)
return r;
}
return 0;
}
-int main(int argc, char **argv) {
- RemoteServer s = {};
- int r;
+static int run(int argc, char **argv) {
+ _cleanup_(notify_on_cleanup) const char *notify_message = NULL;
+ _cleanup_(journal_remote_server_destroy) RemoteServer s = {};
_cleanup_free_ char *key = NULL, *cert = NULL, *trust = NULL;
+ int r;
log_show_color(true);
log_parse_environment();
r = parse_config();
if (r < 0)
- return EXIT_FAILURE;
+ return r;
r = parse_argv(argc, argv);
if (r <= 0)
- return r == 0 ? EXIT_SUCCESS : EXIT_FAILURE;
+ return r;
if (arg_listen_http || arg_listen_https) {
r = setup_gnutls_logger(arg_gnutls_log);
if (r < 0)
- return EXIT_FAILURE;
+ return r;
}
if (arg_listen_https || https_socket >= 0) {
- if (load_certificates(&key, &cert, &trust) < 0)
- return EXIT_FAILURE;
+ r = load_certificates(&key, &cert, &trust);
+ if (r < 0)
+ return r;
+
s.check_trust = !arg_trust_all;
}
- if (create_remoteserver(&s, key, cert, trust) < 0)
- return EXIT_FAILURE;
+ r = create_remoteserver(&s, key, cert, trust);
+ if (r < 0)
+ return r;
r = sd_event_set_watchdog(s.events, true);
if (r < 0)
- log_error_errno(r, "Failed to enable watchdog: %m");
- else
- log_debug("Watchdog is %sd.", enable_disable(r > 0));
+ return log_error_errno(r, "Failed to enable watchdog: %m");
+
+ log_debug("Watchdog is %sd.", enable_disable(r > 0));
log_debug("%s running as pid "PID_FMT,
program_invocation_short_name, getpid_cached());
- sd_notify(false,
- "READY=1\n"
- "STATUS=Processing requests...");
+
+ notify_message = notify_start(NOTIFY_READY, NOTIFY_STOPPING);
while (s.active) {
r = sd_event_get_state(s.events);
if (r < 0)
- break;
+ return r;
if (r == SD_EVENT_FINISHED)
break;
r = sd_event_run(s.events, -1);
- if (r < 0) {
- log_error_errno(r, "Failed to run event loop: %m");
- break;
- }
+ if (r < 0)
+ return log_error_errno(r, "Failed to run event loop: %m");
}
- sd_notifyf(false,
- "STOPPING=1\n"
- "STATUS=Shutting down after writing %" PRIu64 " entries...", s.event_count);
- log_info("Finishing after writing %" PRIu64 " entries", s.event_count);
-
- journal_remote_server_destroy(&s);
+ notify_message = NULL;
+ (void) sd_notifyf(false,
+ "STOPPING=1\n"
+ "STATUS=Shutting down after writing %" PRIu64 " entries...", s.event_count);
- free(arg_key);
- free(arg_cert);
- free(arg_trust);
+ log_info("Finishing after writing %" PRIu64 " entries", s.event_count);
- return r >= 0 ? EXIT_SUCCESS : EXIT_FAILURE;
+ return 0;
}
+
+DEFINE_MAIN_FUNCTION(run);
}
#endif
-RemoteServer* journal_remote_server_destroy(RemoteServer *s) {
+void journal_remote_server_destroy(RemoteServer *s) {
size_t i;
#if HAVE_MICROHTTPD
journal_remote_server_global = NULL;
/* fds that we're listening on remain open... */
- return NULL;
}
/**********************************************************************
uint32_t revents,
RemoteServer *s);
-RemoteServer* journal_remote_server_destroy(RemoteServer *s);
+void journal_remote_server_destroy(RemoteServer *s);
#include "alloc-util.h"
#include "conf-parser.h"
+#include "daemon-util.h"
#include "def.h"
#include "env-file.h"
#include "fd-util.h"
#include "glob-util.h"
#include "journal-upload.h"
#include "log.h"
+#include "main-func.h"
#include "mkdir.h"
#include "parse-util.h"
#include "pretty-print.h"
return r;
}
-int main(int argc, char **argv) {
- Uploader u;
- int r;
+static int run(int argc, char **argv) {
+ _cleanup_(notify_on_cleanup) const char *notify_message = NULL;
+ _cleanup_(destroy_uploader) Uploader u = {};
bool use_journal;
+ int r;
log_show_color(true);
log_parse_environment();
r = parse_config();
if (r < 0)
- goto finish;
+ return r;
r = parse_argv(argc, argv);
if (r <= 0)
- goto finish;
+ return r;
sigbus_install();
r = setup_uploader(&u, arg_url, arg_save_state);
if (r < 0)
- goto cleanup;
+ return r;
sd_event_set_watchdog(u.events, true);
r = check_cursor_updating(&u);
if (r < 0)
- goto cleanup;
+ return r;
log_debug("%s running as pid "PID_FMT,
program_invocation_short_name, getpid_cached());
sd_journal *j;
r = open_journal(&j);
if (r < 0)
- goto finish;
+ return r;
r = open_journal_for_upload(&u, j,
arg_cursor ?: u.last_cursor,
arg_cursor ? arg_after_cursor : true,
!!arg_follow);
if (r < 0)
- goto finish;
+ return r;
}
- sd_notify(false,
- "READY=1\n"
- "STATUS=Processing input...");
+ notify_message = notify_start("READY=1\n"
+ "STATUS=Processing input...",
+ NOTIFY_STOPPING);
for (;;) {
r = sd_event_get_state(u.events);
if (r < 0)
- break;
+ return r;
if (r == SD_EVENT_FINISHED)
- break;
+ return 0;
if (use_journal) {
if (!u.journal)
- break;
+ return 0;
r = check_journal_input(&u);
} else if (u.input < 0 && !use_journal) {
if (optind >= argc)
- break;
+ return 0;
log_debug("Using %s as input.", argv[optind]);
r = open_file_for_upload(&u, argv[optind++]);
}
if (r < 0)
- goto cleanup;
+ return r;
if (u.uploading) {
r = perform_upload(&u);
if (r < 0)
- break;
+ return r;
}
r = sd_event_run(u.events, u.timeout);
- if (r < 0) {
- log_error_errno(r, "Failed to run event loop: %m");
- break;
- }
+ if (r < 0)
+ return log_error_errno(r, "Failed to run event loop: %m");
}
-
-cleanup:
- sd_notify(false,
- "STOPPING=1\n"
- "STATUS=Shutting down...");
-
- destroy_uploader(&u);
-
-finish:
- return r >= 0 ? EXIT_SUCCESS : EXIT_FAILURE;
}
+
+DEFINE_MAIN_FUNCTION(run);
* interesting events without overwhelming detail.
*/
int setup_gnutls_logger(char **categories);
+
+DEFINE_TRIVIAL_CLEANUP_FUNC(struct MHD_Daemon*, MHD_stop_daemon);
/* SPDX-License-Identifier: LGPL-2.1+ */
-#include <stdio.h>
-#include <linux/audit.h>
-#if HAVE_AUDIT
-# include <libaudit.h>
-#endif
-
-#include "missing.h"
#include "audit-type.h"
+#include "missing_audit.h"
+
#include "audit_type-to-name.h"
-#include "macro.h"
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
+#include <alloca.h>
+#include <stdio.h>
+
#include "macro.h"
const char *audit_type_to_string(int type);
############################################################
audit_type_includes = [config_h,
- missing_h,
+ missing_audit_h,
'linux/audit.h']
if conf.get('HAVE_AUDIT') == 1
audit_type_includes += 'libaudit.h'
#include <arpa/inet.h>
#include <linux/sockios.h>
+#include <sys/ioctl.h>
#include "sd-lldp.h"
#include "macro.h"
#include "socket-util.h"
#include "tests.h"
+#include "util.h"
#include "virt.h"
static struct ether_addr mac_addr = {
sd_daemon_c = files('sd-daemon/sd-daemon.c')
-sd_event_c = files('''
+sd_event_sources = files('''
sd-event/event-source.h
sd-event/event-util.c
sd-event/event-util.h
sd-path/sd-path.c
sd-resolve/sd-resolve.c
sd-utf8/sd-utf8.c
-'''.split()) + id128_sources + sd_daemon_c + sd_event_c + sd_login_c
+'''.split()) + id128_sources + sd_daemon_c + sd_event_sources + sd_login_c
disable_mempool_c = files('disable-mempool.c')
_cleanup_(sd_bus_message_unrefp) sd_bus_message *reply_unique = NULL, *reply = NULL;
_cleanup_(sd_bus_creds_unrefp) sd_bus_creds *c = NULL;
- const char *unique = NULL;
+ const char *unique;
pid_t pid = 0;
int r;
if (!BUS_IS_OPEN(bus->state))
return -ENOTCONN;
- /* Only query the owner if the caller wants to know it or if
- * the caller just wants to check whether a name exists */
- if ((mask & SD_BUS_CREDS_UNIQUE_NAME) || mask == 0) {
+ /* If the name is unique anyway, we can use it directly */
+ unique = name[0] == ':' ? name : NULL;
+
+ /* Only query the owner if the caller wants to know it and the name is not unique anyway, or if the caller just
+ * wants to check whether a name exists */
+ if ((FLAGS_SET(mask, SD_BUS_CREDS_UNIQUE_NAME) && !unique) || mask == 0) {
r = sd_bus_call_method(
bus,
"org.freedesktop.DBus",
if (mask != 0) {
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
bool need_pid, need_uid, need_selinux, need_separate_calls;
+
c = bus_creds_new();
if (!c)
return -ENOMEM;
NULL,
&reply,
"s",
- unique ? unique : name);
+ unique ?: name);
if (r < 0)
return r;
&error,
&reply,
"s",
- unique ? unique : name);
+ unique ?: name);
if (r < 0) {
if (!sd_bus_error_has_name(&error, "org.freedesktop.DBus.Error.SELinuxSecurityContextUnknown"))
return r;
if (r < 0)
return r;
- c->label = strndup(p, sz);
+ c->label = memdup_suffix0(p, sz);
if (!c->label)
return -ENOMEM;
/* SPDX-License-Identifier: LGPL-2.1+ */
+#include <sys/time.h>
+
#include "alloc-util.h"
#include "bus-dump.h"
#include "bus-internal.h"
#include "bus-slot.h"
#include "bus-type.h"
#include "bus-util.h"
+#include "missing_capability.h"
#include "set.h"
#include "string-util.h"
#include "strv.h"
#include "missing.h"
#include "path-util.h"
#include "process-util.h"
+#include "rlimit-util.h"
#include "selinux-util.h"
#include "signal-util.h"
#include "stdio-util.h"
if (rearrange_stdio(s[1], s[1], STDERR_FILENO) < 0)
_exit(EXIT_FAILURE);
+ (void) rlimit_nofile_safe();
+
if (b->exec_argv)
execvp(b->exec_path, b->exec_argv);
else {
#include "bus-util.h"
#include "def.h"
#include "fd-util.h"
+#include "missing_resource.h"
#include "time-util.h"
#include "util.h"
#include <ctype.h>
#include <net/if.h>
+#include <sys/ioctl.h>
#include <sys/types.h>
#include "sd-device.h"
};
static const struct NLType rtnl_prot_info_bridge_port_types[] = {
- [IFLA_BRPORT_STATE] = { .type = NETLINK_TYPE_U8 },
- [IFLA_BRPORT_COST] = { .type = NETLINK_TYPE_U32 },
- [IFLA_BRPORT_PRIORITY] = { .type = NETLINK_TYPE_U16 },
- [IFLA_BRPORT_MODE] = { .type = NETLINK_TYPE_U8 },
- [IFLA_BRPORT_GUARD] = { .type = NETLINK_TYPE_U8 },
- [IFLA_BRPORT_PROTECT] = { .type = NETLINK_TYPE_U8 },
- [IFLA_BRPORT_FAST_LEAVE] = { .type = NETLINK_TYPE_U8 },
- [IFLA_BRPORT_LEARNING] = { .type = NETLINK_TYPE_U8 },
- [IFLA_BRPORT_UNICAST_FLOOD] = { .type = NETLINK_TYPE_U8 },
- [IFLA_BRPORT_PROXYARP] = { .type = NETLINK_TYPE_U8 },
- [IFLA_BRPORT_LEARNING_SYNC] = { .type = NETLINK_TYPE_U8 },
+ [IFLA_BRPORT_STATE] = { .type = NETLINK_TYPE_U8 },
+ [IFLA_BRPORT_COST] = { .type = NETLINK_TYPE_U32 },
+ [IFLA_BRPORT_PRIORITY] = { .type = NETLINK_TYPE_U16 },
+ [IFLA_BRPORT_MODE] = { .type = NETLINK_TYPE_U8 },
+ [IFLA_BRPORT_GUARD] = { .type = NETLINK_TYPE_U8 },
+ [IFLA_BRPORT_PROTECT] = { .type = NETLINK_TYPE_U8 },
+ [IFLA_BRPORT_FAST_LEAVE] = { .type = NETLINK_TYPE_U8 },
+ [IFLA_BRPORT_LEARNING] = { .type = NETLINK_TYPE_U8 },
+ [IFLA_BRPORT_UNICAST_FLOOD] = { .type = NETLINK_TYPE_U8 },
+ [IFLA_BRPORT_PROXYARP] = { .type = NETLINK_TYPE_U8 },
+ [IFLA_BRPORT_LEARNING_SYNC] = { .type = NETLINK_TYPE_U8 },
+ [IFLA_BRPORT_PROXYARP_WIFI] = { .type = NETLINK_TYPE_U8 },
+ [IFLA_BRPORT_ROOT_ID] = { .type = NETLINK_TYPE_U8 },
+ [IFLA_BRPORT_BRIDGE_ID] = { .type = NETLINK_TYPE_U8 },
+ [IFLA_BRPORT_DESIGNATED_PORT] = { .type = NETLINK_TYPE_U16 },
+ [IFLA_BRPORT_DESIGNATED_COST] = { .type = NETLINK_TYPE_U16 },
+ [IFLA_BRPORT_ID] = { .type = NETLINK_TYPE_U16 },
+ [IFLA_BRPORT_NO] = { .type = NETLINK_TYPE_U16 },
+ [IFLA_BRPORT_TOPOLOGY_CHANGE_ACK] = { .type = NETLINK_TYPE_U8 },
+ [IFLA_BRPORT_CONFIG_PENDING] = { .type = NETLINK_TYPE_U8 },
+ [IFLA_BRPORT_MESSAGE_AGE_TIMER] = { .type = NETLINK_TYPE_U64 },
+ [IFLA_BRPORT_FORWARD_DELAY_TIMER] = { .type = NETLINK_TYPE_U64 },
+ [IFLA_BRPORT_HOLD_TIMER] = { .type = NETLINK_TYPE_U64 },
+ [IFLA_BRPORT_FLUSH] = { .type = NETLINK_TYPE_U8 },
+ [IFLA_BRPORT_MULTICAST_ROUTER] = { .type = NETLINK_TYPE_U8 },
+ [IFLA_BRPORT_PAD] = { .type = NETLINK_TYPE_U8 },
+ [IFLA_BRPORT_MCAST_FLOOD] = { .type = NETLINK_TYPE_U8 },
+ [IFLA_BRPORT_MCAST_TO_UCAST] = { .type = NETLINK_TYPE_U8 },
+ [IFLA_BRPORT_VLAN_TUNNEL] = { .type = NETLINK_TYPE_U8 },
+ [IFLA_BRPORT_BCAST_FLOOD] = { .type = NETLINK_TYPE_U8 },
+ [IFLA_BRPORT_GROUP_FWD_MASK] = { .type = NETLINK_TYPE_U16 },
+ [IFLA_BRPORT_NEIGH_SUPPRESS] = { .type = NETLINK_TYPE_U8 },
+ [IFLA_BRPORT_ISOLATED] = { .type = NETLINK_TYPE_U8 },
+ [IFLA_BRPORT_BACKUP_PORT] = { .type = NETLINK_TYPE_U32 },
};
static const NLTypeSystem rtnl_prot_info_type_systems[] = {
return 0;
}
+int sd_rtnl_message_routing_policy_rule_set_flags(sd_netlink_message *m, unsigned flags) {
+ struct rtmsg *routing_policy_rule;
+
+ assert_return(m, -EINVAL);
+ assert_return(m->hdr, -EINVAL);
+ assert_return(rtnl_message_type_is_routing_policy_rule(m->hdr->nlmsg_type), -EINVAL);
+
+ routing_policy_rule = NLMSG_DATA(m->hdr);
+ routing_policy_rule->rtm_flags |= flags;
+
+ return 0;
+}
+
+int sd_rtnl_message_routing_policy_rule_get_flags(sd_netlink_message *m, unsigned *flags) {
+ struct rtmsg *routing_policy_rule;
+
+ assert_return(m, -EINVAL);
+ assert_return(m->hdr, -EINVAL);
+ assert_return(rtnl_message_type_is_routing_policy_rule(m->hdr->nlmsg_type), -EINVAL);
+
+ routing_policy_rule = NLMSG_DATA(m->hdr);
+ *flags = routing_policy_rule->rtm_flags;
+
+ return 0;
+}
+
int sd_rtnl_message_routing_policy_rule_set_rtm_type(sd_netlink_message *m, unsigned char type) {
struct rtmsg *routing_policy_rule;
#include "macro.h"
#include "socket-util.h"
#include "string-util.h"
+#include "time-util.h"
#define TEST_TIMEOUT_USEC (20*USEC_PER_SEC)
if (fd < 0)
return log_error_errno(fd, "Failed to inhibit: %s", bus_error_message(&error, fd));
- r = safe_fork("(inhibit)", FORK_RESET_SIGNALS|FORK_DEATHSIG|FORK_CLOSE_ALL_FDS|FORK_LOG, &pid);
+ r = safe_fork("(inhibit)", FORK_RESET_SIGNALS|FORK_DEATHSIG|FORK_CLOSE_ALL_FDS|FORK_RLIMIT_NOFILE_SAFE|FORK_LOG, &pid);
if (r < 0)
return r;
if (r == 0) {
#include "io-util.h"
#include "loop-util.h"
#include "machine-image.h"
+#include "missing_capability.h"
#include "mount-util.h"
#include "process-util.h"
#include "raw-clone.h"
if (pipe2(errno_pipe_fd, O_CLOEXEC|O_NONBLOCK) < 0)
return sd_bus_error_set_errnof(error, errno, "Failed to create pipe: %m");
- r = safe_fork("(imgclone)", FORK_RESET_SIGNALS, &child);
+ r = safe_fork("(sd-imgclone)", FORK_RESET_SIGNALS, &child);
if (r < 0)
return sd_bus_error_set_errnof(error, r, "Failed to fork(): %m");
if (r == 0) {
#include "local-addresses.h"
#include "machine-dbus.h"
#include "machine.h"
+#include "missing_capability.h"
#include "mkdir.h"
#include "os-util.h"
#include "path-util.h"
#include "machine-image.h"
#include "machine-pool.h"
#include "machined.h"
+#include "missing_capability.h"
#include "path-util.h"
#include "process-util.h"
#include "stdio-util.h"
networkd-manager.h
networkd-ndisc.c
networkd-ndisc.h
+ networkd-neighbor.c
+ networkd-neighbor.h
networkd-radv.c
networkd-radv.h
networkd-network-bus.c
#endif
#include "in-addr-util.h"
-#include "missing.h"
+#include "missing_fou.h"
#include "netdev/netdev.h"
typedef enum FooOverUDPEncapType {
#include <linux/if_link.h>
-#include "missing.h"
+#include "missing_if_link.h"
#include "netdev/netdev.h"
typedef enum IPVlanMode {
Tunnel.IPv6RapidDeploymentPrefix, config_parse_6rd_prefix, 0, 0
Tunnel.ERSPANIndex, config_parse_uint32, 0, offsetof(Tunnel, erspan_index)
Tunnel.SerializeTunneledPackets, config_parse_tristate, 0, offsetof(Tunnel, erspan_sequence)
+Tunnel.ISATAP, config_parse_tristate, 0, offsetof(Tunnel, isatap)
FooOverUDP.Protocol, config_parse_uint8, 0, offsetof(FouTunnel, fou_protocol)
FooOverUDP.Encapsulation, config_parse_fou_encap_type, 0, offsetof(FouTunnel, fou_encap_type)
FooOverUDP.Port, config_parse_ip_port, 0, offsetof(FouTunnel, port)
r = sd_netlink_message_append_in6_addr(m, IFLA_IPTUN_6RD_PREFIX, &t->sixrd_prefix);
if (r < 0)
return log_netdev_error_errno(netdev, r, "Could not append IFLA_IPTUN_6RD_PREFIX attribute: %m");
+
/* u16 is deliberate here, even though we're passing a netmask that can never be >128. The kernel is
* expecting to receive the prefixlen as a u16.
*/
return log_netdev_error_errno(netdev, r, "Could not append IFLA_IPTUN_6RD_PREFIXLEN attribute: %m");
}
+ if (t->isatap >= 0) {
+ uint16_t flags = 0;
+
+ SET_FLAG(flags, SIT_ISATAP, t->isatap);
+
+ r = sd_netlink_message_append_u16(m, IFLA_IPTUN_FLAGS, flags);
+ if (r < 0)
+ return log_netdev_error_errno(netdev, r, "Could not append IFLA_IPTUN_FLAGS attribute: %m");
+ }
+
return r;
}
assert(t);
t->pmtudisc = true;
+ t->isatap = -1;
}
static void vti_init(NetDev *n) {
int ipv6_flowlabel;
int allow_localremote;
int erspan_sequence;
+ int isatap;
unsigned ttl;
unsigned tos;
#include "env-file.h"
#include "fd-util.h"
#include "fileio.h"
+#include "missing_network.h"
#include "netlink-util.h"
#include "network-internal.h"
#include "networkd-ipv6-proxy-ndp.h"
#include "networkd-lldp-tx.h"
#include "networkd-manager.h"
#include "networkd-ndisc.h"
+#include "networkd-neighbor.h"
#include "networkd-radv.h"
#include "networkd-routing-policy-rule.h"
#include "set.h"
assert(link);
assert(link->network);
- if (link->state != LINK_STATE_SETTING_ROUTES)
+ if (link->state != LINK_STATE_CONFIGURING)
return;
log_link_info(link, "Configured");
if (!link->network)
return;
+ if (!link->addresses_configured)
+ return;
+
+ if (!link->neighbors_configured)
+ return;
+
if (!link->static_routes_configured)
return;
assert(link);
assert(link->route_messages > 0);
- assert(IN_SET(link->state, LINK_STATE_SETTING_ADDRESSES,
- LINK_STATE_SETTING_ROUTES, LINK_STATE_FAILED,
- LINK_STATE_LINGER));
+ assert(IN_SET(link->state, LINK_STATE_CONFIGURING,
+ LINK_STATE_FAILED, LINK_STATE_LINGER));
link->route_messages--;
return 1;
}
-static int link_enter_set_routes(Link *link) {
+static int link_request_set_routes(Link *link) {
enum {
PHASE_NON_GATEWAY, /* First phase: Routes without a gateway */
PHASE_GATEWAY, /* Second phase: Routes with a gateway */
assert(link);
assert(link->network);
- assert(link->state == LINK_STATE_SETTING_ADDRESSES);
+ assert(link->addresses_configured);
+ assert(link->address_messages == 0);
+ assert(link->state != _LINK_STATE_INVALID);
- (void) link_set_routing_policy_rule(link);
+ link_set_state(link, LINK_STATE_CONFIGURING);
- link_set_state(link, LINK_STATE_SETTING_ROUTES);
+ (void) link_set_routing_policy_rule(link);
/* First add the routes that enable us to talk to gateways, then add in the others that need a gateway. */
for (phase = 0; phase < _PHASE_MAX; phase++)
return 0;
}
+static int link_request_set_neighbors(Link *link) {
+ Neighbor *neighbor;
+ int r;
+
+ assert(link);
+ assert(link->network);
+ assert(link->state != _LINK_STATE_INVALID);
+
+ link_set_state(link, LINK_STATE_CONFIGURING);
+
+ LIST_FOREACH(neighbors, neighbor, link->network->neighbors) {
+ r = neighbor_configure(neighbor, link, NULL);
+ if (r < 0) {
+ log_link_warning_errno(link, r, "Could not set neighbor: %m");
+ link_enter_failed(link);
+ return r;
+ }
+ }
+
+ if (link->neighbor_messages == 0) {
+ link->neighbors_configured = true;
+ link_check_ready(link);
+ } else
+ log_link_debug(link, "Setting neighbors");
+
+ return 0;
+}
+
static int address_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
int r;
assert(link);
assert(link->ifname);
assert(link->address_messages > 0);
- assert(IN_SET(link->state, LINK_STATE_SETTING_ADDRESSES,
+ assert(IN_SET(link->state, LINK_STATE_CONFIGURING,
LINK_STATE_FAILED, LINK_STATE_LINGER));
link->address_messages--;
if (link->address_messages == 0) {
log_link_debug(link, "Addresses set");
- link_enter_set_routes(link);
+ link->addresses_configured = true;
+ link_request_set_routes(link);
}
return 1;
return 0;
}
-static int link_enter_set_addresses(Link *link) {
+static int link_request_set_addresses(Link *link) {
AddressLabel *label;
Address *ad;
int r;
if (r < 0)
return r;
- link_set_state(link, LINK_STATE_SETTING_ADDRESSES);
+ link_set_state(link, LINK_STATE_CONFIGURING);
+
+ link_request_set_neighbors(link);
LIST_FOREACH(addresses, ad, link->network->static_addresses) {
r = address_configure(ad, link, address_handler, false);
log_link_debug(link, "Offering DHCPv4 leases");
}
- if (link->address_messages == 0)
- link_enter_set_routes(link);
- else
+ if (link->address_messages == 0) {
+ link->addresses_configured = true;
+ link_request_set_routes(link);
+ } else
log_link_debug(link, "Setting addresses");
return 0;
r = sd_netlink_message_append_u8(req, IFLA_BRPORT_UNICAST_FLOOD, link->network->unicast_flood);
if (r < 0)
return log_link_error_errno(link, r, "Could not append IFLA_BRPORT_UNICAST_FLOOD attribute: %m");
+ }
+ if (link->network->multicast_to_unicast >= 0) {
+ r = sd_netlink_message_append_u8(req, IFLA_BRPORT_MCAST_TO_UCAST, link->network->multicast_to_unicast);
+ if (r < 0)
+ return log_link_error_errno(link, r, "Could not append IFLA_BRPORT_MCAST_TO_UCAST attribute: %m");
}
if (link->network->cost != 0) {
if (r < 0)
return log_link_error_errno(link, r, "Could not append IFLA_BRPORT_COST attribute: %m");
}
+
if (link->network->priority != LINK_BRIDGE_PORT_PRIORITY_INVALID) {
r = sd_netlink_message_append_u16(req, IFLA_BRPORT_PRIORITY, link->network->priority);
if (r < 0)
if (!link_has_carrier(link) && !link->network->configure_without_carrier)
return 0;
- return link_enter_set_addresses(link);
+ return link_request_set_addresses(link);
}
static int netdev_join_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
assert(link->network);
assert(link->state == LINK_STATE_PENDING);
- link_set_state(link, LINK_STATE_ENSLAVING);
+ link_set_state(link, LINK_STATE_CONFIGURING);
link_dirty(link);
return r;
}
- r = link_enter_set_addresses(link);
+ r = link_request_set_addresses(link);
if (r < 0)
return r;
}
if (link->state == LINK_STATE_LINGER) {
log_link_info(link, "Link readded");
- link_set_state(link, LINK_STATE_ENSLAVING);
+ link_set_state(link, LINK_STATE_CONFIGURING);
r = link_new_carrier_maps(link);
if (r < 0)
static const char* const link_state_table[_LINK_STATE_MAX] = {
[LINK_STATE_PENDING] = "pending",
- [LINK_STATE_ENSLAVING] = "configuring",
- [LINK_STATE_SETTING_ADDRESSES] = "configuring",
- [LINK_STATE_SETTING_ROUTES] = "configuring",
+ [LINK_STATE_CONFIGURING] = "configuring",
[LINK_STATE_CONFIGURED] = "configured",
[LINK_STATE_UNMANAGED] = "unmanaged",
[LINK_STATE_FAILED] = "failed",
typedef enum LinkState {
LINK_STATE_PENDING,
- LINK_STATE_ENSLAVING,
- LINK_STATE_SETTING_ADDRESSES,
- LINK_STATE_SETTING_ROUTES,
+ LINK_STATE_CONFIGURING,
LINK_STATE_CONFIGURED,
LINK_STATE_UNMANAGED,
LINK_STATE_FAILED,
unsigned address_messages;
unsigned address_label_messages;
+ unsigned neighbor_messages;
unsigned route_messages;
unsigned routing_policy_rule_messages;
unsigned routing_policy_rule_remove_messages;
Set *routes;
Set *routes_foreign;
+ bool addresses_configured;
+
sd_dhcp_client *dhcp_client;
sd_dhcp_lease *dhcp_lease;
char *lease_file;
bool ipv4ll_address:1;
bool ipv4ll_route:1;
+ bool neighbors_configured;
+
bool static_routes_configured;
bool routing_policy_rules_configured;
bool setting_mtu;
#include "env-file.h"
#include "fd-util.h"
#include "hostname-util.h"
+#include "missing_network.h"
#include "networkd-lldp-tx.h"
#include "networkd-manager.h"
#include "parse-util.h"
--- /dev/null
+/* SPDX-License-Identifier: LGPL-2.1+ */
+
+#include "sd-netlink.h"
+
+#include "alloc-util.h"
+#include "conf-parser.h"
+#include "ether-addr-util.h"
+#include "hashmap.h"
+#include "in-addr-util.h"
+#include "netlink-util.h"
+#include "networkd-link.h"
+#include "networkd-manager.h"
+#include "networkd-neighbor.h"
+
+void neighbor_free(Neighbor *neighbor) {
+ if (!neighbor)
+ return;
+
+ if (neighbor->network) {
+ LIST_REMOVE(neighbors, neighbor->network->neighbors, neighbor);
+ assert(neighbor->network->n_neighbors > 0);
+ neighbor->network->n_neighbors--;
+
+ if (neighbor->section) {
+ hashmap_remove(neighbor->network->neighbors_by_section, neighbor->section);
+ network_config_section_free(neighbor->section);
+ }
+ }
+
+ free(neighbor);
+}
+
+static int neighbor_new_static(Network *network, const char *filename, unsigned section_line, Neighbor **ret) {
+ _cleanup_(network_config_section_freep) NetworkConfigSection *n = NULL;
+ _cleanup_(neighbor_freep) Neighbor *neighbor = NULL;
+ int r;
+
+ assert(network);
+ assert(ret);
+ assert(!!filename == (section_line > 0));
+
+ if (filename) {
+ r = network_config_section_new(filename, section_line, &n);
+ if (r < 0)
+ return r;
+
+ neighbor = hashmap_get(network->neighbors_by_section, n);
+ if (neighbor) {
+ *ret = TAKE_PTR(neighbor);
+
+ return 0;
+ }
+ }
+
+ neighbor = new(Neighbor, 1);
+ if (!neighbor)
+ return -ENOMEM;
+
+ *neighbor = (Neighbor) {
+ .network = network,
+ .family = AF_UNSPEC,
+ };
+
+ LIST_APPEND(neighbors, network->neighbors, neighbor);
+ network->n_neighbors++;
+
+ if (filename) {
+ neighbor->section = TAKE_PTR(n);
+
+ r = hashmap_ensure_allocated(&network->neighbors_by_section, &network_config_hash_ops);
+ if (r < 0)
+ return r;
+
+ r = hashmap_put(network->neighbors_by_section, neighbor->section, neighbor);
+ if (r < 0)
+ return r;
+ }
+
+ *ret = TAKE_PTR(neighbor);
+
+ return 0;
+}
+
+static int neighbor_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
+ int r;
+
+ assert(link);
+ assert(link->neighbor_messages > 0);
+
+ link->neighbor_messages--;
+
+ if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
+ return 1;
+
+ r = sd_netlink_message_get_errno(m);
+ if (r < 0 && r != -EEXIST)
+ log_link_warning_errno(link, r, "Could not set neighbor: %m");
+
+ if (link->neighbor_messages == 0) {
+ log_link_debug(link, "Neighbors set");
+ link->neighbors_configured = true;
+ link_check_ready(link);
+ }
+
+ return 1;
+}
+
+int neighbor_configure(Neighbor *neighbor, Link *link, link_netlink_message_handler_t callback) {
+ _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL;
+ int r;
+
+ assert(neighbor);
+ assert(link);
+ assert(link->ifindex > 0);
+ assert(link->manager);
+ assert(link->manager->rtnl);
+
+ if (neighbor->family == AF_UNSPEC)
+ return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Neighbor without Address= configured");
+ if (!neighbor->mac_configured)
+ return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Neighbor without MACAddress= configured");
+
+ r = sd_rtnl_message_new_neigh(link->manager->rtnl, &req, RTM_NEWNEIGH,
+ link->ifindex, neighbor->family);
+ if (r < 0)
+ return log_error_errno(r, "Could not allocate RTM_NEWNEIGH message: %m");
+
+ r = sd_rtnl_message_neigh_set_state(req, NUD_PERMANENT);
+ if (r < 0)
+ return log_error_errno(r, "Could not set state: %m");
+
+ r = sd_netlink_message_set_flags(req, NLM_F_REQUEST | NLM_F_CREATE | NLM_F_REPLACE);
+ if (r < 0)
+ return log_error_errno(r, "Could not set flags: %m");
+
+ r = sd_netlink_message_append_ether_addr(req, NDA_LLADDR, &neighbor->mac);
+ if (r < 0)
+ return log_error_errno(r, "Could not append NDA_LLADDR attribute: %m");
+
+ switch (neighbor->family) {
+ case AF_INET6:
+ r = sd_netlink_message_append_in6_addr(req, NDA_DST, &neighbor->in_addr.in6);
+ if (r < 0)
+ return log_error_errno(r, "Could not append NDA_DST attribute: %m");
+ break;
+ case AF_INET:
+ r = sd_netlink_message_append_in_addr(req, NDA_DST, &neighbor->in_addr.in);
+ if (r < 0)
+ return log_error_errno(r, "Could not append NDA_DST attribute: %m");
+ break;
+ default:
+ return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Neighbor with invalid address family");
+ }
+
+ r = netlink_call_async(link->manager->rtnl, NULL, req, callback ?: neighbor_handler,
+ link_netlink_destroy_callback, link);
+ if (r < 0)
+ return log_error_errno(r, "Could not send rtnetlink message: %m");
+
+ link->neighbor_messages++;
+ link_ref(link);
+
+ return 0;
+}
+
+int config_parse_neighbor_address(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_(neighbor_freep) Neighbor *n = NULL;
+ int r;
+
+ assert(filename);
+ assert(section);
+ assert(lvalue);
+ assert(rvalue);
+ assert(data);
+
+ r = neighbor_new_static(network, filename, section_line, &n);
+ if (r < 0)
+ return r;
+
+ r = in_addr_from_string_auto(rvalue, &n->family, &n->in_addr);
+ if (r < 0) {
+ log_syntax(unit, LOG_ERR, filename, line, r, "Neighbor Address is invalid, ignoring assignment: %s", rvalue);
+ return 0;
+ }
+
+ TAKE_PTR(n);
+
+ return 0;
+}
+
+int config_parse_neighbor_hwaddr(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_(neighbor_freep) Neighbor *n = NULL;
+ int r;
+
+ assert(filename);
+ assert(section);
+ assert(lvalue);
+ assert(rvalue);
+ assert(data);
+
+ r = neighbor_new_static(network, filename, section_line, &n);
+ if (r < 0)
+ return r;
+
+ r = ether_addr_from_string(rvalue, &n->mac);
+ if (r < 0) {
+ log_syntax(unit, LOG_ERR, filename, line, r, "Neighbor MACAddress is invalid, ignoring assignment: %s", rvalue);
+ return 0;
+ }
+
+ n->mac_configured = true;
+ TAKE_PTR(n);
+
+ return 0;
+}
--- /dev/null
+/* SPDX-License-Identifier: LGPL-2.1+ */
+#pragma once
+
+#include "sd-netlink.h"
+
+#include "conf-parser.h"
+#include "ether-addr-util.h"
+#include "in-addr-util.h"
+#include "list.h"
+#include "macro.h"
+
+typedef struct Neighbor Neighbor;
+
+#include "networkd-link.h"
+#include "networkd-network.h"
+
+struct Neighbor {
+ Network *network;
+ Link *link;
+ NetworkConfigSection *section;
+
+ int family;
+ union in_addr_union in_addr;
+ bool mac_configured;
+ struct ether_addr mac;
+
+ LIST_FIELDS(Neighbor, neighbors);
+};
+
+void neighbor_free(Neighbor *neighbor);
+
+DEFINE_TRIVIAL_CLEANUP_FUNC(Neighbor*, neighbor_free);
+
+int neighbor_configure(Neighbor *neighbor, Link *link, link_netlink_message_handler_t callback);
+
+CONFIG_PARSER_PROTOTYPE(config_parse_neighbor_address);
+CONFIG_PARSER_PROTOTYPE(config_parse_neighbor_hwaddr);
Address.Scope, config_parse_address_scope, 0, 0
IPv6AddressLabel.Prefix, config_parse_address_label_prefix, 0, 0
IPv6AddressLabel.Label, config_parse_address_label, 0, 0
+Neighbor.Address, config_parse_neighbor_address, 0, 0
+Neighbor.MACAddress, config_parse_neighbor_hwaddr, 0, 0
RoutingPolicyRule.TypeOfService, config_parse_routing_policy_rule_tos, 0, 0
RoutingPolicyRule.Priority, config_parse_routing_policy_rule_priority, 0, 0
RoutingPolicyRule.Table, config_parse_routing_policy_rule_table, 0, 0
RoutingPolicyRule.IPProtocol, config_parse_routing_policy_rule_ip_protocol, 0, 0
RoutingPolicyRule.SourcePort, config_parse_routing_policy_rule_port_range, 0, 0
RoutingPolicyRule.DestinationPort, config_parse_routing_policy_rule_port_range, 0, 0
+RoutingPolicyRule.InvertRule, config_parse_routing_policy_rule_invert, 0, 0
Route.Gateway, config_parse_gateway, 0, 0
Route.Destination, config_parse_destination, 0, 0
Route.Source, config_parse_destination, 0, 0
Bridge.FastLeave, config_parse_tristate, 0, offsetof(Network, fast_leave)
Bridge.AllowPortToBeRoot, config_parse_tristate, 0, offsetof(Network, allow_port_to_be_root)
Bridge.UnicastFlood, config_parse_tristate, 0, offsetof(Network, unicast_flood)
+Bridge.MulticastToUnicast, config_parse_tristate, 0, offsetof(Network, multicast_to_unicast)
Bridge.Priority, config_parse_bridge_port_priority, 0, offsetof(Network, priority)
BridgeFDB.MACAddress, config_parse_fdb_hwaddr, 0, 0
BridgeFDB.VLANId, config_parse_fdb_vlan_id, 0, 0
.fast_leave = -1,
.allow_port_to_be_root = -1,
.unicast_flood = -1,
+ .multicast_to_unicast = -1,
.priority = LINK_BRIDGE_PORT_PRIORITY_INVALID,
.lldp_mode = LLDP_MODE_ROUTERS_ONLY,
"Link\0"
"Network\0"
"Address\0"
+ "Neighbor\0"
"IPv6AddressLabel\0"
"RoutingPolicyRule\0"
"Route\0"
IPv6ProxyNDPAddress *ipv6_proxy_ndp_address;
RoutingPolicyRule *rule;
FdbEntry *fdb_entry;
+ Neighbor *neighbor;
AddressLabel *label;
Prefix *prefix;
Address *address;
while ((ipv6_proxy_ndp_address = network->ipv6_proxy_ndp_addresses))
ipv6_proxy_ndp_address_free(ipv6_proxy_ndp_address);
+ while ((neighbor = network->neighbors))
+ neighbor_free(neighbor);
+
while ((label = network->address_labels))
address_label_free(label);
hashmap_free(network->addresses_by_section);
hashmap_free(network->routes_by_section);
hashmap_free(network->fdb_entries_by_section);
+ hashmap_free(network->neighbors_by_section);
hashmap_free(network->address_labels_by_section);
hashmap_free(network->prefixes_by_section);
hashmap_free(network->rules_by_section);
#include "networkd-fdb.h"
#include "networkd-ipv6-proxy-ndp.h"
#include "networkd-lldp-tx.h"
+#include "networkd-neighbor.h"
#include "networkd-radv.h"
#include "networkd-route.h"
#include "networkd-routing-policy-rule.h"
int fast_leave;
int allow_port_to_be_root;
int unicast_flood;
+ int multicast_to_unicast;
uint32_t cost;
uint16_t priority;
LIST_HEAD(Route, static_routes);
LIST_HEAD(FdbEntry, static_fdb_entries);
LIST_HEAD(IPv6ProxyNDPAddress, ipv6_proxy_ndp_addresses);
+ LIST_HEAD(Neighbor, neighbors);
LIST_HEAD(AddressLabel, address_labels);
LIST_HEAD(Prefix, static_prefixes);
LIST_HEAD(RoutingPolicyRule, rules);
unsigned n_static_routes;
unsigned n_static_fdb_entries;
unsigned n_ipv6_proxy_ndp_addresses;
+ unsigned n_neighbors;
unsigned n_address_labels;
unsigned n_static_prefixes;
unsigned n_rules;
Hashmap *addresses_by_section;
Hashmap *routes_by_section;
Hashmap *fdb_entries_by_section;
+ Hashmap *neighbors_by_section;
Hashmap *address_labels_by_section;
Hashmap *prefixes_by_section;
Hashmap *rules_by_section;
return log_error_errno(r, "Could not append FRA_DPORT_RANGE attribute: %m");
}
+ if (rule->invert_rule) {
+ r = sd_rtnl_message_routing_policy_rule_set_flags(m, FIB_RULE_INVERT);
+ if (r < 0)
+ return log_error_errno(r, "Could not append FIB_RULE_INVERT attribute: %m");
+ }
+
rule->link = link;
r = netlink_call_async(link->manager->rtnl, NULL, m,
return 0;
}
+int config_parse_routing_policy_rule_invert(
+ const char *unit,
+ const char *filename,
+ unsigned line,
+ const char *section,
+ unsigned section_line,
+ const char *lvalue,
+ int ltype,
+ const char *rvalue,
+ void *data,
+ void *userdata) {
+
+ _cleanup_(routing_policy_rule_freep) RoutingPolicyRule *n = NULL;
+ Network *network = userdata;
+ int r;
+
+ assert(filename);
+ assert(section);
+ assert(lvalue);
+ assert(rvalue);
+ assert(data);
+
+ r = routing_policy_rule_new_static(network, filename, section_line, &n);
+ if (r < 0)
+ return r;
+
+ r = parse_boolean(rvalue);
+ if (r < 0) {
+ log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse RPDB rule invert, ignoring: %s", rvalue);
+ return 0;
+ }
+
+ n->invert_rule = r;
+
+ n = NULL;
+
+ return 0;
+}
+
static int routing_policy_rule_read_full_file(const char *state_file, char **ret) {
_cleanup_free_ char *s = NULL;
size_t size;
Link *link;
NetworkConfigSection *section;
+ bool invert_rule;
+
uint8_t tos;
uint8_t protocol;
CONFIG_PARSER_PROTOTYPE(config_parse_routing_policy_rule_device);
CONFIG_PARSER_PROTOTYPE(config_parse_routing_policy_rule_port_range);
CONFIG_PARSER_PROTOTYPE(config_parse_routing_policy_rule_ip_protocol);
+CONFIG_PARSER_PROTOTYPE(config_parse_routing_policy_rule_invert);
#include "sd-event.h"
#include "capability-util.h"
+#include "daemon-util.h"
+#include "main-func.h"
#include "mkdir.h"
#include "networkd-conf.h"
#include "networkd-manager.h"
#include "signal-util.h"
#include "user-util.h"
-int main(int argc, char *argv[]) {
+static int run(int argc, char *argv[]) {
+ _cleanup_(notify_on_cleanup) const char *notify_message = NULL;
_cleanup_(manager_freep) Manager *m = NULL;
const char *user = "systemd-network";
uid_t uid;
umask(0022);
- if (argc != 1) {
- log_error("This program takes no arguments.");
- r = -EINVAL;
- goto out;
- }
+ if (argc != 1)
+ return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "This program takes no arguments.");
r = get_user_creds(&user, &uid, &gid, NULL, NULL, 0);
- if (r < 0) {
- log_error_errno(r, "Cannot resolve user name %s: %m", user);
- goto out;
- }
+ if (r < 0)
+ return log_error_errno(r, "Cannot resolve user name %s: %m", user);
/* Create runtime directory. This is not necessary when networkd is
* started with "RuntimeDirectory=systemd/netif", or after
(1ULL << CAP_NET_BROADCAST) |
(1ULL << CAP_NET_RAW));
if (r < 0)
- goto out;
+ return log_error_errno(r, "Failed to drop privileges: %m");
}
/* Always create the directories people can create inotify watches in.
assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGTERM, SIGINT, -1) >= 0);
r = manager_new(&m);
- if (r < 0) {
- log_error_errno(r, "Could not create manager: %m");
- goto out;
- }
+ if (r < 0)
+ return log_error_errno(r, "Could not create manager: %m");
r = manager_connect_bus(m);
- if (r < 0) {
- log_error_errno(r, "Could not connect to bus: %m");
- goto out;
- }
+ if (r < 0)
+ return log_error_errno(r, "Could not connect to bus: %m");
r = manager_parse_config_file(m);
if (r < 0)
log_warning_errno(r, "Failed to parse configuration file: %m");
r = manager_load_config(m);
- if (r < 0) {
- log_error_errno(r, "Could not load configuration files: %m");
- goto out;
- }
+ if (r < 0)
+ return log_error_errno(r, "Could not load configuration files: %m");
r = manager_rtnl_enumerate_links(m);
- if (r < 0) {
- log_error_errno(r, "Could not enumerate links: %m");
- goto out;
- }
+ if (r < 0)
+ return log_error_errno(r, "Could not enumerate links: %m");
r = manager_rtnl_enumerate_addresses(m);
- if (r < 0) {
- log_error_errno(r, "Could not enumerate addresses: %m");
- goto out;
- }
+ if (r < 0)
+ return log_error_errno(r, "Could not enumerate addresses: %m");
r = manager_rtnl_enumerate_routes(m);
- if (r < 0) {
- log_error_errno(r, "Could not enumerate routes: %m");
- goto out;
- }
+ if (r < 0)
+ return log_error_errno(r, "Could not enumerate routes: %m");
r = manager_rtnl_enumerate_rules(m);
- if (r < 0) {
- log_error_errno(r, "Could not enumerate rules: %m");
- goto out;
- }
+ if (r < 0)
+ return log_error_errno(r, "Could not enumerate rules: %m");
r = manager_start(m);
- if (r < 0) {
- log_error_errno(r, "Could not start manager: %m");
- goto out;
- }
+ if (r < 0)
+ return log_error_errno(r, "Could not start manager: %m");
log_info("Enumeration completed");
- sd_notify(false,
- "READY=1\n"
- "STATUS=Processing requests...");
+ notify_message = notify_start(NOTIFY_READY, NOTIFY_STOPPING);
r = sd_event_loop(m->event);
- if (r < 0) {
- log_error_errno(r, "Event loop failed: %m");
- goto out;
- }
-out:
- sd_notify(false,
- "STOPPING=1\n"
- "STATUS=Shutting down...");
+ if (r < 0)
+ return log_error_errno(r, "Event loop failed: %m");
- return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
+ return 0;
}
+
+DEFINE_MAIN_FUNCTION(run);
#include "sd-daemon.h"
+#include "daemon-util.h"
+#include "main-func.h"
#include "manager.h"
#include "pretty-print.h"
#include "signal-util.h"
static char **arg_interfaces = NULL;
static char **arg_ignore = NULL;
+STATIC_DESTRUCTOR_REGISTER(arg_interfaces, strv_freep);
+STATIC_DESTRUCTOR_REGISTER(arg_ignore, strv_freep);
+
static int help(void) {
_cleanup_free_ char *link = NULL;
int r;
return 1;
}
-int main(int argc, char *argv[]) {
+static int run(int argc, char *argv[]) {
+ _cleanup_(notify_on_cleanup) const char *notify_message = NULL;
_cleanup_(manager_freep) Manager *m = NULL;
int r;
assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGTERM, SIGINT, -1) >= 0);
r = manager_new(&m, arg_interfaces, arg_ignore, arg_timeout);
- if (r < 0) {
- log_error_errno(r, "Could not create manager: %m");
- goto finish;
- }
+ if (r < 0)
+ return log_error_errno(r, "Could not create manager: %m");
- if (manager_all_configured(m)) {
- r = 0;
- goto finish;
- }
+ if (manager_all_configured(m))
+ goto success;
- sd_notify(false,
- "READY=1\n"
- "STATUS=Waiting for network connections...");
+ notify_message = notify_start("READY=1\n"
+ "STATUS=Waiting for network connections...",
+ "STATUS=Failed to wait for network connectivity...");
r = sd_event_loop(m->event);
- if (r < 0) {
- log_error_errno(r, "Event loop failed: %m");
- goto finish;
- }
-
-finish:
- strv_free(arg_interfaces);
- strv_free(arg_ignore);
-
- if (r >= 0) {
- sd_notify(false, "STATUS=All interfaces configured...");
+ if (r < 0)
+ return log_error_errno(r, "Event loop failed: %m");
- return EXIT_SUCCESS;
- } else {
- sd_notify(false, "STATUS=Failed waiting for network connectivity...");
+success:
+ notify_message = "STATUS=All interfaces configured...";
- return EXIT_FAILURE;
- }
+ return 0;
}
+
+DEFINE_MAIN_FUNCTION(run);
#include "alloc-util.h"
#include "ether-addr-util.h"
#include "lockfile-util.h"
+#include "missing_network.h"
#include "netlink-util.h"
#include "nspawn-network.h"
#include "siphash24.h"
#include "conf-parser.h"
#include "macro.h"
-#include "missing.h"
+#include "missing_resource.h"
#include "nspawn-expose-ports.h"
#include "nspawn-mount.h"
#include "mkdir.h"
#include "nspawn-setuid.h"
#include "process-util.h"
+#include "rlimit-util.h"
#include "signal-util.h"
#include "string-util.h"
#include "strv.h"
close_all_fds(NULL, 0);
+ (void) rlimit_nofile_safe();
+
execle("/usr/bin/getent", "getent", database, key, NULL, &empty_env);
execle("/bin/getent", "getent", database, key, NULL, &empty_env);
_exit(EXIT_FAILURE);
#include <errno.h>
#include <getopt.h>
#include <grp.h>
+#include <linux/fs.h>
#include <linux/loop.h>
#include <pwd.h>
#include <sched.h>
#include <stdlib.h>
#include <string.h>
#include <sys/file.h>
-#include <sys/mount.h>
#include <sys/personality.h>
#include <sys/prctl.h>
#include <sys/types.h>
if (access(mkfs, X_OK) != 0)
return log_error_errno(errno, "%s is not executable: %m", mkfs);
- r = safe_fork("(fsck)", FORK_RESET_SIGNALS|FORK_DEATHSIG|FORK_LOG, &pid);
+ r = safe_fork("(mkfs)", FORK_RESET_SIGNALS|FORK_DEATHSIG|FORK_RLIMIT_NOFILE_SAFE|FORK_LOG, &pid);
if (r < 0)
return r;
if (r == 0) {
#include "fd-util.h"
#include "io-util.h"
#include "machine-image.h"
+#include "missing_capability.h"
#include "portable.h"
#include "portabled-bus.h"
#include "portabled-image-bus.h"
#include "fileio.h"
#include "io-util.h"
#include "machine-image.h"
+#include "missing_capability.h"
#include "portable.h"
#include "portabled-bus.h"
#include "portabled-image-bus.h"
return 0;
}
- r = safe_fork("(quotacheck)", FORK_RESET_SIGNALS|FORK_DEATHSIG|FORK_LOG|FORK_WAIT, NULL);
+ r = safe_fork("(quotacheck)", FORK_RESET_SIGNALS|FORK_DEATHSIG|FORK_RLIMIT_NOFILE_SAFE|FORK_WAIT|FORK_LOG, NULL);
if (r < 0)
return r;
if (r == 0) {
static int add_symlink(const char *service, const char *where) {
const char *from, *to;
- int r;
assert(service);
assert(where);
(void) mkdir_parents_label(to, 0755);
- r = symlink(from, to);
- if (r < 0) {
+ if (symlink(from, to) < 0) {
if (errno == EEXIST)
return 0;
return 1;
}
+static int check_executable(const char *path) {
+ assert(path);
+
+ if (access(path, X_OK) < 0) {
+ if (errno == ENOENT)
+ return log_debug_errno(errno, "%s does not exist, skipping.", path);
+ if (errno == EACCES)
+ return log_info_errno(errno, "%s is not marked executable, skipping.", path);
+
+ return log_warning_errno(errno, "Couldn't determine if %s exists and is executable, skipping: %m", path);
+ }
+
+ return 0;
+}
+
static int run(int argc, char *argv[]) {
int r = 0, k = 0;
if (argc > 1)
arg_dest = argv[1];
- if (access(RC_LOCAL_SCRIPT_PATH_START, X_OK) < 0)
- log_full_errno(errno == ENOENT ? LOG_DEBUG : LOG_WARNING, errno,
- RC_LOCAL_SCRIPT_PATH_START " is not executable: %m");
- else {
+ if (check_executable(RC_LOCAL_SCRIPT_PATH_START) >= 0) {
log_debug("Automatically adding rc-local.service.");
r = add_symlink("rc-local.service", "multi-user.target");
}
- if (access(RC_LOCAL_SCRIPT_PATH_STOP, X_OK) < 0)
- log_full_errno(errno == ENOENT ? LOG_DEBUG : LOG_WARNING, errno,
- RC_LOCAL_SCRIPT_PATH_STOP " is not executable: %m");
- else {
+ if (check_executable(RC_LOCAL_SCRIPT_PATH_STOP) >= 0) {
log_debug("Automatically adding halt-local.service.");
k = add_symlink("halt-local.service", "final.target");
log_debug("Remounting %s", me->mnt_dir);
- r = safe_fork("(remount)", FORK_RESET_SIGNALS|FORK_DEATHSIG|FORK_LOG, &pid);
+ r = safe_fork("(remount)", FORK_RESET_SIGNALS|FORK_DEATHSIG|FORK_RLIMIT_NOFILE_SAFE|FORK_LOG, &pid);
if (r < 0)
return r;
if (r == 0) {
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
"Expected interface name as argument.");
- r = ifname_mangle(argv[optind], false);
+ r = ifname_mangle(argv[optind]);
if (r <= 0)
return r;
#include "gcrypt-util.h"
#include "in-addr-util.h"
#include "main-func.h"
-#include "missing.h"
+#include "missing_network.h"
#include "netlink-util.h"
#include "pager.h"
#include "parse-util.h"
return ifi;
}
-int ifname_mangle(const char *s, bool allow_loopback) {
+int ifname_mangle(const char *s) {
_cleanup_free_ char *iface = NULL;
const char *dot;
- int r;
+ int ifi;
assert(s);
- if (arg_ifname) {
- assert(arg_ifindex >= 0);
-
- if (!allow_loopback && arg_ifindex == LOOPBACK_IFINDEX)
- return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
- "Interface can't be the loopback interface (lo). Sorry.");
-
- return 1;
- }
-
dot = strchr(s, '.');
if (dot) {
+ log_debug("Ignoring protocol specifier '%s'.", dot + 1);
iface = strndup(s, dot - s);
- if (!iface)
- return log_oom();
- log_debug("Ignoring protocol specifier '%s'.", dot + 1);
- } else {
+ } else
iface = strdup(s);
- if (!iface)
- return log_oom();
- }
+ if (!iface)
+ return log_oom();
- if (parse_ifindex(iface, &r) < 0) {
- r = if_nametoindex(iface);
- if (r <= 0) {
+ if (parse_ifindex(iface, &ifi) < 0) {
+ ifi = if_nametoindex(iface);
+ if (ifi <= 0) {
if (errno == ENODEV && arg_ifindex_permissive) {
log_debug("Interface '%s' not found, but -f specified, ignoring.", iface);
return 0; /* done */
}
}
- if (!allow_loopback && r == LOOPBACK_IFINDEX)
- return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
- "Interface can't be the loopback interface (lo). Sorry.");
+ if (arg_ifindex > 0 && arg_ifindex != ifi) {
+ log_error("Specified multiple different interfaces. Refusing.");
+ return -EINVAL;
+ }
- arg_ifindex = r;
- arg_ifname = TAKE_PTR(iface);
+ arg_ifindex = ifi;
+ free_and_replace(arg_ifname, iface);
return 1;
}
if (flags == 0)
return;
- fputs("\n-- Information acquired via", stdout);
+ printf("\n%s-- Information acquired via", ansi_grey());
if (flags != 0)
printf(" protocol%s%s%s%s%s",
assert_se(format_timespan(rtt_str, sizeof(rtt_str), rtt, 100));
- printf(" in %s", rtt_str);
+ printf(" in %s.%s\n"
+ "%s-- Data is authenticated: %s%s\n",
+ rtt_str, ansi_normal(),
+ ansi_grey(), yes_no(flags & SD_RESOLVED_AUTHENTICATED), ansi_normal());
+}
+
+static void print_ifindex_comment(int printed_so_far, int ifindex) {
+ char ifname[IF_NAMESIZE];
- fputc('.', stdout);
- fputc('\n', stdout);
+ if (ifindex <= 0)
+ return;
- printf("-- Data is authenticated: %s\n", yes_no(flags & SD_RESOLVED_AUTHENTICATED));
+ if (!if_indextoname(ifindex, ifname))
+ log_warning_errno(errno, "Failed to resolve interface name for index %i, ignoring: %m", ifindex);
+ else
+ printf("%*s%s-- link: %s%s",
+ 60 > printed_so_far ? 60 - printed_so_far : 0, " ", /* Align comment to the 60th column */
+ ansi_grey(), ifname, ansi_normal());
}
static int resolve_host(sd_bus *bus, const char *name) {
while ((r = sd_bus_message_enter_container(reply, 'r', "iiay")) > 0) {
_cleanup_free_ char *pretty = NULL;
- char ifname[IF_NAMESIZE] = "";
- int ifindex, family;
+ int ifindex, family, k;
const void *a;
size_t sz;
return -EINVAL;
}
- if (ifindex > 0 && !if_indextoname(ifindex, ifname))
- log_warning_errno(errno, "Failed to resolve interface name for index %i: %m", ifindex);
-
r = in_addr_ifindex_to_string(family, a, ifindex, &pretty);
if (r < 0)
return log_error_errno(r, "Failed to print address for %s: %m", name);
- printf("%*s%s %s%s%s\n",
- (int) strlen(name), c == 0 ? name : "", c == 0 ? ":" : " ",
- pretty,
- isempty(ifname) ? "" : "%", ifname);
+ k = printf("%*s%s %s%s%s",
+ (int) strlen(name), c == 0 ? name : "", c == 0 ? ":" : " ",
+ ansi_highlight(), pretty, ansi_normal());
+
+ print_ifindex_comment(k, ifindex);
+ fputc('\n', stdout);
c++;
}
_cleanup_(sd_bus_message_unrefp) sd_bus_message *req = NULL, *reply = NULL;
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
_cleanup_free_ char *pretty = NULL;
- char ifname[IF_NAMESIZE] = "";
uint64_t flags;
unsigned c = 0;
usec_t ts;
if (r < 0)
return log_oom();
- if (ifindex > 0 && !if_indextoname(ifindex, ifname))
- return log_error_errno(errno, "Failed to resolve interface name for index %i: %m", ifindex);
-
- log_debug("Resolving %s%s%s.", pretty, isempty(ifname) ? "" : "%", ifname);
+ log_debug("Resolving %s.", pretty);
r = sd_bus_message_new_method_call(
bus,
while ((r = sd_bus_message_enter_container(reply, 'r', "is")) > 0) {
const char *n;
+ int k;
assert_cc(sizeof(int) == sizeof(int32_t));
if (r < 0)
return r;
- ifname[0] = 0;
- if (ifindex > 0 && !if_indextoname(ifindex, ifname))
- log_warning_errno(errno, "Failed to resolve interface name for index %i: %m", ifindex);
+ k = printf("%*s%s %s%s%s",
+ (int) strlen(pretty), c == 0 ? pretty : "",
+ c == 0 ? ":" : " ",
+ ansi_highlight(), n, ansi_normal());
- printf("%*s%*s%*s%s %s\n",
- (int) strlen(pretty), c == 0 ? pretty : "",
- isempty(ifname) ? 0 : 1, c > 0 || isempty(ifname) ? "" : "%",
- (int) strlen(ifname), c == 0 ? ifname : "",
- c == 0 ? ":" : " ",
- n);
+ print_ifindex_comment(k, ifindex);
+ fputc('\n', stdout);
c++;
}
_cleanup_(dns_resource_record_unrefp) DnsResourceRecord *rr = NULL;
_cleanup_(dns_packet_unrefp) DnsPacket *p = NULL;
int r;
- char ifname[IF_NAMESIZE] = "";
r = dns_packet_new(&p, DNS_PROTOCOL_DNS, 0, DNS_PACKET_SIZE_MAX);
if (r < 0)
fwrite(data, 1, k, stdout);
} else {
const char *s;
+ int k;
s = dns_resource_record_to_string(rr);
if (!s)
return log_oom();
- if (ifindex > 0 && !if_indextoname(ifindex, ifname))
- log_warning_errno(errno, "Failed to resolve interface name for index %i: %m", ifindex);
-
- printf("%s%s%s\n", s, isempty(ifname) ? "" : " # interface ", ifname);
+ k = printf("%s", s);
+ print_ifindex_comment(k, ifindex);
+ fputc('\n', stdout);
}
return 0;
while ((r = sd_bus_message_enter_container(reply, 'r', "iiay")) > 0) {
_cleanup_free_ char *pretty = NULL;
- char ifname[IF_NAMESIZE] = "";
- int ifindex, family;
+ int ifindex, family, k;
const void *a;
assert_cc(sizeof(int) == sizeof(int32_t));
return -EINVAL;
}
- if (ifindex > 0 && !if_indextoname(ifindex, ifname))
- log_warning_errno(errno, "Failed to resolve interface name for index %i: %m", ifindex);
-
- r = in_addr_to_string(family, a, &pretty);
+ r = in_addr_ifindex_to_string(family, a, ifindex, &pretty);
if (r < 0)
return log_error_errno(r, "Failed to print address for %s: %m", name);
- printf("%*s%s%s%s\n", (int) indent, "", pretty, isempty(ifname) ? "" : "%s", ifname);
+ k = printf("%*s%s", (int) indent, "", pretty);
+ print_ifindex_comment(k, ifindex);
+ fputc('\n', stdout);
}
if (r < 0)
return bus_log_parse_error(r);
assert(bus);
- if (argc <= 1)
- return status_all(bus, STATUS_DNS);
+ if (argc >= 2) {
+ r = ifname_mangle(argv[1]);
+ if (r < 0)
+ return r;
+ }
- r = ifname_mangle(argv[1], false);
- if (r < 0)
- return r;
+ if (arg_ifindex <= 0)
+ return status_all(bus, STATUS_DNS);
- if (argc == 2)
+ if (argc < 3)
return status_ifindex(bus, arg_ifindex, NULL, STATUS_DNS, NULL);
r = sd_bus_message_new_method_call(
assert(bus);
- if (argc <= 1)
- return status_all(bus, STATUS_DOMAIN);
+ if (argc >= 2) {
+ r = ifname_mangle(argv[1]);
+ if (r < 0)
+ return r;
+ }
- r = ifname_mangle(argv[1], false);
- if (r < 0)
- return r;
+ if (arg_ifindex <= 0)
+ return status_all(bus, STATUS_DOMAIN);
- if (argc == 2)
+ if (argc < 3)
return status_ifindex(bus, arg_ifindex, NULL, STATUS_DOMAIN, NULL);
r = sd_bus_message_new_method_call(
assert(bus);
- if (argc <= 1)
- return status_all(bus, STATUS_LLMNR);
+ if (argc >= 2) {
+ r = ifname_mangle(argv[1]);
+ if (r < 0)
+ return r;
+ }
- r = ifname_mangle(argv[1], false);
- if (r < 0)
- return r;
+ if (arg_ifindex <= 0)
+ return status_all(bus, STATUS_LLMNR);
- if (argc == 2)
+ if (argc < 3)
return status_ifindex(bus, arg_ifindex, NULL, STATUS_LLMNR, NULL);
r = sd_bus_call_method(bus,
assert(bus);
- if (argc <= 1)
- return status_all(bus, STATUS_MDNS);
+ if (argc >= 2) {
+ r = ifname_mangle(argv[1]);
+ if (r < 0)
+ return r;
+ }
- r = ifname_mangle(argv[1], false);
- if (r < 0)
- return r;
+ if (arg_ifindex <= 0)
+ return status_all(bus, STATUS_MDNS);
- if (argc == 2)
+ if (argc < 3)
return status_ifindex(bus, arg_ifindex, NULL, STATUS_MDNS, NULL);
r = sd_bus_call_method(bus,
assert(bus);
- if (argc <= 1)
- return status_all(bus, STATUS_PRIVATE);
+ if (argc >= 2) {
+ r = ifname_mangle(argv[1]);
+ if (r < 0)
+ return r;
+ }
- r = ifname_mangle(argv[1], false);
- if (r < 0)
- return r;
+ if (arg_ifindex <= 0)
+ return status_all(bus, STATUS_PRIVATE);
- if (argc == 2)
+ if (argc < 3)
return status_ifindex(bus, arg_ifindex, NULL, STATUS_PRIVATE, NULL);
r = sd_bus_call_method(bus,
assert(bus);
- if (argc <= 1)
- return status_all(bus, STATUS_DNSSEC);
+ if (argc >= 2) {
+ r = ifname_mangle(argv[1]);
+ if (r < 0)
+ return r;
+ }
- r = ifname_mangle(argv[1], false);
- if (r < 0)
- return r;
+ if (arg_ifindex <= 0)
+ return status_all(bus, STATUS_DNSSEC);
- if (argc == 2)
+ if (argc < 3)
return status_ifindex(bus, arg_ifindex, NULL, STATUS_DNSSEC, NULL);
r = sd_bus_call_method(bus,
assert(bus);
- if (argc <= 1)
- return status_all(bus, STATUS_NTA);
+ if (argc >= 2) {
+ r = ifname_mangle(argv[1]);
+ if (r < 0)
+ return r;
+ }
- r = ifname_mangle(argv[1], false);
- if (r < 0)
- return r;
+ if (arg_ifindex <= 0)
+ return status_all(bus, STATUS_NTA);
- if (argc == 2)
+ if (argc < 3)
return status_ifindex(bus, arg_ifindex, NULL, STATUS_NTA, NULL);
/* If only argument is the empty string, then call SetLinkDNSSECNegativeTrustAnchors()
assert(bus);
- r = ifname_mangle(argv[1], false);
- if (r < 0)
- return r;
+ if (argc >= 2) {
+ r = ifname_mangle(argv[1]);
+ if (r < 0)
+ return r;
+ }
+
+ if (arg_ifindex <= 0)
+ return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Interface argument required.");
r = sd_bus_call_method(bus,
"org.freedesktop.resolve1",
break;
case 'i':
- arg_ifname = mfree(arg_ifname);
- r = ifname_mangle(optarg, true);
+ r = ifname_mangle(optarg);
if (r < 0)
return r;
break;
if (arg_ifindex <= 0)
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
"--set-dns=, --set-domain=, --set-llmnr=, --set-mdns=, --set-dnsovertls=, --set-dnssec=, --set-nta= and --revert require --interface=.");
-
- if (arg_ifindex == LOOPBACK_IFINDEX)
- return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
- "Interface can't be the loopback interface (lo). Sorry.");
}
return 1 /* work to do */;
break;
case 'i':
- arg_ifname = mfree(arg_ifname);
- r = ifname_mangle(optarg, true);
+ r = ifname_mangle(optarg);
if (r < 0)
return r;
break;
{ "dnsovertls", VERB_ANY, 3, 0, verb_dns_over_tls },
{ "dnssec", VERB_ANY, 3, 0, verb_dnssec },
{ "nta", VERB_ANY, VERB_ANY, 0, verb_nta },
- { "revert", 2, 2, 0, verb_revert_link },
+ { "revert", VERB_ANY, 2, 0, verb_revert_link },
{}
};
extern char **arg_set_domain;
extern bool arg_ifindex_permissive;
-int ifname_mangle(const char *s, bool allow_loopback);
+int ifname_mangle(const char *s);
#include "bus-common-errors.h"
#include "bus-util.h"
#include "dns-domain.h"
+#include "missing_capability.h"
#include "resolved-bus.h"
#include "resolved-def.h"
#include "resolved-dns-synthesize.h"
if (type == SOCK_DGRAM) {
/* Set IP_RECVERR or IPV6_RECVERR to get ICMP error feedback. See discussion in #10345. */
- r = setsockopt_int(fd, SOL_IP, sa.sa.sa_family == AF_INET ? IP_RECVERR : IPV6_RECVERR, true);
- if (r < 0)
- return r;
+
+ if (sa.sa.sa_family == AF_INET) {
+ r = setsockopt_int(fd, IPPROTO_IP, IP_RECVERR, true);
+ if (r < 0)
+ return r;
+
+ r = setsockopt_int(fd, IPPROTO_IP, IP_PKTINFO, true);
+ if (r < 0)
+ return r;
+
+ } else if (sa.sa.sa_family == AF_INET6) {
+ r = setsockopt_int(fd, IPPROTO_IPV6, IPV6_RECVERR, true);
+ if (r < 0)
+ return r;
+
+ r = setsockopt_int(fd, IPPROTO_IPV6, IPV6_RECVPKTINFO, true);
+ if (r < 0)
+ return r;
+ }
}
if (ret_socket_address)
return -E2BIG;
}
- s = new0(DnsServer, 1);
+ s = new(DnsServer, 1);
if (!s)
return -ENOMEM;
- s->n_ref = 1;
- s->manager = m;
- s->type = type;
- s->family = family;
- s->address = *in_addr;
- s->ifindex = ifindex;
+ *s = (DnsServer) {
+ .n_ref = 1,
+ .manager = m,
+ .type = type,
+ .family = family,
+ .address = *in_addr,
+ .ifindex = ifindex,
+ };
dns_server_reset_features(s);
static DnsServer* dns_server_free(DnsServer *s) {
assert(s);
- dns_stream_unref(s->stream);
+ dns_server_unref_stream(s);
#if ENABLE_DNS_OVER_TLS
dnstls_server_free(s);
if (s->manager->current_dns_server == s)
manager_set_dns_server(s->manager, NULL);
+ /* No need to keep a default stream around anymore */
+ dns_server_unref_stream(s);
+
dns_server_unref(s);
}
s->warned_downgrade = false;
dns_server_reset_counters(s);
+
+ /* Let's close the default stream, so that we reprobe with the new features */
+ dns_server_unref_stream(s);
}
void dns_server_reset_features_all(DnsServer *s) {
yes_no(s->packet_rrsig_missing));
}
+void dns_server_unref_stream(DnsServer *s) {
+ DnsStream *ref;
+
+ assert(s);
+
+ /* Detaches the default stream of this server. Some special care needs to be taken here, as that stream and
+ * this server reference each other. First, take the stream out of the server. It's destructor will check if it
+ * is registered with us, hence let's invalidate this separatly, so that it is already unregistered. */
+ ref = TAKE_PTR(s->stream);
+
+ /* And then, unref it */
+ dns_stream_unref(ref);
+}
+
static const char* const dns_server_type_table[_DNS_SERVER_TYPE_MAX] = {
[DNS_SERVER_SYSTEM] = "system",
[DNS_SERVER_FALLBACK] = "fallback",
int ifindex; /* for IPv6 link-local DNS servers */
char *server_string;
+
+ /* The long-lived stream towards this server. */
DnsStream *stream;
#if ENABLE_DNS_OVER_TLS
void dns_server_reset_features_all(DnsServer *s);
void dns_server_dump(DnsServer *s, FILE *f);
+
+void dns_server_unref_stream(DnsServer *s);
s->io_event_source = sd_event_source_unref(s->io_event_source);
s->timeout_event_source = sd_event_source_unref(s->timeout_event_source);
s->fd = safe_close(s->fd);
+
+ /* Disconnect us from the server object if we are now not usable anymore */
+ dns_stream_detach(s);
}
static int dns_stream_update_io(DnsStream *s) {
}
static int dns_stream_complete(DnsStream *s, int error) {
+ _cleanup_(dns_stream_unrefp) _unused_ DnsStream *ref = dns_stream_ref(s); /* Protect stream while we process it */
+
assert(s);
#if ENABLE_DNS_OVER_TLS
#endif
dns_stream_stop(s);
+ dns_stream_detach(s);
+
if (s->complete)
s->complete(s, error);
else /* the default action if no completion function is set is to close the stream */
}
ssize_t dns_stream_writev(DnsStream *s, const struct iovec *iov, size_t iovcnt, int flags) {
- ssize_t r;
+ ssize_t m;
assert(s);
assert(iov);
ssize_t ss;
size_t i;
- r = 0;
+ m = 0;
for (i = 0; i < iovcnt; i++) {
ss = dnstls_stream_write(s, iov[i].iov_base, iov[i].iov_len);
if (ss < 0)
return ss;
- r += ss;
+ m += ss;
if (ss != (ssize_t) iov[i].iov_len)
continue;
}
.msg_namelen = s->tfo_salen
};
- r = sendmsg(s->fd, &hdr, MSG_FASTOPEN);
- if (r < 0) {
+ m = sendmsg(s->fd, &hdr, MSG_FASTOPEN);
+ if (m < 0) {
if (errno == EOPNOTSUPP) {
s->tfo_salen = 0;
- r = connect(s->fd, &s->tfo_address.sa, s->tfo_salen);
- if (r < 0)
+ if (connect(s->fd, &s->tfo_address.sa, s->tfo_salen) < 0)
return -errno;
- r = -EAGAIN;
- } else if (errno == EINPROGRESS)
- r = -EAGAIN;
- else
- r = -errno;
+ return -EAGAIN;
+ }
+ if (errno == EINPROGRESS)
+ return -EAGAIN;
+
+ return -errno;
} else
s->tfo_salen = 0; /* connection is made */
} else {
- r = writev(s->fd, iov, iovcnt);
- if (r < 0)
- r = -errno;
+ m = writev(s->fd, iov, iovcnt);
+ if (m < 0)
+ return -errno;
}
- return r;
+ return m;
}
static ssize_t dns_stream_read(DnsStream *s, void *buf, size_t count) {
{
ss = read(s->fd, buf, count);
if (ss < 0)
- ss = -errno;
+ return -errno;
}
return ss;
}
static int on_stream_io(sd_event_source *es, int fd, uint32_t revents, void *userdata) {
- DnsStream *s = userdata;
+ _cleanup_(dns_stream_unrefp) DnsStream *s = dns_stream_ref(userdata); /* Protect stream while we process it */
int r;
assert(s);
#if ENABLE_DNS_OVER_TLS
if (s->encrypted) {
r = dnstls_stream_on_io(s, revents);
-
if (r == DNSTLS_STREAM_CLOSED)
return 0;
- else if (r == -EAGAIN)
+ if (r == -EAGAIN)
return dns_stream_update_io(s);
- else if (r < 0) {
+ if (r < 0)
return dns_stream_complete(s, -r);
- } else {
- r = dns_stream_update_io(s);
- if (r < 0)
- return r;
- }
+
+ r = dns_stream_update_io(s);
+ if (r < 0)
+ return r;
}
#endif
dns_stream_stop(s);
- if (s->server && s->server->stream == s)
- s->server->stream = NULL;
-
if (s->manager) {
LIST_REMOVE(streams, s->manager->dns_streams, s);
s->manager->n_dns_streams--;
DEFINE_TRIVIAL_REF_UNREF_FUNC(DnsStream, dns_stream, dns_stream_free);
-int dns_stream_new(Manager *m, DnsStream **ret, DnsProtocol protocol, int fd, const union sockaddr_union *tfo_address) {
+int dns_stream_new(
+ Manager *m,
+ DnsStream **ret,
+ DnsProtocol protocol,
+ int fd,
+ const union sockaddr_union *tfo_address) {
+
_cleanup_(dns_stream_unrefp) DnsStream *s = NULL;
int r;
assert(m);
+ assert(ret);
assert(fd >= 0);
if (m->n_dns_streams > DNS_STREAMS_MAX)
return -EBUSY;
- s = new0(DnsStream, 1);
+ s = new(DnsStream, 1);
if (!s)
return -ENOMEM;
+ *s = (DnsStream) {
+ .n_ref = 1,
+ .fd = -1,
+ .protocol = protocol,
+ };
+
r = ordered_set_ensure_allocated(&s->write_queue, &dns_packet_hash_ops);
if (r < 0)
return r;
- s->n_ref = 1;
- s->fd = -1;
- s->protocol = protocol;
-
r = sd_event_add_io(m->event, &s->io_event_source, fd, EPOLLIN, on_stream_io, s);
if (r < 0)
return r;
(void) sd_event_source_set_description(s->timeout_event_source, "dns-stream-timeout");
LIST_PREPEND(streams, m->dns_streams, s);
+ m->n_dns_streams++;
s->manager = m;
+
s->fd = fd;
+
if (tfo_address) {
s->tfo_address = *tfo_address;
s->tfo_salen = tfo_address->sa.sa_family == AF_INET6 ? sizeof(tfo_address->in6) : sizeof(tfo_address->in);
}
- m->n_dns_streams++;
-
*ret = TAKE_PTR(s);
return 0;
int r;
assert(s);
+ assert(p);
r = ordered_set_put(s->write_queue, p);
if (r < 0)
return dns_stream_update_io(s);
}
+
+DnsPacket *dns_stream_take_read_packet(DnsStream *s) {
+ assert(s);
+
+ if (!s->read_packet)
+ return NULL;
+
+ if (s->n_read < sizeof(s->read_size))
+ return NULL;
+
+ if (s->n_read < sizeof(s->read_size) + be16toh(s->read_size))
+ return NULL;
+
+ s->n_read = 0;
+ return TAKE_PTR(s->read_packet);
+}
+
+void dns_stream_detach(DnsStream *s) {
+ assert(s);
+
+ if (!s->server)
+ return;
+
+ if (s->server->stream != s)
+ return;
+
+ dns_server_unref_stream(s->server);
+}
size_t n_written, n_read;
OrderedSet *write_queue;
- int (*on_connection)(DnsStream *s);
int (*on_packet)(DnsStream *s);
int (*complete)(DnsStream *s, int error);
LIST_HEAD(DnsTransaction, transactions); /* when used by the transaction logic */
DnsServer *server; /* when used by the transaction logic */
- DnsQuery *query; /* when used by the DNS stub logic */
+ DnsQuery *query; /* when used by the DNS stub logic */
/* used when DNS-over-TLS is enabled */
bool encrypted:1;
return !!s->write_packet;
}
+
+DnsPacket *dns_stream_take_read_packet(DnsStream *s);
+
+void dns_stream_detach(DnsStream *s);
/* SPDX-License-Identifier: LGPL-2.1+ */
#include "fd-util.h"
+#include "missing_network.h"
#include "resolved-dns-stub.h"
#include "socket-util.h"
}
static int on_dns_stub_stream_packet(DnsStream *s) {
+ _cleanup_(dns_packet_unrefp) DnsPacket *p = NULL;
+
assert(s);
- assert(s->read_packet);
- if (dns_packet_validate_query(s->read_packet) > 0) {
- log_debug("Got DNS stub TCP query packet for id %u", DNS_PACKET_ID(s->read_packet));
+ p = dns_stream_take_read_packet(s);
+ assert(p);
+
+ if (dns_packet_validate_query(p) > 0) {
+ log_debug("Got DNS stub TCP query packet for id %u", DNS_PACKET_ID(p));
- dns_stub_process_query(s->manager, s, s->read_packet);
+ dns_stub_process_query(s->manager, s, p);
} else
log_debug("Invalid DNS stub TCP packet, ignoring.");
#include "alloc-util.h"
#include "hostname-util.h"
#include "local-addresses.h"
+#include "missing_network.h"
#include "resolved-dns-synthesize.h"
int dns_synthesize_ifindex(int ifindex) {
}
static int on_stream_complete(DnsStream *s, int error) {
- _cleanup_(dns_stream_unrefp) DnsStream *p = NULL;
- DnsTransaction *t, *n;
- int r = 0;
-
- /* Do not let new transactions use this stream */
- if (s->server && s->server->stream == s)
- p = TAKE_PTR(s->server->stream);
+ assert(s);
if (ERRNO_IS_DISCONNECT(error) && s->protocol != DNS_PROTOCOL_LLMNR) {
- usec_t usec;
-
log_debug_errno(error, "Connection failure for DNS TCP stream: %m");
if (s->transactions) {
+ DnsTransaction *t;
+
t = s->transactions;
- assert_se(sd_event_now(t->scope->manager->event, clock_boottime_or_monotonic(), &usec) >= 0);
dns_server_packet_lost(t->server, IPPROTO_TCP, t->current_feature_level);
}
}
- LIST_FOREACH_SAFE(transactions_by_stream, t, n, s->transactions)
- if (error != 0)
+ if (error != 0) {
+ DnsTransaction *t, *n;
+
+ LIST_FOREACH_SAFE(transactions_by_stream, t, n, s->transactions)
on_transaction_stream_error(t, error);
- else if (DNS_PACKET_ID(s->read_packet) == t->id)
- /* As each transaction have a unique id the return code is only set once */
- r = dns_transaction_on_stream_packet(t, s->read_packet);
+ }
- return r;
+ return 0;
}
-static int dns_stream_on_packet(DnsStream *s) {
+static int on_stream_packet(DnsStream *s) {
_cleanup_(dns_packet_unrefp) DnsPacket *p = NULL;
- int r = 0;
DnsTransaction *t;
+ assert(s);
+
/* Take ownership of packet to be able to receive new packets */
- p = TAKE_PTR(s->read_packet);
- s->n_read = 0;
+ p = dns_stream_take_read_packet(s);
+ assert(p);
t = hashmap_get(s->manager->dns_transactions, UINT_TO_PTR(DNS_PACKET_ID(p)));
+ if (t)
+ return dns_transaction_on_stream_packet(t, p);
/* Ignore incorrect transaction id as transaction can have been canceled */
- if (t)
- r = dns_transaction_on_stream_packet(t, p);
- else {
- if (dns_packet_validate_reply(p) <= 0) {
- log_debug("Invalid TCP reply packet.");
- on_stream_complete(s, 0);
- }
- return 0;
+ if (dns_packet_validate_reply(p) <= 0) {
+ log_debug("Invalid TCP reply packet.");
+ on_stream_complete(s, 0);
}
- return r;
+ return 0;
+}
+
+static uint16_t dns_port_for_feature_level(DnsServerFeatureLevel level) {
+ return DNS_SERVER_FEATURE_LEVEL_IS_TLS(level) ? 853 : 53;
}
static int dns_transaction_emit_tcp(DnsTransaction *t) {
if (t->server->stream && (DNS_SERVER_FEATURE_LEVEL_IS_TLS(t->current_feature_level) == t->server->stream->encrypted))
s = dns_stream_ref(t->server->stream);
else
- fd = dns_scope_socket_tcp(t->scope, AF_UNSPEC, NULL, t->server, DNS_SERVER_FEATURE_LEVEL_IS_TLS(t->current_feature_level) ? 853 : 53, &sa);
+ fd = dns_scope_socket_tcp(t->scope, AF_UNSPEC, NULL, t->server, dns_port_for_feature_level(t->current_feature_level), &sa);
break;
fd = -1;
#if ENABLE_DNS_OVER_TLS
- if (DNS_SERVER_FEATURE_LEVEL_IS_TLS(t->current_feature_level)) {
+ if (t->scope->protocol == DNS_PROTOCOL_DNS &&
+ DNS_SERVER_FEATURE_LEVEL_IS_TLS(t->current_feature_level)) {
+
assert(t->server);
r = dnstls_stream_connect_tls(s, t->server);
if (r < 0)
#endif
if (t->server) {
- dns_stream_unref(t->server->stream);
+ dns_server_unref_stream(t->server);
t->server->stream = dns_stream_ref(s);
s->server = dns_server_ref(t->server);
}
s->complete = on_stream_complete;
- s->on_packet = dns_stream_on_packet;
+ s->on_packet = on_stream_packet;
/* The interface index is difficult to determine if we are
* connecting to the local host, hence fill this in right away
#include "alloc-util.h"
#include "bus-util.h"
+#include "missing_capability.h"
#include "resolved-dnssd.h"
#include "resolved-dnssd-bus.h"
#include "resolved-link.h"
}
static int on_llmnr_stream_packet(DnsStream *s) {
+ _cleanup_(dns_packet_unrefp) DnsPacket *p = NULL;
DnsScope *scope;
assert(s);
- assert(s->read_packet);
- scope = manager_find_scope(s->manager, s->read_packet);
+ p = dns_stream_take_read_packet(s);
+ assert(p);
+
+ scope = manager_find_scope(s->manager, p);
if (!scope)
log_debug("Got LLMNR TCP packet on unknown scope. Ignoring.");
- else if (dns_packet_validate_query(s->read_packet) > 0) {
- log_debug("Got LLMNR TCP query packet for id %u", DNS_PACKET_ID(s->read_packet));
+ else if (dns_packet_validate_query(p) > 0) {
+ log_debug("Got LLMNR TCP query packet for id %u", DNS_PACKET_ID(p));
- dns_scope_process_query(scope, s, s->read_packet);
+ dns_scope_process_query(scope, s, p);
} else
log_debug("Invalid LLMNR TCP packet, ignoring.");
#include "fileio.h"
#include "hostname-util.h"
#include "io-util.h"
+#include "missing_network.h"
#include "netlink-util.h"
#include "network-internal.h"
#include "ordered-set.h"
#include "sd-event.h"
#include "capability-util.h"
+#include "daemon-util.h"
+#include "main-func.h"
#include "mkdir.h"
#include "resolved-conf.h"
#include "resolved-manager.h"
#include "signal-util.h"
#include "user-util.h"
-int main(int argc, char *argv[]) {
+static int run(int argc, char *argv[]) {
+ _cleanup_(notify_on_cleanup) const char *notify_stop = NULL;
_cleanup_(manager_freep) Manager *m = NULL;
const char *user = "systemd-resolve";
uid_t uid;
log_setup_service();
- if (argc != 1) {
- log_error("This program takes no arguments.");
- r = -EINVAL;
- goto finish;
- }
+ if (argc != 1)
+ return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "This program takes no arguments.");
umask(0022);
r = mac_selinux_init();
- if (r < 0) {
- log_error_errno(r, "SELinux setup failed: %m");
- goto finish;
- }
+ if (r < 0)
+ return log_error_errno(r, "SELinux setup failed: %m");
r = get_user_creds(&user, &uid, &gid, NULL, NULL, 0);
- if (r < 0) {
- log_error_errno(r, "Cannot resolve user name %s: %m", user);
- goto finish;
- }
+ if (r < 0)
+ return log_error_errno(r, "Cannot resolve user name %s: %m", user);
/* Always create the directory where resolv.conf will live */
r = mkdir_safe_label("/run/systemd/resolve", 0755, uid, gid, MKDIR_WARN_MODE);
- if (r < 0) {
- log_error_errno(r, "Could not create runtime directory: %m");
- goto finish;
- }
+ if (r < 0)
+ return log_error_errno(r, "Could not create runtime directory: %m");
/* Drop privileges, but only if we have been started as root. If we are not running as root we assume most
* privileges are already dropped. */
(UINT64_C(1) << CAP_NET_BIND_SERVICE)| /* needed to bind on port 53 */
(UINT64_C(1) << CAP_SETPCAP) /* needed in order to drop the caps later */);
if (r < 0)
- goto finish;
+ return log_error_errno(r, "Failed to drop privileges: %m");
}
assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGTERM, SIGINT, SIGUSR1, SIGUSR2, SIGRTMIN+1, -1) >= 0);
r = manager_new(&m);
- if (r < 0) {
- log_error_errno(r, "Could not create manager: %m");
- goto finish;
- }
+ if (r < 0)
+ return log_error_errno(r, "Could not create manager: %m");
r = manager_start(m);
- if (r < 0) {
- log_error_errno(r, "Failed to start manager: %m");
- goto finish;
- }
+ if (r < 0)
+ return log_error_errno(r, "Failed to start manager: %m");
/* Write finish default resolv.conf to avoid a dangling symlink */
(void) manager_write_resolv_conf(m);
/* Let's drop the remaining caps now */
r = capability_bounding_set_drop(0, true);
- if (r < 0) {
- log_error_errno(r, "Failed to drop remaining caps: %m");
- goto finish;
- }
+ if (r < 0)
+ return log_error_errno(r, "Failed to drop remaining caps: %m");
- sd_notify(false,
- "READY=1\n"
- "STATUS=Processing requests...");
+ notify_stop = notify_start(NOTIFY_READY, NOTIFY_STOPPING);
r = sd_event_loop(m->event);
- if (r < 0) {
- log_error_errno(r, "Event loop failed: %m");
- goto finish;
- }
+ if (r < 0)
+ return log_error_errno(r, "Event loop failed: %m");
- sd_event_get_exit_code(m->event, &r);
+ (void) sd_event_get_exit_code(m->event, &r);
-finish:
- sd_notify(false,
- "STOPPING=1\n"
- "STATUS=Shutting down...");
-
- return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
+ return r;
}
+
+DEFINE_MAIN_FUNCTION(run);
f = fopen("/etc/hosts", "re");
if (!f) {
- assert_se(errno == -ENOENT);
+ assert_se(errno == ENOENT);
return;
}
#pragma once
#if HAVE_BLKID
-#include <blkid.h>
-#endif
+# include <blkid.h>
-#include "util.h"
+# include "macro.h"
-#if HAVE_BLKID
DEFINE_TRIVIAL_CLEANUP_FUNC(blkid_probe, blkid_free_probe);
#endif
#include "ip-protocol-list.h"
#include "list.h"
#include "locale-util.h"
+#include "missing_fs.h"
#include "mountpoint-util.h"
#include "nsflags.h"
#include "parse-util.h"
#include "fs-util.h"
#include "log.h"
#include "macro.h"
+#include "missing.h"
#include "parse-util.h"
#include "path-util.h"
#include "process-util.h"
+#include "rlimit-util.h"
#include "signal-util.h"
#include "socket-util.h"
#include "string-util.h"
#include "syslog-util.h"
#include "time-util.h"
#include "utf8.h"
-#include "rlimit-util.h"
int config_item_table_lookup(
const void *table,
--- /dev/null
+/* SPDX-License-Identifier: LGPL-2.1+ */
+#pragma once
+
+#include <stdbool.h>
+
+#include "sd-daemon.h"
+
+#define NOTIFY_READY "READY=1\n" "STATUS=Processing requests..."
+#define NOTIFY_STOPPING "STOPPING=1\n" "STATUS=Shutting down..."
+
+static inline const char *notify_start(const char *start, const char *stop) {
+ if (start)
+ (void) sd_notify(false, start);
+
+ return stop;
+}
+
+/* This is intended to be used with _cleanup_ attribute. */
+static inline void notify_on_cleanup(const char **p) {
+ if (p)
+ (void) sd_notify(false, *p);
+}
#include "hashmap.h"
#include "macro.h"
#include "process-util.h"
+#include "rlimit-util.h"
#include "serialize.h"
#include "set.h"
#include "signal-util.h"
_exit(EXIT_FAILURE);
}
+ (void) rlimit_nofile_safe();
+
if (!argv) {
_argv[0] = (char*) path;
_argv[1] = NULL;
const char *opts,
char **filtered) {
- /* Allow configuration how long we wait for a device that
- * backs a mount point to show up. This is useful to support
- * endless device timeouts for devices that show up only after
- * user input, like crypto devices. */
+ /* Configure how long we wait for a device that backs a mount point or a
+ * swap partition to show up. This is useful to support endless device timeouts
+ * for devices that show up only after user input, like crypto devices. */
_cleanup_free_ char *node = NULL, *unit = NULL, *timeout = NULL;
usec_t u;
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-#include <stddef.h>
-
-#include "macro.h"
-#include "missing.h"
-
typedef struct LockFile {
char *path;
int fd;
color_on = ANSI_HIGHLIGHT;
color_off = ANSI_NORMAL;
highlight_on = ANSI_HIGHLIGHT_RED;
+ } else if (priority >= LOG_DEBUG) {
+ color_on = ANSI_GREY;
+ color_off = ANSI_NORMAL;
+ highlight_on = ANSI_HIGHLIGHT_RED;
}
}
#include <stdlib.h>
#include <string.h>
#include <sys/file.h>
+#include <sys/ioctl.h>
#include <sys/stat.h>
#include <unistd.h>
#include <linux/fs.h>
cpu-set-util.h
crypt-util.c
crypt-util.h
+ daemon-util.h
dev-setup.c
dev-setup.h
dissect-image.c
reboot-util.h
resolve-util.c
resolve-util.h
- rlimit-util.c
- rlimit-util.h
seccomp-util.h
securebits-util.c
securebits-util.h
/* SPDX-License-Identifier: LGPL-2.1+ */
-#include <sched.h>
+#include <errno.h>
#include "alloc-util.h"
#include "extract-word.h"
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-#include <sched.h>
-
-#include "missing.h"
+#include "missing_sched.h"
/* The combination of all namespace flags defined by the kernel. The right type for this isn't clear. setns() and
* unshare() expect these flags to be passed as (signed) "int", while clone() wants them as "unsigned long". The latter
#include "macro.h"
#include "pager.h"
#include "process-util.h"
+#include "rlimit-util.h"
#include "signal-util.h"
#include "string-util.h"
#include "strv.h"
file = fdopen(exe_name_fd, "r");
if (!file) {
safe_close(exe_name_fd);
- return log_debug_errno(errno, "Failed to create FILE object: %m");
+ return log_error_errno(errno, "Failed to create FILE object: %m");
}
/* Find the last line */
r = read_line(file, LONG_LINE_MAX, &t);
if (r < 0)
- return r;
+ return log_error_errno(r, "Failed to read from socket: %m");
if (r == 0)
break;
return 0;
if (!is_main_thread())
- return -EPERM;
+ return log_error_errno(SYNTHETIC_ERRNO(EPERM), "Pager invoked from wrong thread.");
pager = getenv("SYSTEMD_PAGER");
if (!pager)
if (pager) {
pager_args = strv_split(pager, WHITESPACE);
if (!pager_args)
- return -ENOMEM;
+ return log_oom();
/* If the pager is explicitly turned off, honour it */
if (strv_isempty(pager_args) || strv_equal(pager_args, STRV_MAKE("cat")))
if (flags & PAGER_JUMP_TO_END)
less_opts = strjoina(less_opts, " +G");
- r = safe_fork("(pager)", FORK_RESET_SIGNALS|FORK_DEATHSIG|FORK_LOG, &pager_pid);
+ r = safe_fork("(pager)", FORK_RESET_SIGNALS|FORK_DEATHSIG|FORK_RLIMIT_NOFILE_SAFE|FORK_LOG, &pager_pid);
if (r < 0)
return r;
if (r == 0) {
/* In the child start the pager */
- (void) dup2(fd[0], STDIN_FILENO);
+ if (dup2(fd[0], STDIN_FILENO) < 0) {
+ log_error_errno(errno, "Failed to duplicate file descriptor to STDIN: %m");
+ _exit(EXIT_FAILURE);
+ }
+
safe_close_pair(fd);
- if (setenv("LESS", less_opts, 1) < 0)
+ if (setenv("LESS", less_opts, 1) < 0) {
+ log_error_errno(errno, "Failed to set environment variable LESS: %m");
_exit(EXIT_FAILURE);
+ }
/* Initialize a good charset for less. This is
* particularly important if we output UTF-8
if (!less_charset && is_locale_utf8())
less_charset = "utf-8";
if (less_charset &&
- setenv("LESSCHARSET", less_charset, 1) < 0)
+ setenv("LESSCHARSET", less_charset, 1) < 0) {
+ log_error_errno(errno, "Failed to set environment variable LESSCHARSET: %m");
_exit(EXIT_FAILURE);
+ }
if (pager_args) {
- if (loop_write(exe_name_pipe[1], pager_args[0], strlen(pager_args[0]) + 1, false) < 0)
+ r = loop_write(exe_name_pipe[1], pager_args[0], strlen(pager_args[0]) + 1, false);
+ if (r < 0) {
+ log_error_errno(r, "Failed to write pager name to socket: %m");
_exit(EXIT_FAILURE);
+ }
execvp(pager_args[0], pager_args);
+ log_full_errno(errno == ENOENT ? LOG_DEBUG : LOG_WARNING, errno,
+ "Failed execute %s, using fallback pagers: %m", pager_args[0]);
}
/* Debian's alternatives command for pagers is
* is similar to this one anyway, but is
* Debian-specific. */
FOREACH_STRING(exe, "pager", "less", "more") {
- if (loop_write(exe_name_pipe[1], exe, strlen(exe) + 1, false) < 0)
+ r = loop_write(exe_name_pipe[1], exe, strlen(exe) + 1, false);
+ if (r < 0) {
+ log_error_errno(r, "Failed to write pager name to socket: %m");
_exit(EXIT_FAILURE);
+ }
execlp(exe, exe, NULL);
+ log_full_errno(errno == ENOENT ? LOG_DEBUG : LOG_WARNING, errno,
+ "Failed execute %s, using next fallback pager: %m", exe);
}
- if (loop_write(exe_name_pipe[1], "(built-in)", strlen("(built-in") + 1, false) < 0)
+ r = loop_write(exe_name_pipe[1], "(built-in)", strlen("(built-in") + 1, false);
+ if (r < 0) {
+ log_error_errno(r, "Failed to write pager name to socket: %m");
_exit(EXIT_FAILURE);
+ }
pager_fallback();
/* not reached */
}
} else
args[1] = desc;
- r = safe_fork("(man)", FORK_RESET_SIGNALS|FORK_DEATHSIG|(null_stdio ? FORK_NULL_STDIO : 0)|FORK_LOG, &pid);
+ r = safe_fork("(man)", FORK_RESET_SIGNALS|FORK_DEATHSIG|(null_stdio ? FORK_NULL_STDIO : 0)|FORK_RLIMIT_NOFILE_SAFE|FORK_LOG, &pid);
if (r < 0)
return r;
if (r == 0) {
pid_t pid;
int r;
- r = safe_fork("(sulogin)", FORK_RESET_SIGNALS|FORK_DEATHSIG|FORK_LOG, &pid);
+ r = safe_fork("(sulogin)", FORK_RESET_SIGNALS|FORK_DEATHSIG|FORK_RLIMIT_NOFILE_SAFE|FORK_LOG, &pid);
if (r < 0)
return r;
if (r == 0) {
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- Copyright © 2013 Marc-Antoine Perennou
-***/
#include <errno.h>
#include <fcntl.h>
}
static int on_properties_changed(sd_bus_message *m, void *userdata, sd_bus_error *error) {
+ const char *path, *interface, *active_state = NULL, *job_path = NULL;
WaitContext *c = userdata;
- const char *path;
+ bool is_failed;
int r;
+ /* Called whenever we get a PropertiesChanged signal. Checks if ActiveState changed to inactive/failed.
+ *
+ * Signal parameters: (s interface, a{sv} changed_properties, as invalidated_properties) */
+
path = sd_bus_message_get_path(m);
if (!set_contains(c->unit_paths, path))
return 0;
- /* Check if ActiveState changed to inactive/failed */
- /* (s interface, a{sv} changed_properties, as invalidated_properties) */
- r = sd_bus_message_skip(m, "s");
+ r = sd_bus_message_read(m, "s", &interface);
if (r < 0)
return bus_log_parse_error(r);
+ if (!streq(interface, "org.freedesktop.systemd1.Unit")) /* ActiveState is on the Unit interface */
+ return 0;
+
r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "{sv}");
if (r < 0)
return bus_log_parse_error(r);
- while ((r = sd_bus_message_enter_container(m, SD_BUS_TYPE_DICT_ENTRY, "sv")) > 0) {
+ for (;;) {
const char *s;
- r = sd_bus_message_read(m, "s", &s);
+ r = sd_bus_message_enter_container(m, SD_BUS_TYPE_DICT_ENTRY, "sv");
if (r < 0)
return bus_log_parse_error(r);
+ if (r == 0) /* end of array */
+ break;
- if (streq(s, "ActiveState")) {
- bool is_failed;
+ r = sd_bus_message_read(m, "s", &s); /* Property name */
+ if (r < 0)
+ return bus_log_parse_error(r);
- r = sd_bus_message_enter_container(m, SD_BUS_TYPE_VARIANT, "s");
+ if (streq(s, "ActiveState")) {
+ r = sd_bus_message_read(m, "v", "s", &active_state);
if (r < 0)
return bus_log_parse_error(r);
- r = sd_bus_message_read(m, "s", &s);
+ if (job_path) /* Found everything we need */
+ break;
+
+ } else if (streq(s, "Job")) {
+ uint32_t job_id;
+
+ r = sd_bus_message_read(m, "v", "(uo)", &job_id, &job_path);
if (r < 0)
return bus_log_parse_error(r);
- is_failed = streq(s, "failed");
- if (streq(s, "inactive") || is_failed) {
- log_debug("%s became %s, dropping from --wait tracking", path, s);
- free(set_remove(c->unit_paths, path));
- c->any_failed = c->any_failed || is_failed;
- } else
- log_debug("ActiveState on %s changed to %s", path, s);
+ /* There's still a job pending for this unit, let's ignore this for now, and return right-away. */
+ if (job_id != 0)
+ return 0;
+
+ if (active_state) /* Found everything we need */
+ break;
- break; /* no need to dissect the rest of the message */
} else {
- /* other property */
- r = sd_bus_message_skip(m, "v");
+ r = sd_bus_message_skip(m, "v"); /* Other property */
if (r < 0)
return bus_log_parse_error(r);
}
+
r = sd_bus_message_exit_container(m);
if (r < 0)
return bus_log_parse_error(r);
}
- if (r < 0)
- return bus_log_parse_error(r);
+
+ /* If this didn't contain the ActiveState property we can't do anything */
+ if (!active_state)
+ return 0;
+
+ is_failed = streq(active_state, "failed");
+ if (streq(active_state, "inactive") || is_failed) {
+ log_debug("%s became %s, dropping from --wait tracking", path, active_state);
+ free(set_remove(c->unit_paths, path));
+ c->any_failed = c->any_failed || is_failed;
+ } else
+ log_debug("ActiveState on %s changed to %s", path, active_state);
if (set_isempty(c->unit_paths))
sd_event_exit(c->event, EXIT_SUCCESS);
_cleanup_(bus_wait_for_jobs_freep) BusWaitForJobs *w = NULL;
_cleanup_(wait_context_free) WaitContext wait_context = {};
const char *method, *mode, *one_name, *suffix = NULL;
+ _cleanup_free_ char **stopped_units = NULL; /* Do not use _cleanup_strv_free_ */
_cleanup_strv_free_ char **names = NULL;
int r, ret = EXIT_SUCCESS;
sd_bus *bus;
r = start_unit_one(bus, method, *name, mode, &error, w, arg_wait ? &wait_context : NULL);
if (ret == EXIT_SUCCESS && r < 0)
ret = translate_bus_error_to_exit_status(r, &error);
+
+ if (r >= 0 && streq(method, "StopUnit")) {
+ r = strv_push(&stopped_units, *name);
+ if (r < 0)
+ return log_oom();
+ }
}
if (!arg_no_block) {
/* When stopping units, warn if they can still be triggered by
* another active unit (socket, path, timer) */
- if (!arg_quiet && streq(method, "StopUnit"))
- STRV_FOREACH(name, names)
+ if (!arg_quiet)
+ STRV_FOREACH(name, stopped_units)
(void) check_triggering_units(bus, *name);
}
if (arg_dry_run)
return 0;
- r = safe_fork("(kexec)", FORK_RESET_SIGNALS|FORK_DEATHSIG|FORK_LOG, &pid);
+ r = safe_fork("(kexec)", FORK_RESET_SIGNALS|FORK_DEATHSIG|FORK_RLIMIT_NOFILE_SAFE|FORK_LOG, &pid);
if (r < 0)
return r;
if (r == 0) {
if (!arg_quiet)
log_info("Executing: %s", l);
- j = safe_fork("(sysv-install)", FORK_RESET_SIGNALS|FORK_DEATHSIG|FORK_LOG, &pid);
+ j = safe_fork("(sysv-install)", FORK_RESET_SIGNALS|FORK_DEATHSIG|FORK_RLIMIT_NOFILE_SAFE|FORK_LOG, &pid);
if (j < 0)
return j;
if (j == 0) {
assert(paths);
- r = safe_fork("(editor)", FORK_RESET_SIGNALS|FORK_DEATHSIG|FORK_LOG|FORK_WAIT, NULL);
+ r = safe_fork("(editor)", FORK_RESET_SIGNALS|FORK_DEATHSIG|FORK_RLIMIT_NOFILE_SAFE|FORK_LOG|FORK_WAIT, NULL);
if (r < 0)
return r;
if (r == 0) {
/* we default to allowing interactive authorization only in systemctl (not in the legacy commands) */
arg_ask_password = true;
- while ((c = getopt_long(argc, argv, "ht:p:alqfs:H:M:n:o:ir", options, NULL)) >= 0)
+ while ((c = getopt_long(argc, argv, "ht:p:alqfs:H:M:n:o:ir.::", options, NULL)) >= 0)
switch (c) {
return log_oom();
break;
+ case '.':
+ /* Output an error mimicking getopt, and print a hint afterwards */
+ log_error("%s: invalid option -- '.'", program_invocation_name);
+ log_notice("Hint: to specify units starting with a dash, use \"--\":\n"
+ " %s [OPTIONS...] {COMMAND} -- -.%s ...",
+ program_invocation_name, optarg ?: "mount");
+ _fallthrough_;
+
case '?':
return -EINVAL;
/* Hmm, so some other init system is running, we need to forward this request to
* it. For now we simply guess that it is Upstart. */
+ (void) rlimit_nofile_safe();
execv(TELINIT, argv);
return log_error_errno(SYNTHETIC_ERRNO(EIO),
int sd_rtnl_message_routing_policy_rule_get_rtm_dst_prefixlen(sd_netlink_message *m, unsigned char *len);
int sd_rtnl_message_routing_policy_rule_set_rtm_type(sd_netlink_message *m, unsigned char type);
int sd_rtnl_message_routing_policy_rule_get_rtm_type(sd_netlink_message *m, unsigned char *type);
+int sd_rtnl_message_routing_policy_rule_set_flags(sd_netlink_message *m, unsigned flags);
+int sd_rtnl_message_routing_policy_rule_get_flags(sd_netlink_message *m, unsigned *flags);
/* genl */
int sd_genl_socket_open(sd_netlink **nl);
#include <string.h>
#include "macro.h"
+#include "missing_network.h"
#include "string-util.h"
-#include "util.h"
_unused_ \
static const struct arphrd_name* lookup_arphrd(register const char *str, register GPERF_LEN_TYPE len);
#include "io-util.h"
#include "log.h"
#include "macro.h"
+#include "missing_network.h"
#include "process-util.h"
#include "socket-util.h"
#include "string-util.h"
#!/usr/bin/env python3
-# SPDX-License-Identifier: LGPL-2.1+
+# SPDX-License-Identifier: LGPL-2.1+
#
-# systemd is free software; you can redistribute it and/or modify it
-# under the terms of the GNU Lesser General Public License as published by
-# the Free Software Foundation; either version 2.1 of the License, or
-# (at your option) any later version.
+# systemd is free software; you can redistribute it and/or modify it
+# under the terms of the GNU Lesser General Public License as published by
+# the Free Software Foundation; either version 2.1 of the License, or
+# (at your option) any later version.
import os
import sys
#include "capability-util.h"
#include "clock-util.h"
+#include "daemon-util.h"
#include "fd-util.h"
#include "fs-util.h"
+#include "main-func.h"
#include "mkdir.h"
#include "network-util.h"
#include "process-util.h"
return 0;
}
-int main(int argc, char *argv[]) {
+static int run(int argc, char *argv[]) {
+ _cleanup_(notify_on_cleanup) const char *notify_message = NULL;
_cleanup_(manager_freep) Manager *m = NULL;
const char *user = "systemd-timesync";
uid_t uid, uid_current;
umask(0022);
- if (argc != 1) {
- log_error("This program does not take arguments.");
- r = -EINVAL;
- goto finish;
- }
+ if (argc != 1)
+ return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "This program does not take arguments.");
uid = uid_current = geteuid();
gid = getegid();
if (uid_current == 0) {
r = get_user_creds(&user, &uid, &gid, NULL, NULL, 0);
- if (r < 0) {
- log_error_errno(r, "Cannot resolve user name %s: %m", user);
- goto finish;
- }
+ if (r < 0)
+ return log_error_errno(r, "Cannot resolve user name %s: %m", user);
}
r = load_clock_timestamp(uid, gid);
if (r < 0)
- goto finish;
+ return r;
/* Drop privileges, but only if we have been started as root. If we are not running as root we assume all
* privileges are already dropped. */
if (uid_current == 0) {
r = drop_privileges(uid, gid, (1ULL << CAP_SYS_TIME));
if (r < 0)
- goto finish;
+ return log_error_errno(r, "Failed to drop privileges: %m");
}
assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGTERM, SIGINT, -1) >= 0);
r = manager_new(&m);
- if (r < 0) {
- log_error_errno(r, "Failed to allocate manager: %m");
- goto finish;
- }
+ if (r < 0)
+ return log_error_errno(r, "Failed to allocate manager: %m");
r = manager_connect_bus(m);
- if (r < 0) {
- log_error_errno(r, "Could not connect to bus: %m");
- goto finish;
- }
+ if (r < 0)
+ return log_error_errno(r, "Could not connect to bus: %m");
if (clock_is_localtime(NULL) > 0) {
log_info("The system is configured to read the RTC time in the local time zone. "
log_warning_errno(r, "Failed to parse configuration file: %m");
r = manager_parse_fallback_string(m, NTP_SERVERS);
- if (r < 0) {
- log_error_errno(r, "Failed to parse fallback server strings: %m");
- goto finish;
- }
+ if (r < 0)
+ return log_error_errno(r, "Failed to parse fallback server strings: %m");
log_debug("systemd-timesyncd running as pid " PID_FMT, getpid_cached());
- sd_notify(false,
- "READY=1\n"
- "STATUS=Daemon is running");
+
+ notify_message = notify_start("READY=1\n"
+ "STATUS=Daemon is running",
+ NOTIFY_STOPPING);
if (network_is_online()) {
r = manager_connect(m);
if (r < 0)
- goto finish;
+ return r;
}
r = sd_event_loop(m->event);
- if (r < 0) {
- log_error_errno(r, "Failed to run event loop: %m");
- goto finish;
- }
+ if (r < 0)
+ return log_error_errno(r, "Failed to run event loop: %m");
/* if we got an authoritative time, store it in the file system */
if (m->sync) {
log_debug_errno(r, "Failed to touch %s, ignoring: %m", CLOCK_FILE);
}
- sd_event_get_exit_code(m->event, &r);
-
-finish:
- sd_notify(false,
- "STOPPING=1\n"
- "STATUS=Shutting down...");
+ (void) sd_event_get_exit_code(m->event, &r);
- return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
+ return r;
}
+
+DEFINE_MAIN_FUNCTION(run);
#include <linux/ethtool.h>
#include "conf-parser.h"
-#include "missing.h"
+#include "missing_network.h"
struct link_config;
#include "socket-util.h"
#include "strxcpyx.h"
#include "udev-ctrl.h"
+#include "util.h"
/* wire protocol magic must match */
#define UDEV_CTRL_MAGIC 0xdead1dea
#include "netlink-util.h"
#include "path-util.h"
#include "process-util.h"
+#include "rlimit-util.h"
#include "signal-util.h"
#include "stdio-util.h"
#include "string-util.h"
_exit(EXIT_FAILURE);
(void) close_all_fds(NULL, 0);
+ (void) rlimit_nofile_safe();
execve(argv[0], argv, envp);
_exit(EXIT_FAILURE);
if (r < 0)
return log_error_errno(r, "Worker: Failed to enable receiving of device: %m");
- r = safe_fork(NULL, FORK_DEATHSIG, &pid);
+ r = safe_fork("(worker)", FORK_DEATHSIG, &pid);
if (r < 0) {
event->state = EVENT_QUEUED;
return log_error_errno(r, "Failed to fork() worker: %m");
return 0;
/* child */
- setsid();
+ (void) setsid();
r = set_oom_score_adjust(-1000);
if (r < 0)
log_debug("Executing \"%s\"...", strnull(cmd));
}
- r = safe_fork("(loadkeys)", FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_LOG, &pid);
+ r = safe_fork("(loadkeys)", FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_RLIMIT_NOFILE_SAFE|FORK_LOG, &pid);
if (r < 0)
return r;
if (r == 0) {
log_debug("Executing \"%s\"...", strnull(cmd));
}
- r = safe_fork("(setfont)", FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_LOG, &pid);
+ r = safe_fork("(setfont)", FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_RLIMIT_NOFILE_SAFE|FORK_LOG, &pid);
if (r < 0)
return r;
if (r == 0) {
IPv6RapidDeploymentPrefix=
ERSPANIndex=
SerializeTunneledPackets=
+ISATAP=
[VXLAN]
UDP6ZeroChecksumRx=
ARPProxy=
--- /dev/null
+[Match]
+Name=dummy98
+
+[Neighbor]
+Address=2004:da8:1:0::
+MACAddress=00:00:5e:00:02:00
HairPin = true
FastLeave = true
UnicastFlood = true
+MulticastToUnicast = true
FastLeave=
Priority=
AllowPortToBeRoot=
+MulticastToUnicast=
[Match]
KernelVersion=
Type=
SourcePort=
DestinationPort=
IPProtocol=
+InvertRule=
[IPv6PrefixDelegation]
RouterPreference=
DNSLifetimeSec=
EmitDomains=
Managed=
OtherInformation=
+[Neighbor]
+Address=
+MacAddress=
[IPv6AddressLabel]
Label=
Prefix=
GroupForwardMask=
GroupPolicyExtension=
HairPin=
+MulticastToUnicast=
HelloTimeSec=
HomeAddress=
Host=
InitialAdvertisedReceiveWindow=
InitialCongestionWindow=
InputKey=
+InvertRule=
KernelCommandLine=
KernelVersion=
Key=
--- /dev/null
+[Match]
+Name=test1
+
+[RoutingPolicyRule]
+TypeOfService=0x08
+Table=7
+From= 192.168.100.18
+Priority=111
+IPProtocol = tcp
+InvertRule=true
--- /dev/null
+[NetDev]
+Name=isataptun99
+Kind=sit
+
+[Tunnel]
+Local=10.65.223.238
+Remote=10.65.223.239
+ISATAP=true
--- /dev/null
+[Match]
+Name=dummy98
+
+[Neighbor]
+Address=192.168.10.1
+MACAddress=00:00:5e:00:02:65
+
+[Neighbor]
+Address=2004:da8:1:0::1
+MACAddress=00:00:5e:00:02:66
HairPin = true
FastLeave = true
UnicastFlood = true
+MulticastToUnicast = true
--- /dev/null
+[Match]
+Name=dummy98
+
+[Network]
+Tunnel=isataptun99
# systemd-networkd tests
import os
-import sys
-import unittest
-import subprocess
-import time
import re
import shutil
import signal
import socket
+import subprocess
+import sys
import threading
+import time
+import unittest
from shutil import copytree
network_unit_file_path='/run/systemd/network'
with open(os.path.join(os.path.join(os.path.join('/sys/class/net/', link), dev), attribute)) as f:
return f.readline().strip()
+ def read_bridge_port_attr(self, bridge, link, attribute):
+
+ path_bridge = os.path.join('/sys/devices/virtual/net', bridge)
+ path_port = 'lower_' + link + '/brport'
+ path = os.path.join(path_bridge, path_port)
+
+ with open(os.path.join(path, attribute)) as f:
+ return f.readline().strip()
+
def link_exits(self, link):
return os.path.exists(os.path.join('/sys/class/net', link))
os.remove(pid_file)
- def search_words_in_file(self, word):
+ def search_words_in_dnsmasq_log(self, words, show_all=False):
if os.path.exists(dnsmasq_log_file):
with open (dnsmasq_log_file) as in_file:
contents = in_file.read()
- print(contents)
- for part in contents.split():
- if word in part:
+ if show_all:
+ print(contents)
+ for line in contents.split('\n'):
+ if words in line:
in_file.close()
- print("%s, %s" % (word, part))
+ print("%s, %s" % (words, line))
return True
return False
else:
subprocess.check_call('systemctl restart systemd-networkd', shell=True)
time.sleep(5)
+ print()
global ip
global port
class NetworkdNetDevTests(unittest.TestCase, Utilities):
- links =['bridge99', 'bond99', 'bond99', 'vlan99', 'test1', 'macvtap99',
- 'macvlan99', 'ipvlan99', 'vxlan99', 'veth99', 'vrf99', 'tun99',
- 'tap99', 'vcan99', 'geneve99', 'dummy98', 'ipiptun99', 'sittun99', '6rdtun99',
- 'gretap99', 'vtitun99', 'vti6tun99','ip6tnl99', 'gretun99', 'ip6gretap99',
- 'wg99', 'dropin-test', 'erspan-test']
-
- units = ['25-bridge.netdev', '25-bond.netdev', '21-vlan.netdev', '11-dummy.netdev', '21-vlan.network',
- '21-macvtap.netdev', 'macvtap.network', '21-macvlan.netdev', 'macvlan.network', 'vxlan.network',
- '25-vxlan.netdev', '25-ipvlan.netdev', 'ipvlan.network', '25-veth.netdev', '25-vrf.netdev',
- '25-tun.netdev', '25-tun.netdev', '25-vcan.netdev', '25-geneve.netdev', '25-ipip-tunnel.netdev',
- '25-ip6tnl-tunnel.netdev', '25-ip6gre-tunnel.netdev', '25-sit-tunnel.netdev', '25-6rd-tunnel.netdev',
- '25-erspan-tunnel.netdev', '25-gre-tunnel.netdev', '25-gretap-tunnel.netdev', '25-vti-tunnel.netdev',
- '25-vti6-tunnel.netdev', '12-dummy.netdev', 'gre.network', 'ipip.network', 'ip6gretap.network',
- 'gretun.network', 'ip6tnl.network', '25-tap.netdev', 'vti6.network', 'vti.network', 'gretap.network',
- 'sit.network', '25-ipip-tunnel-independent.netdev', '25-wireguard.netdev', '6rd.network', '10-dropin-test.netdev']
+ links =[
+ '6rdtun99',
+ 'bond99',
+ 'bridge99',
+ 'dropin-test',
+ 'dummy98',
+ 'erspan-test',
+ 'geneve99',
+ 'gretap99',
+ 'gretun99',
+ 'ip6gretap99',
+ 'ip6tnl99',
+ 'ipiptun99',
+ 'ipvlan99',
+ 'isataptun99',
+ 'macvlan99',
+ 'macvtap99',
+ 'sittun99',
+ 'tap99',
+ 'test1',
+ 'tun99',
+ 'vcan99',
+ 'veth99',
+ 'vlan99',
+ 'vrf99',
+ 'vti6tun99',
+ 'vtitun99',
+ 'vxlan99',
+ 'wg99']
+
+ units = [
+ '10-dropin-test.netdev',
+ '11-dummy.netdev',
+ '12-dummy.netdev',
+ '21-macvlan.netdev',
+ '21-macvtap.netdev',
+ '21-vlan.netdev',
+ '21-vlan.network',
+ '25-6rd-tunnel.netdev',
+ '25-bond.netdev',
+ '25-bridge.netdev',
+ '25-erspan-tunnel.netdev',
+ '25-geneve.netdev',
+ '25-gretap-tunnel.netdev',
+ '25-gre-tunnel.netdev',
+ '25-ip6gre-tunnel.netdev',
+ '25-ip6tnl-tunnel.netdev',
+ '25-ipip-tunnel-independent.netdev',
+ '25-ipip-tunnel.netdev',
+ '25-ipvlan.netdev',
+ '25-isatap-tunnel.netdev',
+ '25-sit-tunnel.netdev',
+ '25-tap.netdev',
+ '25-tun.netdev',
+ '25-vcan.netdev',
+ '25-veth.netdev',
+ '25-vrf.netdev',
+ '25-vti6-tunnel.netdev',
+ '25-vti-tunnel.netdev',
+ '25-vxlan.netdev',
+ '25-wireguard.netdev',
+ '6rd.network',
+ 'gre.network',
+ 'gretap.network',
+ 'gretun.network',
+ 'ip6gretap.network',
+ 'ip6tnl.network',
+ 'ipip.network',
+ 'ipvlan.network',
+ 'isatap.network',
+ 'macvlan.network',
+ 'macvtap.network',
+ 'sit.network',
+ 'vti6.network',
+ 'vti.network',
+ 'vxlan.network']
def setUp(self):
self.link_remove(self.links)
def test_dropin(self):
self.copy_unit_to_networkd_unit_path('10-dropin-test.netdev')
-
self.start_networkd()
self.assertTrue(self.link_exits('dropin-test'))
def test_vlan(self):
self.copy_unit_to_networkd_unit_path('21-vlan.netdev', '11-dummy.netdev', '21-vlan.network')
-
self.start_networkd()
self.assertTrue(self.link_exits('vlan99'))
output = subprocess.check_output(['ip', '-d', 'link', 'show', 'vlan99']).rstrip().decode('utf-8')
+ print(output)
self.assertTrue(output, 'REORDER_HDR')
self.assertTrue(output, 'LOOSE_BINDING')
self.assertTrue(output, 'GVRP')
def test_macvtap(self):
self.copy_unit_to_networkd_unit_path('21-macvtap.netdev', '11-dummy.netdev', 'macvtap.network')
-
self.start_networkd()
self.assertTrue(self.link_exits('macvtap99'))
def test_macvlan(self):
self.copy_unit_to_networkd_unit_path('21-macvlan.netdev', '11-dummy.netdev', 'macvlan.network')
-
self.start_networkd()
self.assertTrue(self.link_exits('macvlan99'))
@expectedFailureIfModuleIsNotAvailable('ipvlan')
def test_ipvlan(self):
self.copy_unit_to_networkd_unit_path('25-ipvlan.netdev', '11-dummy.netdev', 'ipvlan.network')
-
self.start_networkd()
self.assertTrue(self.link_exits('ipvlan99'))
def test_veth(self):
self.copy_unit_to_networkd_unit_path('25-veth.netdev')
-
self.start_networkd()
self.assertTrue(self.link_exits('veth99'))
def test_dummy(self):
self.copy_unit_to_networkd_unit_path('11-dummy.netdev')
-
self.start_networkd()
self.assertTrue(self.link_exits('test1'))
def test_tun(self):
self.copy_unit_to_networkd_unit_path('25-tun.netdev')
-
self.start_networkd()
self.assertTrue(self.link_exits('tun99'))
def test_tap(self):
self.copy_unit_to_networkd_unit_path('25-tap.netdev')
-
self.start_networkd()
self.assertTrue(self.link_exits('tap99'))
@expectedFailureIfModuleIsNotAvailable('vrf')
def test_vrf(self):
self.copy_unit_to_networkd_unit_path('25-vrf.netdev')
-
self.start_networkd()
self.assertTrue(self.link_exits('vrf99'))
@expectedFailureIfModuleIsNotAvailable('vcan')
def test_vcan(self):
self.copy_unit_to_networkd_unit_path('25-vcan.netdev')
-
self.start_networkd()
self.assertTrue(self.link_exits('vcan99'))
@expectedFailureIfModuleIsNotAvailable('wireguard')
def test_wireguard(self):
self.copy_unit_to_networkd_unit_path('25-wireguard.netdev')
-
self.start_networkd()
if shutil.which('wg'):
def test_geneve(self):
self.copy_unit_to_networkd_unit_path('25-geneve.netdev')
-
self.start_networkd()
self.assertTrue(self.link_exits('geneve99'))
output = subprocess.check_output(['ip', '-d', 'link', 'show', 'geneve99']).rstrip().decode('utf-8')
+ print(output)
self.assertTrue(output, '192.168.22.1')
self.assertTrue(output, '6082')
self.assertTrue(output, 'udpcsum')
self.assertTrue(self.link_exits('dummy98'))
self.assertTrue(self.link_exits('sittun99'))
+ def test_isatap_tunnel(self):
+ self.copy_unit_to_networkd_unit_path('12-dummy.netdev', '25-isatap-tunnel.netdev', 'isatap.network')
+ self.start_networkd()
+
+ self.assertTrue(self.link_exits('dummy98'))
+ self.assertTrue(self.link_exits('isataptun99'))
+
+ output = subprocess.check_output(['ip', '-d', 'link', 'show', 'isataptun99']).rstrip().decode('utf-8')
+ print(output)
+ self.assertRegex(output, "isatap ")
+
def test_6rd_tunnel(self):
self.copy_unit_to_networkd_unit_path('12-dummy.netdev', '25-6rd-tunnel.netdev', '6rd.network')
self.start_networkd()
def test_tunnel_independent(self):
self.copy_unit_to_networkd_unit_path('25-ipip-tunnel-independent.netdev')
-
self.start_networkd()
+
self.assertTrue(self.link_exits('ipiptun99'))
def test_vxlan(self):
self.copy_unit_to_networkd_unit_path('25-vxlan.netdev', 'vxlan.network','11-dummy.netdev')
-
self.start_networkd()
self.assertTrue(self.link_exits('vxlan99'))
output = subprocess.check_output(['ip', '-d', 'link', 'show', 'vxlan99']).rstrip().decode('utf-8')
+ print(output)
self.assertRegex(output, "999")
self.assertRegex(output, '5555')
self.assertRegex(output, 'l2miss')
self.assertRegex(output, 'gbp')
class NetworkdNetWorkTests(unittest.TestCase, Utilities):
- links = ['dummy98', 'test1', 'bond199']
-
- units = ['12-dummy.netdev', 'test-static.network', 'configure-without-carrier.network', '11-dummy.netdev',
- '23-primary-slave.network', '23-test1-bond199.network', '11-dummy.netdev', '23-bond199.network',
- '25-bond-active-backup-slave.netdev', '12-dummy.netdev', '23-active-slave.network',
- 'routing-policy-rule.network', '25-fibrule-port-range.network', '25-address-section.network',
- '25-address-section-miscellaneous.network', '25-route-section.network', '25-route-type.network',
- '25-route-tcp-window-settings.network', '25-route-gateway.network', '25-route-gateway-on-link.network',
- '25-address-link-section.network', '25-ipv6-address-label-section.network', '25-link-section-unmanaged.network',
- '25-sysctl.network', '25-route-reverse-order.network']
+ links = [
+ 'bond199',
+ 'dummy98',
+ 'test1']
+
+ units = [
+ '11-dummy.netdev',
+ '12-dummy.netdev',
+ '23-active-slave.network',
+ '23-bond199.network',
+ '23-primary-slave.network',
+ '23-test1-bond199.network',
+ '25-address-link-section.network',
+ '25-address-section-miscellaneous.network',
+ '25-address-section.network',
+ '25-bond-active-backup-slave.netdev',
+ '25-fibrule-invert.network',
+ '25-fibrule-port-range.network',
+ '25-ipv6-address-label-section.network',
+ '25-neighbor-section.network',
+ '25-link-section-unmanaged.network',
+ '25-route-gateway.network',
+ '25-route-gateway-on-link.network',
+ '25-route-reverse-order.network',
+ '25-route-section.network',
+ '25-route-tcp-window-settings.network',
+ '25-route-type.network',
+ '25-sysctl.network',
+ 'configure-without-carrier.network',
+ 'routing-policy-rule.network',
+ 'test-static.network']
def setUp(self):
self.link_remove(self.links)
self.start_networkd()
self.assertTrue(self.link_exits('dummy98'))
+
output = subprocess.check_output(['networkctl', 'status', 'dummy98']).rstrip().decode('utf-8')
print(output)
self.assertRegex(output, '192.168.0.15')
self.start_networkd()
self.assertTrue(self.link_exits('test1'))
+
output = subprocess.check_output(['networkctl', 'status', 'test1']).rstrip().decode('utf-8')
print(output)
self.assertRegex(output, '192.168.0.15')
self.assertTrue(self.link_exits('dummy98'))
self.assertTrue(self.link_exits('bond199'))
+
output = subprocess.check_output(['ip', '-d', 'link', 'show', 'bond199']).rstrip().decode('utf-8')
print(output)
self.assertRegex(output, 'active_slave dummy98')
self.assertTrue(self.link_exits('test1'))
self.assertTrue(self.link_exits('bond199'))
+
output = subprocess.check_output(['ip', '-d', 'link', 'show', 'bond199']).rstrip().decode('utf-8')
print(output)
self.assertRegex(output, 'primary test1')
self.start_networkd()
self.assertTrue(self.link_exits('test1'))
+
output = subprocess.check_output(['ip', 'rule']).rstrip().decode('utf-8')
print(output)
self.assertRegex(output, '111')
self.assertRegex(output, 'oif test1')
self.assertRegex(output, 'lookup 7')
+ subprocess.call(['ip', 'rule', 'del', 'table', '7'])
+
def test_routing_policy_rule_port_range(self):
self.copy_unit_to_networkd_unit_path('25-fibrule-port-range.network', '11-dummy.netdev')
self.start_networkd()
self.assertTrue(self.link_exits('test1'))
+
output = subprocess.check_output(['ip', 'rule']).rstrip().decode('utf-8')
print(output)
self.assertRegex(output, '111')
self.assertRegex(output, 'tcp')
self.assertRegex(output, 'lookup 7')
+ subprocess.call(['ip', 'rule', 'del', 'table', '7'])
+
+ def test_routing_policy_rule_invert(self):
+ self.copy_unit_to_networkd_unit_path('25-fibrule-invert.network', '11-dummy.netdev')
+ self.start_networkd()
+
+ self.assertTrue(self.link_exits('test1'))
+
+ output = subprocess.check_output(['ip', 'rule']).rstrip().decode('utf-8')
+ print(output)
+ self.assertRegex(output, '111')
+ self.assertRegex(output, 'not.*?from.*?192.168.100.18')
+ self.assertRegex(output, 'tcp')
+ self.assertRegex(output, 'lookup 7')
+
+ subprocess.call(['ip', 'rule', 'del', 'table', '7'])
+
def test_address_preferred_lifetime_zero_ipv6(self):
self.copy_unit_to_networkd_unit_path('25-address-section-miscellaneous.network', '12-dummy.netdev')
self.start_networkd()
print(output)
self.assertRegex(output, '2004:da8:1::/64')
+ def test_ipv6_neighbor(self):
+ self.copy_unit_to_networkd_unit_path('25-neighbor-section.network', '12-dummy.netdev')
+ self.start_networkd()
+
+ self.assertTrue(self.link_exits('dummy98'))
+
+ output = subprocess.check_output(['ip', 'neigh', 'list']).rstrip().decode('utf-8')
+ print(output)
+ self.assertRegex(output, '192.168.10.1.*00:00:5e:00:02:65.*PERMANENT')
+ self.assertRegex(output, '2004:da8:1:0::1.*00:00:5e:00:02:66.*PERMANENT')
+
def test_sysctl(self):
self.copy_unit_to_networkd_unit_path('25-sysctl.network', '12-dummy.netdev')
self.start_networkd()
self.assertEqual(self.read_ipv4_sysctl_attr('dummy98', 'forwarding'),'1')
self.assertEqual(self.read_ipv4_sysctl_attr('dummy98', 'proxy_arp'), '1')
-class NetworkdNetWorkBrideTests(unittest.TestCase, Utilities):
- links = ['dummy98', 'test1', 'bridge99']
+class NetworkdNetWorkBridgeTests(unittest.TestCase, Utilities):
+ links = [
+ 'bridge99',
+ 'dummy98',
+ 'test1']
- units = ['11-dummy.netdev', '12-dummy.netdev', '26-bridge.netdev', '26-bridge-slave-interface-1.network',
- '26-bridge-slave-interface-2.network', 'bridge99.network']
+ units = [
+ '11-dummy.netdev',
+ '12-dummy.netdev',
+ '26-bridge.netdev',
+ '26-bridge-slave-interface-1.network',
+ '26-bridge-slave-interface-2.network',
+ 'bridge99.network']
def setUp(self):
self.link_remove(self.links)
output = subprocess.check_output(['bridge', '-d', 'link', 'show', 'dummy98']).rstrip().decode('utf-8')
print(output)
- self.assertRegex(output, 'cost 400')
- self.assertRegex(output, 'hairpin on')
- self.assertRegex(output, 'flood on')
- self.assertRegex(output, 'fastleave on')
+ self.assertEqual(self.read_bridge_port_attr('bridge99', 'dummy98', 'hairpin_mode'), '1')
+ self.assertEqual(self.read_bridge_port_attr('bridge99', 'dummy98', 'path_cost'), '400')
+ self.assertEqual(self.read_bridge_port_attr('bridge99', 'dummy98', 'unicast_flood'), '1')
+ self.assertEqual(self.read_bridge_port_attr('bridge99', 'dummy98', 'multicast_fast_leave'), '1')
+
+ # CONFIG_BRIDGE_IGMP_SNOOPING=y
+ if (os.path.exists('/sys/devices/virtual/net/bridge00/lower_dummy98/brport/multicast_to_unicast')):
+ self.assertEqual(self.read_bridge_port_attr('bridge99', 'dummy98', 'multicast_to_unicast'), '1')
class NetworkdNetWorkLLDPTests(unittest.TestCase, Utilities):
links = ['veth99']
- units = ['23-emit-lldp.network', '24-lldp.network', '25-veth.netdev']
+ units = [
+ '23-emit-lldp.network',
+ '24-lldp.network',
+ '25-veth.netdev']
def setUp(self):
self.link_remove(self.links)
class NetworkdNetworkRATests(unittest.TestCase, Utilities):
links = ['veth99']
- units = ['25-veth.netdev', 'ipv6-prefix.network', 'ipv6-prefix-veth.network']
+ units = [
+ '25-veth.netdev',
+ 'ipv6-prefix.network',
+ 'ipv6-prefix-veth.network']
def setUp(self):
self.link_remove(self.links)
self.assertRegex(output, '2002:da8:1:0')
class NetworkdNetworkDHCPServerTests(unittest.TestCase, Utilities):
- links = ['veth99', 'dummy98']
-
- units = ['25-veth.netdev', 'dhcp-client.network', 'dhcp-server.network', '12-dummy.netdev', '24-search-domain.network',
- 'dhcp-client-timezone-router.network', 'dhcp-server-timezone-router.network']
+ links = [
+ 'dummy98',
+ 'veth99']
+
+ units = [
+ '12-dummy.netdev',
+ '24-search-domain.network',
+ '25-veth.netdev',
+ 'dhcp-client.network',
+ 'dhcp-client-timezone-router.network',
+ 'dhcp-server.network',
+ 'dhcp-server-timezone-router.network']
def setUp(self):
self.link_remove(self.links)
self.assertTrue(self.link_exits('veth99'))
- time.sleep(5)
-
output = subprocess.check_output(['networkctl', 'status', 'veth99']).rstrip().decode('utf-8')
print(output)
self.assertRegex(output, '192.168.5.*')
self.assertRegex(output, 'Europe/Berlin')
class NetworkdNetworkDHCPClientTests(unittest.TestCase, Utilities):
- links = ['veth99', 'dummy98']
-
- units = ['25-veth.netdev', 'dhcp-server-veth-peer.network','dhcp-client-ipv6-only.network',
- 'dhcp-client-ipv4-only-ipv6-disabled.network', 'dhcp-client-ipv4-only.network',
- 'dhcp-client-ipv4-dhcp-settings.network', 'dhcp-client-anonymize.network',
- 'dhcp-client-ipv6-rapid-commit.network', 'dhcp-client-route-table.network',
- 'dhcp-v4-server-veth-peer.network', 'dhcp-client-listen-port.network',
- 'dhcp-client-route-metric.network', 'dhcp-client-critical-connection.network']
+ links = [
+ 'dummy98',
+ 'veth99']
+
+ units = [
+ '25-veth.netdev',
+ 'dhcp-client-anonymize.network',
+ 'dhcp-client-critical-connection.network',
+ 'dhcp-client-ipv4-dhcp-settings.network',
+ 'dhcp-client-ipv4-only-ipv6-disabled.network',
+ 'dhcp-client-ipv4-only.network',
+ 'dhcp-client-ipv6-only.network',
+ 'dhcp-client-ipv6-rapid-commit.network',
+ 'dhcp-client-listen-port.network',
+ 'dhcp-client-route-metric.network',
+ 'dhcp-client-route-table.network',
+ 'dhcp-server-veth-peer.network',
+ 'dhcp-v4-server-veth-peer.network']
def setUp(self):
self.link_remove(self.links)
print(output)
self.assertRegex(output, 'default.*dev veth99 proto dhcp')
- self.search_words_in_file('vendor class: SusantVendorTest')
- self.search_words_in_file('client MAC address: 12:34:56:78:9a:bc')
- self.search_words_in_file('client provides name: test-hostname')
- self.search_words_in_file('26:mtu')
+ self.assertTrue(self.search_words_in_dnsmasq_log('vendor class: SusantVendorTest', True))
+ self.assertTrue(self.search_words_in_dnsmasq_log('DHCPDISCOVER(veth-peer) 12:34:56:78:9a:bc'))
+ self.assertTrue(self.search_words_in_dnsmasq_log('client provides name: test-hostname'))
+ self.assertTrue(self.search_words_in_dnsmasq_log('26:mtu'))
def test_dhcp6_client_settings_rapidcommit_true(self):
self.copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-ipv6-only.network')
output = subprocess.check_output(['ip', 'address', 'show', 'dev', 'veth99']).rstrip().decode('utf-8')
print(output)
self.assertRegex(output, '12:34:56:78:9a:bc')
-
- self.assertTrue(self.search_words_in_file('14:rapid-commit'))
+ self.assertTrue(self.search_words_in_dnsmasq_log('14:rapid-commit', True))
def test_dhcp6_client_settings_rapidcommit_false(self):
self.copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-ipv6-rapid-commit.network')
output = subprocess.check_output(['ip', 'address', 'show', 'dev', 'veth99']).rstrip().decode('utf-8')
print(output)
self.assertRegex(output, '12:34:56:78:9a:bc')
-
- self.assertFalse(self.search_words_in_file('14:rapid-commit'))
+ self.assertFalse(self.search_words_in_dnsmasq_log('14:rapid-commit', True))
def test_dhcp_client_settings_anonymize(self):
self.copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-anonymize.network')
self.assertTrue(self.link_exits('veth99'))
self.start_dnsmasq()
- self.assertFalse(self.search_words_in_file('VendorClassIdentifier=SusantVendorTest'))
- self.assertFalse(self.search_words_in_file('test-hostname'))
- self.assertFalse(self.search_words_in_file('26:mtu'))
+
+ self.assertFalse(self.search_words_in_dnsmasq_log('VendorClassIdentifier=SusantVendorTest', True))
+ self.assertFalse(self.search_words_in_dnsmasq_log('test-hostname'))
+ self.assertFalse(self.search_words_in_dnsmasq_log('26:mtu'))
def test_dhcp_client_listen_port(self):
self.copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-listen-port.network')
+
dh_server = DHCPServer("dhcp_server")
dh_server.start()
def test_dhcp_route_table_id(self):
self.copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-v4-server-veth-peer.network', 'dhcp-client-route-table.network')
self.start_networkd()
- self.start_dnsmasq()
self.assertTrue(self.link_exits('veth99'))
+ self.start_dnsmasq()
+
output = subprocess.check_output(['ip', 'route', 'show', 'table', '12']).rstrip().decode('utf-8')
print(output)
-
self.assertRegex(output, 'veth99 proto dhcp')
self.assertRegex(output, '192.168.5.1')
def test_dhcp_route_metric(self):
self.copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-v4-server-veth-peer.network', 'dhcp-client-route-metric.network')
self.start_networkd()
- self.start_dnsmasq()
self.assertTrue(self.link_exits('veth99'))
+ self.start_dnsmasq()
+
output = subprocess.check_output(['ip', 'route', 'show', 'dev', 'veth99']).rstrip().decode('utf-8')
print(output)
-
self.assertRegex(output, 'metric 24')
def test_dhcp_route_criticalconnection_true(self):
self.copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-v4-server-veth-peer.network', 'dhcp-client-critical-connection.network')
self.start_networkd()
- self.start_dnsmasq()
self.assertTrue(self.link_exits('veth99'))
+ self.start_dnsmasq()
+
output = subprocess.check_output(['networkctl', 'status', 'veth99']).rstrip().decode('utf-8')
print(output)
-
self.assertRegex(output, '192.168.5.*')
+
# Stoping dnsmasq as networkd won't be allowed to renew the DHCP lease.
self.stop_dnsmasq(dnsmasq_pid_file)
#!/usr/bin/env python3
-# -*- Mode: python; coding: utf-8; indent-tabs-mode: nil -*- */
# SPDX-License-Identifier: MIT
#
# This file is distributed under the MIT license, see below.
#!/usr/bin/env python3
-# -*- Mode: python; coding: utf-8; indent-tabs-mode: nil -*- */
# SPDX-License-Identifier: LGPL-2.1+
from __future__ import print_function
d = gdb.parse_and_eval("hashmap_debug_list")
all_entry_sizes = gdb.parse_and_eval("all_entry_sizes")
all_direct_buckets = gdb.parse_and_eval("all_direct_buckets")
- hashmap_base_t = gdb.lookup_type("HashmapBase")
uchar_t = gdb.lookup_type("unsigned char")
ulong_t = gdb.lookup_type("unsigned long")
debug_offset = gdb.parse_and_eval("(unsigned long)&((HashmapBase*)0)->debug")
#!/usr/bin/env python3
+# SPDX-License-Identifier: LGPL-2.1+
-"""Generate %-from-name.gperf from %-list.txt
+"""
+Generate %-from-name.gperf from %-list.txt
"""
import sys
#!/usr/bin/env python3
-# -*- Mode: python; coding: utf-8; indent-tabs-mode: nil -*- */
# SPDX-License-Identifier: LGPL-2.1+
import sys
#!/usr/bin/env python3
-# -*- Mode: python; coding: utf-8; indent-tabs-mode: nil -*- */
# SPDX-License-Identifier: LGPL-2.1+
import collections
#!/usr/bin/env python3
-# -*- Mode: python; coding: utf-8; indent-tabs-mode: nil -*- */
-# SPDX-License-Identifier: LGPL-2.1+
+# SPDX-License-Identifier: LGPL-2.1+
from __future__ import print_function
import collections
#!/usr/bin/env python3
-# -*- Mode: python; coding: utf-8; indent-tabs-mode: nil -*- */
-# SPDX-License-Identifier: LGPL-2.1+
+# SPDX-License-Identifier: LGPL-2.1+
from lxml import etree as tree
--- /dev/null
+#!/bin/bash
+
+# Run this script from the root of the systemd's git repository
+# or set REPO_ROOT to a correct path.
+#
+# Example execution on Fedora:
+# dnf install docker
+# systemctl start docker
+# export CONT_NAME="my-fancy-container"
+# travis-ci/managers/debian.sh SETUP RUN CLEANUP
+
+PHASES=(${@:-SETUP RUN RUN_ASAN CLEANUP})
+DEBIAN_RELEASE="${DEBIAN_RELEASE:-testing}"
+CONT_NAME="${CONT_NAME:-debian-$DEBIAN_RELEASE-$RANDOM}"
+DOCKER_EXEC="${DOCKER_EXEC:-docker exec -it $CONT_NAME}"
+DOCKER_RUN="${DOCKER_RUN:-docker run}"
+REPO_ROOT="${REPO_ROOT:-$PWD}"
+ADDITIONAL_DEPS=(python3-libevdev python3-pyparsing clang)
+
+function info() {
+ echo -e "\033[33;1m$1\033[0m"
+}
+
+set -e
+
+source "$(dirname $0)/travis_wait.bash"
+
+for phase in "${PHASES[@]}"; do
+ case $phase in
+ SETUP)
+ info "Setup phase"
+ info "Using Debian $DEBIAN_RELEASE"
+ printf "FROM debian:$DEBIAN_RELEASE\nRUN bash -c 'apt-get -y update && apt-get install -y systemd'\n" | docker build -t debian-with-systemd/latest -
+ info "Starting container $CONT_NAME"
+ $DOCKER_RUN -v $REPO_ROOT:/build:rw \
+ -w /build --privileged=true --name $CONT_NAME \
+ -dit --net=host debian-with-systemd/latest /usr/bin/systemd
+ $DOCKER_EXEC bash -c "echo deb-src http://deb.debian.org/debian $DEBIAN_RELEASE main >>/etc/apt/sources.list"
+ $DOCKER_EXEC apt-get -y update
+ $DOCKER_EXEC apt-get -y build-dep systemd
+ $DOCKER_EXEC apt-get -y install "${ADDITIONAL_DEPS[@]}"
+ # overlayfs on TravisCI is having trouble delivering inotify events to test-path and test-event.
+ # Let's use tmpfs instead for now.
+ $DOCKER_EXEC mount -t tmpfs tmpfs /tmp
+ ;;
+ RUN)
+ info "Run phase"
+ $DOCKER_EXEC meson --werror -Dtests=unsafe -Dslow-tests=true -Dsplit-usr=true build
+ $DOCKER_EXEC ninja -v -C build
+ $DOCKER_EXEC ninja -C build test
+ $DOCKER_EXEC tools/check-directives.sh
+ ;;
+ RUN_CLANG)
+ docker exec -e CC=clang -e CXX=clang++ -it $CONT_NAME meson --werror -Dtests=unsafe -Dslow-tests=true -Dsplit-usr=true build
+ $DOCKER_EXEC ninja -v -C build
+ $DOCKER_EXEC ninja -C build test
+ ;;
+ RUN_ASAN|RUN_CLANG_ASAN)
+ if [[ "$phase" = "RUN_CLANG_ASAN" ]]; then
+ ENV_VARS="-e CC=clang -e CXX=clang++"
+ MESON_ARGS="-Db_lundef=false" # See https://github.com/mesonbuild/meson/issues/764
+ fi
+ docker exec $ENV_VARS -it $CONT_NAME meson --werror -Dtests=unsafe -Db_sanitize=address,undefined -Dsplit-usr=true $MESON_ARGS build
+ $DOCKER_EXEC ninja -v -C build
+
+ # Never remove halt_on_error from UBSAN_OPTIONS. See https://github.com/systemd/systemd/commit/2614d83aa06592aedb.
+ travis_wait docker exec --interactive=false \
+ -e UBSAN_OPTIONS=print_stacktrace=1:print_summary=1:halt_on_error=1 \
+ -e ASAN_OPTIONS=strict_string_checks=1:detect_stack_use_after_return=1:check_initialization_order=1:strict_init_order=1 \
+ -e "TRAVIS=$TRAVIS" \
+ -t $CONT_NAME \
+ meson test --timeout-multiplier=3 -C ./build/ --print-errorlogs
+ ;;
+ CLEANUP)
+ info "Cleanup phase"
+ docker stop $CONT_NAME
+ docker rm -f $CONT_NAME
+ ;;
+ *)
+ echo >&2 "Unknown phase '$phase'"
+ exit 1
+ esac
+done