36 Commits
v1.1 ... v1.6

Author SHA1 Message Date
Tore Anderson
ff6aa57c4b Release clatd v1.6
Also update copyright year to 2023.
2023-03-05 11:33:00 +01:00
Tore Anderson
a416278570 Make NM/systemd integration more robust
This fixed the following dependency loop that could occur when the
system was booting up:

1. NetworkManager configures a network interface and fires off the clatd
   dispatcher script.
2. The dispatcher scripts tries to restart `clatd.service`.
3. However, `clatd.service` cannot be (re)started at this point because
   its dependency `network-online.target` has not yet been reached.
4. Therefore, the `systemctl restart clatd.service` command in the
   dispatcher script blocks, waiting for `network-online.target` to be
   reached.
5. But that won't happen until the dispatcher scripts finishes...

Adding `--no-block` allows the dispatcher script to finish immediately
without waiting for the restart to complete (instead, systemd will do it
in the background once `network-online.target` has been reached).

Furthermore, since `clatd.service` may end up being restarted several
times during a boot process (especially on a system with many network
interfaces handled by NetworkManager), it is also at risk of
inadvertently triggering the restart rate-limiting feature in systemd,
so disable that while we're at it.

Closes #22. Thanks to @patrakov for the report!
2023-03-05 10:58:29 +01:00
Michal Josef Špaček
4583c592d8 Rewrite obsolete module usage to new one (#20)
Perl module IO::Socket::INET6 is obsolete and recomended one is
IO::Socket::IP, which has compatibility to old one.

btw: Net::DNS was rewrited to use IO::Socket::IP.
2022-11-08 14:43:50 +01:00
Thomas Schäfer
41a312f908 Update Makefile (#14)
Correct iproute2 package name for Debian-based distributions.
2020-02-27 09:23:54 +01:00
Tore Anderson
66e1e5fc28 Bump version to v1.5
Most important change is 19c4042 - necessary to support newer Linux kernels.
2019-05-20 10:19:56 +02:00
Tore Anderson
1441a3ff4b Copyright year update to 2019 2019-05-20 10:18:56 +02:00
Tore Anderson
19c4042f1e Strip prefix length before route lookup for $plat_prefix
Recent Linux kernels have removed the ability to do a `ip -6 route get` lookup
for destinations with a prefix length:

https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=0eff0a274104487938d741b5c37aca1795afd184

Strip the prefix length before doing this lookup, so that it is done for the
first address in `$plat_prefix` instead.

Closes #12.
2019-05-20 09:13:05 +02:00
Tore Anderson
888e30bd2b Copyright year update to 2018 2018-12-14 23:59:01 +01:00
Tore Anderson
b8f583a4e0 Correctly detect PLAT prefixes containing embedded WKAs
The previous code would fail to detect PLAT prefix if ipv4only.arpa resolved to
an address such as 2001:db8:c000:aa::c000:aa. It would get confused as to
whether the prefix was 2001:db8::/32 (incorrect) or 2001:db8:c000:aa::/96
(correct).

Bug reported by Kasper Dupont - thanks!
2018-12-14 23:48:32 +01:00
Tore Anderson
c228c2bb64 Copyright year update to 2017 2017-08-15 18:15:31 +02:00
Tore Anderson
ebd8487dd0 README: typofixes 2017-08-15 18:14:37 +02:00
Tore Anderson
1218ca7979 Remove doc saying TAYGA will be auto-built
Now that TAYGA is avaiable in EPEL, it is better to point people at that
instead of building TAYGA from source. In commit 18dca08 the build from source
functionality was removed. Update documentation accordingly.
2017-08-15 18:11:39 +02:00
Tore Anderson
3f73b5281e Makefile: Add DESTDIR, PREFIX and SYSCONFDIR variables
These variables can be used to control exactly where clatd gets installed.

Requested by @ingvarha.

Closes: #8
2017-08-15 18:00:47 +02:00
Tore Anderson
6c7c2d2a92 Don't hardcode commands paths
Don't assume that utilities such as systemctl or initctl is found in a certain
specific path. Instead look for them in $PATH. This applies to both the
Makefile and the NetworkManager dispatcher script.

Resolves #11.
2017-08-15 17:46:54 +02:00
Tore Anderson
18dca086c2 Update siit-dc/eam I-D references to RFC numbers
The three I-Ds that describe SIIT-DC and SIIT-EAM have been published as
RFCs, so update the references accordingly. Also update once occurrence
of old terminology ("Host Agent") with the new and final one ("Edge
Relay").
2016-03-28 08:38:56 +02:00
Tore Anderson
fb4587bfd6 nm-dispatcher: only act on iface up/down events
Ensure other events (like hostname changes, DHCP lease renewals, etc.)
are ignored as they are very unlikely to be relevant for clatd.
2016-03-28 08:26:20 +02:00
Tore Anderson
1abcec1285 Minor documentation fixes 2016-01-28 13:40:05 +01:00
Tore Anderson
9a1a4ae797 2016 licence update
Change "2014-2015" with "2014-2016". Also, I had forgotten to update the
licence comment in the clatd script itself in b5725c0, so fix that too.
Thanks to @ingvarha for noticing!
2016-01-28 11:55:02 +01:00
Tore Anderson
aa92cb0287 Bump version to v1.4 2015-10-23 13:43:34 +02:00
Tore Anderson
5e2297903a Improve handing of single-scalar calls to cmd()
Just pass the entire supplied command line, be it a single scalar or an array,
to system(). It'll do the right thing with it. This gets rid of a spurious
trailing space in debugging output when cmd() was called with a single scalar
as the command argument (leaving @cmdline undefined).
2015-10-23 11:49:51 +02:00
Tore Anderson
f976f46b57 Correct debug output for cfg() and cfgint() 2015-10-23 11:35:03 +02:00
Tore Anderson
e8cb719f10 Insert the effective default advmss into %CFG
This ensures that the effective value (rather than the configured value or lack
thereof) is available in the environment of script-up/down.
2015-10-23 11:33:35 +02:00
Tore Anderson
0bc3bbd797 New feature: script-up/down
Adds the possibility of making clatd run a custom script while starting up or
shutting down.
2015-10-23 11:22:00 +02:00
Tore Anderson
a80e2f30ab New feature: Set advmss on IPv4 default route
This ensures that TCP connections terminated through the CLAT gets a sensible
TCP MSS value negotiated. By default, the value is set to the MTU of the
defaultroute minus 40. There should be no reason to change this in the vast
majority of cases, but it can be overridden with the "v4-defaultroute-advmss"
setting.
2015-10-22 11:58:19 +02:00
Tore Anderson
9f1789f34d New feature: Replace original IPv4 default route
Adds "v4-defaultroute-replace" config/command-line setting (default disabled).
When enabled, it will unconditionally disable the pre-flight IPv4 connectivity
check, and ensure that any pre-existing IPv4 default routes are removed during
startup (and presumably replaced with the one pointing to the CLAT, unless
"v4-defaultroute-enable" has been disabled). Any IPv4 default routes that were
removed in this manner are restored when clatd is shutting down.
2015-10-22 11:12:34 +02:00
Tore Anderson
2f2a59ddf3 v1.3: new licence => new release 2015-07-23 13:40:17 +02:00
Tore Anderson
b5725c093c relicence to MIT to make lrintel happy 2015-07-23 13:38:30 +02:00
Tore Anderson
ad114b18cf Update for siit-dc ietf changes
- the siit-dc drafts have been adopted by the v6ops wg
- host agent renamed to edge relay
2015-07-23 13:29:28 +02:00
Tore Anderson
c48ad644c0 Avoid a restart loop with NM dispatcher scripts
Newer NetworkManager versions will run the dispatcher scripts when new
unknown interfaces show up, including 'clat'. That will cause a clatd
restart right after startup, and we'll never get to fully initialise. So
ensure the dispatcher script does nothing if the device in question is
our own 'clat' to prevent this.
2014-10-05 20:27:07 +02:00
Tore Anderson
81f2c61364 Generate random IIDs if no EUI-64 address is found
This allows clatd to work correctly on 3GPP mobile networks, where the
IID is assigned from the network, rather than being generated using
EUI-64. We still prefer the old method, though, the random one is only
used if no EUI-64 address exists on the PLAT device. Update docs
accordingly.

Also upgrade docs to better describe usage as a SIIT-DC Host Agent.
2014-10-05 20:14:01 +02:00
Tore Anderson
54dd5ac854 Replace I-D.draft-byrne-v6ops-clatip with RFC 7335
I-D.draft-byrne-v6ops-clatip has been published as RFC 7335, update
documentation and comments accordingly.
2014-10-05 17:14:03 +02:00
Tore Anderson
6f359a8d60 Minor spelling and punctuation fixes 2014-06-29 13:46:09 +02:00
Tore Anderson
058061525e Fix a misspelling 2014-06-29 13:40:44 +02:00
Tore Anderson
2d2cbd8c19 Reflow a couple of lines to fit within 80 chars 2014-06-29 13:38:45 +02:00
Tore Anderson
85002b6a26 Fix truncated comment documenting readconf() 2014-06-29 13:32:56 +02:00
Tore Anderson
da7b48e779 Avoid using a bogus CLAT address if no EUI-64
get_clat_v6_addr() didn't actually check if it saw any Modified EUI-64
based addresses on the PLAT device before proceeding. This caused it to
return a bogus CLAT address (::c1:a700:0) instead of failing with a
useful error message.
2014-06-29 13:27:53 +02:00
6 changed files with 387 additions and 111 deletions

22
LICENCE
View File

@@ -1,5 +1,19 @@
Copyright (c) 2014 Tore Anderson <tore@fud.no>
Copyright (c) 2014-2023 Tore Anderson <tore@fud.no>
As long as you retain this notice, you may use this piece of software as
you wish. If you like it, and we happen to meet one day, you can buy me
a beer in return. If you really like it, make it an IPA.
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do
so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@@ -1,20 +1,30 @@
DESTDIR=
PREFIX=/usr
SYSCONFDIR=/etc
APT_GET:=$(shell which apt-get)
DNF_OR_YUM:=$(shell which dnf || which yum)
INITCTL:=$(shell which initctl)
SYSTEMCTL:=$(shell which systemctl)
TAYGA:=$(shell which tayga)
install:
# Install the main script to /usr/sbin
install -m0755 clatd /usr/sbin/clatd
# Install the main script
install -m0755 clatd $(DESTDIR)$(PREFIX)/sbin/clatd
# Install manual page if pod2man is installed
pod2man --name clatd --center "clatd - a CLAT implementation for Linux" --section 8 README.pod /usr/share/man/man8/clatd.8 && gzip -f9 /usr/share/man/man8/clatd.8 || echo "pod2man is required to generate manual page"
pod2man --name clatd --center "clatd - a CLAT implementation for Linux" --section 8 README.pod $(DESTDIR)$(PREFIX)/share/man/man8/clatd.8 && gzip -f9 $(DESTDIR)$(PREFIX)/share/man/man8/clatd.8 || echo "pod2man is required to generate manual page"
# Install systemd service file if applicable for this system
if test -x /usr/bin/systemctl && test -d "/etc/systemd/system"; then install -m0644 scripts/clatd.systemd /etc/systemd/system/clatd.service && systemctl daemon-reload; fi
if test -e "/etc/systemd/system/clatd.service" && test ! -e "/etc/systemd/system/multi-user.target.wants/clatd.service"; then systemctl enable clatd.service; fi
if test -x "$(SYSTEMCTL)" && test -d "$(DESTDIR)$(SYSCONFDIR)/systemd/system"; then install -m0644 scripts/clatd.systemd $(DESTDIR)$(SYSCONFDIR)/systemd/system/clatd.service && $(SYSTEMCTL) daemon-reload; fi
if test -e "$(DESTDIR)$(SYSCONFDIR)/systemd/system/clatd.service" && test ! -e "$(DESTDIR)$(SYSCONFDIR)/systemd/system/multi-user.target.wants/clatd.service"; then $(SYSTEMCTL) enable clatd.service; fi
# Install upstart service file if applicable for this system
if test -x /sbin/initctl && test -d "/etc/init"; then install -m0644 scripts/clatd.upstart /etc/init/clatd.conf; fi
if test -x "$(INITCTL)" && test -d "$(DESTDIR)$(SYSCONFDIR)/init"; then install -m0644 scripts/clatd.upstart $(DESTDIR)$(SYSCONFDIR)/init/clatd.conf; fi
# Install NetworkManager dispatcher script if applicable
if test -d /etc/NetworkManager/dispatcher.d; then install -m0755 scripts/clatd.networkmanager /etc/NetworkManager/dispatcher.d/50-clatd; fi
if test -d $(DESTDIR)$(SYSCONFDIR)/NetworkManager/dispatcher.d; then install -m0755 scripts/clatd.networkmanager $(DESTDIR)$(SYSCONFDIR)/NetworkManager/dispatcher.d/50-clatd; fi
installdeps:
# .deb/apt-get based distros
if test -x /usr/bin/apt-get; then apt-get -y install perl-base perl-modules libnet-ip-perl libnet-dns-perl libio-socket-inet6-perl iproute iptables tayga; fi
# .rpm/YUM-based distros
if test -x /usr/bin/yum; then yum -y install perl perl-Net-IP perl-Net-DNS perl-IO-Socket-INET6 perl-File-Temp iproute iptables; fi
# to get TAYGA on .rpm/YUM-based distros, we unfortunately need to install from source
if test -x /usr/bin/yum && test ! -x /usr/sbin/tayga; then echo "TAYGA isn't packaged for YUM-based distros, will download and compile the source in 5 seconds (^C interrupts)" && sleep 5 && yum -y install gcc tar wget bzip2 && wget http://www.litech.org/tayga/tayga-0.9.2.tar.bz2 && bzcat tayga-0.9.2.tar.bz2 | tar x && cd tayga-0.9.2 && ./configure --prefix=/usr && make && make install && rm -rf ../tayga-0.9.2.tar.bz2 ../tayga-0.9.2; fi
if test -x "$(APT_GET)"; then $(APT_GET) -y install perl-base perl-modules libnet-ip-perl libnet-dns-perl libio-socket-ip-perl iproute2 iptables tayga; fi
# .rpm/DNF/YUM-based distros
if test -x "$(DNF_OR_YUM)"; then $(DNF_OR_YUM) -y install perl perl-Net-IP perl-Net-DNS perl-IO-Socket-IP perl-File-Temp iproute iptables; fi
# If necessary, try to install the TAYGA .rpm using dnf/yum. It is unfortunately not available in all .rpm based distros (in particular CentOS/RHEL).
if test -x "$(DNF_OR_YUM)" && test ! -x "$(TAYGA)"; then $(DNF_OR_YUM) -y install tayga || echo "ERROR: Failed to install TAYGA using dnf/yum, the package is probably not included in your distro. Try enabling the EPEL repo <URL: https://fedoraproject.org/wiki/EPEL> and try again, or install TAYGA <URL: http://www.litech.org/tayga> directly from source."; exit 1; fi

View File

@@ -1,6 +1,6 @@
=head1 NAME
B<clatd> - a CLAT implementation for Linux
B<clatd> - a CLAT / SIIT-DC Edge Relay implementation for Linux
=head1 DESCRIPTION
@@ -13,11 +13,12 @@ local applications on the host requires actual IPv4 connectivity or cannot
make use of DNS64 (for example because they use legacy AF_INET socket calls,
or if they are simply not using DNS64).
It may also be used in combination with a stateless PLAT as defined by
I<I-D.anderson-siit-dc> to give the otherwise IPv6-only host a public IPv4
address with connectivity to the IPv4 internet. This may be useful in a
server environment that are using legacy IPv4-only applications as described
above.
B<clatd> may also be used to implement an SIIT-DC Edge Relay as described in
I<RFC 7756>. In this scenario, the PLAT is in reality a SIIT-DC Border Relay
(see I<RFC 7755>) instead of a Stateful NAT64 (see I<RFC6146>). When used as a
SIIT-DC Edge Relay, you will probably want to manually configure the settings
I<clat-v4-addr>, I<clat-v6-addr>, and I<plat-prefix> to mirror the SIIT-DC
Border Relay's configuration.
It relies on the software package TAYGA by Nathan Lutchansky for the actual
translation of packets between IPv4 and IPv6 (I<RFC 6145>) TAYGA may be
@@ -33,7 +34,7 @@ B<clatd> [options]
=item -q
Quiet mode; suppress normal output This is the same as setting B<quiet=1>.
Quiet mode; suppress normal output. This is the same as setting B<quiet=1>.
Warnings and errors are still outputted, to silence those too, repeat I<-q>.
=item -d
@@ -86,21 +87,21 @@ of B<clatd> and its dependencies:
This will install B<clatd> to /usr/sbin, plus install systemd, upstart, and/or
NetworkManager scripts if your distribution appears to be using them, and
install all the dependencies. Note that TAYGA isn't available in RPM format,
so on RedHat/Fedora the installdeps target will install gcc and attempt to
compile TAYGA from source.
install all the dependencies. Note that TAYGA isn't available in all RPM-based
distros (in particular RHEL and its clones). It is however available in EPEL
(see L<https://fedoraproject.org/wiki/EPEL>).
=head1 CONFIGURATION
B<clatd> is designed to be able to run without any user-supplied configuration
in most cases. However, user-specified onfiguration settings may be added to
in most cases. However, user-specified configuration settings may be added to
the configuration file, the path to which may be given on the command line
using the I<-c> option, or if it is not, the default location
I</etc/clatd.conf> is used. Configuration settings may also be given directly
on the command line when starting B<clatd>, which takes precedence over settings
in the configuration file.
Settings are of the form B<key=value>. A list of recogniced keys and their
Settings are of the form B<key=value>. A list of recognised keys and their
possible values follow below:
=over
@@ -118,6 +119,57 @@ Set this to 1 to get debugging output from B<clatd>, or 2 to get even more of
the stuff. These are the equivalent of providing the command line option I<-d>
the specified number of times.
=item B<script-up=string> (no default)
Specify a custom script to be run when B<clatd> is starting up. The invocation
of this script is the last thing that happens before TAYGA starts up, so all
the preparations have been completed at that point (i.e., the B<clat-dev>
exists and has routing/addressing configured, forwarding has been enabled, and
so on).
The script is run by the system shell, so you can do everything you could in an
interactive shell: run multiple commands by separating them by semi-colon or
double ampersands, use standard if/else statements, use variable substitutions,
redirect output to files, set up command pipelines, and so on. However it must
all be on one line, so if you want to do complex things or use some other
programming language it's probably better to put the script itself in a
separate executable file and just make B<script-up> invoke that file instead.
If the script returns a nonzero exit status, this is considered a fatal error,
and B<clatd> will abort. This can be prevented by appending I<|| true> at the
end of the script.
All of B<clatd>'s configuration settings are available as standard variables in
the script's environment (hyphens are replaced with underscores).
Logging or debug messages from the script may simply be sent to stdout, where
it will be picked up by the init system along with B<clatd>'s own output. The
script may of course consult the I<$quiet> and I<$debug> environment variables
in order to determine how much output is appropriate.
The script should not be enclosed in quotes in the configuration file (even
though it contains whitespace). For example:
B<script-up=echo `date -Ins`: clatd started on $clat_dev | tee -a ~/clatd.log>
If on the other hand you want to supply a B<script-up> containing whitespace
directly B<clatd>'s command line, quoting is required in order to prevent the
shell from splitting it up and into multiple command line arguments. For
example:
B<clatd 'script-up=ip route add 192.0.2.0/24 dev $clat_dev || true'>
=item B<script-down=string> (no default)
This works exactly the same as B<script-up>, only that this script is run right
after TAYGA has exited, before the clean-up process of restoring any settings
that were changed.
An unsuccessful exit code from B<script-down> will cause B<clatd> to exit
unsuccessfully too. Beyond that an unsuccessful exit won't change anything,
because B<script-down> is invoked at a point in time where the only thing left
for B<clatd> to do is to clean up after itself and exit anyway.
=item B<clat-dev=string> (default: I<clat>)
The name of the network device used by the CLAT. There should be no reason to
@@ -129,22 +181,40 @@ simultaneously.
The IPv4 address that will be assigned to the CLAT device. Local applications
will bind to this address when communicating with external IPv4 destinations.
In a standard 464XLAT environment with a stateful NAT64 serving as the PLAT,
there should be no need to change the default, but if the PLAT is a stateless
translator (a la I-D.draft-anderson-siit-dc), you might want to set this to
the true external address used externally, so the the local applications can
correctly identify which public address they'll be using on the IPv4 internet.
there should be no need to change the default.
The default address is one from I<I-D.draft-byrne-v6ops-clatip>.
When using B<clatd> as an SIIT-DC Edge Relay (I<RFC 7756>), you will want to
set this to the IPv4 Service Address configured in the SIIT-DC Border Relay.
This way, local applications can correctly identify which public address
they'll be using on the IPv4 internet, and will be able to provide fully
functional references to it in application-level payload, and so on.
The default address is one from I<RFC 7335>.
=item B<clat-v6-addr=ipv6-address> (default: auto-generated)
The IPv6 address of the CLAT. Traffic to/from the B<clat-v4-addr> will be
translated into this address. By default, B<clatd> will attempt to figure out
which network device will be used for traffic towards the PLAT, see if there
is any SLAAC-configured addresses on it, and if so substitute the '0xfffe'
value in the middle of the Interface ID for '0xc1a7' to generate a new
address for the CLAT. If you're not using SLAAC you will have to set this
manually.
translated into this address. When using B<clatd> as an SIIT-DC Edge Relay, you
will want to set this to the same IPv6 address in the Explicit Address Mapping
configured in the SIIT-DC Border Relay.
By default, B<clatd> will attempt to figure out which network device will be
used for traffic towards the PLAT, see if there is any SLAAC-based globally
scoped addresses on it (i.e., a /64 with '0xfffe' in the middle of the
Interface ID), and will if so substitute that '0xfffe' value with '0xc1a7'
("clat") to generate a CLAT IPv6 address.
If only a non-SLAAC global address is found on the PLAT-facing device,
B<clatd> will substitute its Interface ID with a random integer and use the
result as the CLAT IPv6 address. It will only do so if the prefix length is
/120 or smaller, as otherwise the risk of IID collisions is considered to be
too high. Note that on most Perl platforms, the I<rand()> function is limited
to 48 bits, which means that for longer IIDs, the least significant bits will
be all 0.
If multiple addresses are found in either category, the one that shares the
longest common prefix with the PLAT prefix will be preferred when deriving
the CLAT IPv6 address according to the algorithm described above.
=item B<dns64-servers=srv1,[srv2,..]> (default: use system resolver)
@@ -173,10 +243,11 @@ L<http://www.litech.org/tayga>. Required.
=item B<forwarding-enable=bool> (default: I<yes>)
Controls whether or not B<clatd> should enable IPv6 forwarding if necessary. IPv6
forwarding is necessary for B<clatd> to work correctly. It will also ensure that
the I<accept_ra> sysctl is to '2' for all devices have it set to '1', in order
to prevent any connectivity loss as a result of enabling forwarding.
Controls whether or not B<clatd> should enable IPv6 forwarding if necessary.
IPv6 forwarding is necessary for B<clatd> to work correctly. It will also
ensure that the I<accept_ra> sysctl is to '2' for all devices have it set to
'1', in order to prevent any connectivity loss as a result of enabling
forwarding.
All sysctls that are modified will be restored to their original values when
B<clatd> is shutting down.
@@ -185,8 +256,8 @@ B<clatd> is shutting down.
Controls whether or not B<clatd> should insert ip6tables rules that permit the
forwarding of IPv6 traffic between the CLAT and PLAT devices. Such forwarding
must be permitted for B<clatd> to work correctly. Any rules added will be removed
when B<clatd> is shutting down.
must be permitted for B<clatd> to work correctly. Any rules added will be
removed when B<clatd> is shutting down.
The default is I<yes> if the ip6tables_filter kernel module is loaded, I<no>
if it is not.
@@ -194,7 +265,7 @@ if it is not.
=item B<plat-dev> (default: auto-detect)
Which network device is facing the PLAT (NAT64). By default, this is
auto-detecting by performing a route table lookup towards the PLAT prefix.
auto-detected by performing a route table lookup towards the PLAT prefix.
This setting is used when setting up generating the CLAT IPv6 address, and
when setting up ip6tables rules and Proxy-ND entries.
@@ -209,7 +280,7 @@ DNS64 answers using the method in I<RFC 7050>.
Controls whether or not B<clatd> should add a Proxy-ND entry for the CLAT IPv6
address on the network device facing the PLAT. This is probably necessary
on Ethernet networks (otherwise the upstream IPv6 router won't know where to
send packets to the CLAT's IPv6 adderss), but likely not necessary on
send packets to the CLAT's IPv6 address), but likely not necessary on
point-to-point links like PPP or 3GPP mobile broadband, as in those cases
IPv6 ND isn't used. However it doesn't hurt to add Proxy-ND entries in that
case, either.
@@ -230,7 +301,7 @@ ICMPv4 errors back to the host (i.e., it will show up as the first hop when
tracerouting to IPv4 destinations), and you may also ping it to verify that
the TAYGA process is still alive and well.
The default address is one from I<I-D.draft-byrne-v6ops-clatip>.
The default address is one from I<RFC 7335>.
=item B<v4-conncheck-enable=bool> (default: I<yes>)
@@ -246,6 +317,9 @@ system has IPv4 connectivity, disable this setting. You may instead use the
B<v4-defaultroute-enable> and B<v4-defaultroute-metric> settings to prevent
B<clatd> from interfering with native IPv4 connectivity.
Note that enabling B<v4-defaultroute-replace> will override
B<v4-conncheck-enable> and unconditionally disable IPv4 connectivity checking.
=item B<v4-conncheck-delay=seconds> (default: I<10>)
When performing an IPv4 connectivity check, wait this number of seconds
@@ -266,6 +340,23 @@ an environment where native IPv4 connectivity is also present, you might want
to disable this and instead control manually which IPv4 destinations is
reached through the CLAT and which are not.
=item B<v4-defaultroute-replace=bool> (default: I<no>)
Instructs B<clatd> to remove any pre-existing IPv4 default routes, replacing it
with one pointing to the CLAT (assuming B<v4-defaultroute-enable> is I<yes>).
The replacement is temporary, any pre-existing routes that were removed will be
restored when B<clatd> is shutting down.
Note that nothing prevents software like a connection manager or a DHCPv4
client daemon from re-adding any replaced routes while B<clatd> is running.
If you enable B<v4-defaultroute-replace> while at the same time disabling
B<v4-defaultroute-enable>, B<clatd> will remove any pre-existing IPv4 default
routes but not add any of its own.
Setting B<v4-defaultroute-replace> to I<yes> will disable the IPv4 connectivity
check.
=item B<v4-defaultroute-metric=integer> (default: I<2048>)
The metric of the IPv4 default route pointing to the CLAT. The default is
@@ -286,6 +377,17 @@ If you know that the IPv6 Path MTU between the host and the PLAT is larger
than 1280, you may increase this, but then you should also recompile TAYGA
with a larger B<ipv6_offlink_mtu> setting in I<conffile.c>.
=item B<v4-defaultroute-advmss=integer> (default: B<v4-defaultroute-mtu> - 40)
The "advmss" value assigned to the the default route potining to the CLAT. This
controls the advertised TCP MSS value for TCP connections made through the
CLAT.
You should normally not need to set this. By default the value is calculated by
taking the value of B<v4-defaultroute-mtu> and substracting 40 (20 bytes for
the IPv4 header + 20 bytes for the TCP header). If B<v4-defaultroute-mtu> is
unset or 0, there is no default.
=back
=head1 LIMITATIONS
@@ -310,18 +412,31 @@ configuration file) when reporting a bug.
=head1 LICENCE
Copyright (c) 2014 Tore Anderson <tore@fud.no>
Copyright (c) 2014-2023 Tore Anderson <tore@fud.no>
As long as you retain this notice, you may use this piece of software as
you wish. If you like it, and we happen to meet one day, you can buy me
a beer in return. If you really like it, make it an IPA.
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do
so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
=head1 SEE ALSO
ip(8), ip6tables(8), tayga(8), tayga.conf(5)
RFC 6052, RFC 6145, RFC 6146, RFC 6877, RFC 7050
I-D.anderson-siit-dc, I-D.byrne-v6ops-clatip
RFC 6052, RFC 6145, RFC 6146, RFC 6877, RFC 7050, RFC 7335 RFC 7755, RFC 7756,
RFC 7757
=cut

230
clatd
View File

@@ -1,10 +1,24 @@
#! /usr/bin/perl -w
#
# Copyright (c) 2014 Tore Anderson <tore@fud.no>
# Copyright (c) 2014-2023 Tore Anderson <tore@fud.no>
#
# As long as you retain this notice, you may use this piece of software as
# you wish. If you like it, and we happen to meet one day, you can buy me
# a beer in return. If you really like it, make it an IPA.
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
#
# See the file 'README.pod' in the source distribution or the manual page
# clatd(8) for more information.
@@ -12,7 +26,7 @@
use strict;
use Net::IP;
my $VERSION = "1.1";
my $VERSION = "1.6";
#
# Populate the global config hash with the default values
@@ -20,8 +34,10 @@ my $VERSION = "1.1";
my %CFG;
$CFG{"quiet"} = 0; # suppress normal output
$CFG{"debug"} = 0; # debugging output level
$CFG{"script-up"} = undef; # sh script to run when starting up
$CFG{"script-down"} = undef; # sh script to run when shutting down
$CFG{"clat-dev"} = "clat"; # TUN interface name to use
$CFG{"clat-v4-addr"} = "192.0.0.1"; # from I-D.draft-byrne-v6ops-clatip
$CFG{"clat-v4-addr"} = "192.0.0.1"; # from RFC 7335
$CFG{"clat-v6-addr"} = undef; # derive from existing SLAAC addr
$CFG{"dns64-servers"} = undef; # use system resolver by default
$CFG{"cmd-ip"} = "ip"; # assume in $PATH
@@ -33,12 +49,14 @@ $CFG{"plat-dev"} = undef; # PLAT-facing device, default detect
$CFG{"plat-prefix"} = undef; # detect using DNS64 by default
$CFG{"proxynd-enable"} = 1; # add proxy-nd entry for clat?
$CFG{"tayga-conffile"} = undef; # make a temporary one by default
$CFG{"tayga-v4-addr"} = "192.0.0.2"; # from I-D.draft-byrne-v6ops-clatip
$CFG{"tayga-v4-addr"} = "192.0.0.2"; # from RFC 7335
$CFG{"v4-conncheck-enable"} = 1; # exit if there's already a defroute
$CFG{"v4-conncheck-delay"} = 10; # seconds before checking for v4 conn.
$CFG{"v4-defaultroute-enable"} = 1; # add a v4 defaultroute via the CLAT?
$CFG{"v4-defaultroute-replace"} = 0; # replace existing v4 defaultroute?
$CFG{"v4-defaultroute-metric"} = 2048; # metric for the IPv4 defaultroute
$CFG{"v4-defaultroute-mtu"} = 1260; # MTU for the IPv4 defaultroute
$CFG{"v4-defaultroute-advmss"} = 0; # TCP MSS for the IPv4 defaultroute
#
@@ -69,18 +87,17 @@ sub err {
#
sub cmd {
my $msgsub = shift;
my $command = shift;
my @cmdline = @_;
my @cmd = @_;
d("cmd($command @cmdline)");
d("cmd(@cmd)");
if(system($command, @cmdline)) {
if(system(@cmd)) {
if($? == -1) {
&{$msgsub}("cmd($command @cmdline) failed to execute");
&{$msgsub}("cmd(@cmd) failed to execute");
} elsif($? & 127) {
&{$msgsub}("cmd($command @cmdline) died with signal ", ($? & 127));
&{$msgsub}("cmd(@cmd) died with signal ", ($? & 127));
} else {
&{$msgsub}("cmd($command @cmdline) returned ", ($? >> 127));
&{$msgsub}("cmd(@cmd) returned ", ($? >> 127));
}
}
return $?;
@@ -89,7 +106,8 @@ sub cmd {
#
# Reads in key=value pairs from a configuration file, overwriting the default
# setting in the %CFG hash. The key must exist, or we
# setting in the %CFG hash. The key must exist in the built-in hash, or we
# ignore the setting in the config file.
#
sub readconf {
d("readconf('@_')");
@@ -134,7 +152,7 @@ sub cfgbool {
#
sub cfgint {
my ($key) = @_;
d2("cfgstr($key)");
d2("cfgint($key)");
if(!exists($CFG{$key})) {
err("key '$key' doesn't exist in config hash");
}
@@ -149,7 +167,7 @@ sub cfgint {
#
sub cfg {
my ($key) = @_;
d2("cfgstr($key)");
d2("cfg($key)");
if(!exists($CFG{$key})) {
err("key '$key' doesn't exist in config hash");
}
@@ -201,9 +219,9 @@ sub sysctl {
#
# Look for either of the WKAs for ipv4only.arpa (192.0.0.170 and .171) in an
# IPv6 address at all of the locations RFC 6052 says it can occur. If it's
# present at any of those locations (but no more than once), return the
# inferred translation prefix.
# IPv6 address at all of the locations RFC 6052 says it can occur, starting at
# the longest prefix length. If it's present at any of those locations, return
# the inferred translation prefix.
#
sub find_rfc7050_wka {
my $AAAA = shift;
@@ -230,7 +248,7 @@ sub find_rfc7050_wka {
my $discovered_pfx_len;
for my $len (keys(%rfc6052table)) {
outer: for my $len (sort {$b <=> $a} keys(%rfc6052table)) {
d2("Looking for Well-Known Addresses at prefix length /$len");
my $maskedip = $ip->intip();
my $mask = Net::IP->new($rfc6052table{"$len"}{"mask"}, 6);
@@ -251,13 +269,9 @@ sub find_rfc7050_wka {
}
if($maskedip == $wkaint->intip) {
if($discovered_pfx_len) {
w("Found WKA at two locations in ", $ip->sort,
"(/$discovered_pfx_len and /$len) - ignoring");
return;
}
d2("Found it!");
$discovered_pfx_len = $len;
last outer;
} else {
d2("Didn't find it");
}
@@ -314,7 +328,7 @@ sub find_rfc7050_wka {
sub get_plat_prefix {
p("Performing DNS64-based PLAT prefix discovery (cf. RFC 7050)");
require IO::Socket::INET6; # needed by Net::DNS for querying IPv6 servers
require IO::Socket::IP; # needed by Net::DNS for querying IPv6 servers
require Net::DNS;
my @dns64_servers = split(",", cfg("dns64-servers") || "");
@@ -379,6 +393,7 @@ sub get_plat_dev {
if(!$plat_prefix) {
err("get_plat_dev(): No PLAT prefix to work with");
}
$plat_prefix =~ s|/\d+$||;
open(my $fd, '-|', cfg("cmd-ip"), qw(-6 route get), $plat_prefix)
or err("get_plat_dev(): 'ip -6 route get $plat_prefix' failed to execute");
while(<$fd>) {
@@ -424,12 +439,14 @@ sub is_modified_eui64 {
#
# This function considers any globally scoped /64 address on the PLAT-facing
# device, checks to see if it is base on Modified EUI-64, and generates a
# new address for the CLAT by substituting the "0xfffe" bits in the middle
# of the Interface ID with 0xc1a7 ("clat"). This keeps the last 24 bits
# unchanged, which has the added bonus of not requiring the host to join
# another Solicited-Node multicast group.
# This function considers any globally scoped IPv6 address on the PLAT-facing
# device, and derives an CLAT IPv6 address from the best match (longest
# common prefix with PLAT prefix). Addresses based on Modified EUI-64 are
# preferred, and if found, it generates a new address for the CLAT by
# substituting the "0xfffe" bits in the middle of the Interface ID with
# 0xc1a7 ("clat"). This keeps the last 24 bits unchanged, which has the added
# bonus of not requiring the host to join another Solicited-Node multicast
# group. If no EUI-64 address is seen, it'll use a random IID instead.
#
sub get_clat_v6_addr {
my $plat_dev = cfg("plat-dev");
@@ -445,42 +462,108 @@ sub get_clat_v6_addr {
err("Failed to convert plat prefix to bigint");
}
my $ip; # will contain the best candidate ip in bigint format
my $best_score;
my $ip_plen; # will contain the prefix length of the best candidate ip
my $best_score; # will contain the score of the best candidate seen
my $seen_eui64; # set if we've seen an eui-64 based address
p("Attempting to derive a CLAT IPv6 address from a EUI-64 address on ",
p("Attempting to derive a CLAT IPv6 address from an IPv6 address on ",
"'$plat_dev'");
open(my $fd, '-|', cfg("cmd-ip"), qw(-6 address list scope global dev),
$plat_dev)
or err("'ip -6 address list scope global dev $plat_dev' failed to execute");
while(<$fd>) {
if(m| inet6 (\S+)/64 scope global |) {
if(m| inet6 (\S+)/(\d{1,3}) scope global |) {
my $candidate = $1;
next unless(is_modified_eui64($candidate));
d2("Saw EUI-64 based address: $candidate");
my $plen = $2;
d2("Saw a candidate address on '$plat_dev': $candidate/$plen");
my $candidate_int = Net::IP->new($candidate, 6)->intip();
if(!$candidate_int) {
err("Failed to convert plat prefix to bigint");
}
if(!$best_score or $best_score > ($plat_prefix_int ^ $candidate_int)) {
d2("$candidate has so far the longest common prefix with plat prefix");
if($plen > 120) {
# We'll need a subnet with some space if we are to generate a random
# IID and don't have too large risk of collisions... /120 seems like
# an OK limit
d2("Refusing to use random IIDs for prefix lengths > /120");
next;
}
# True if the candidate under consideration is EUI-64 based
my $is_eui64 = ($plen == 64) && is_modified_eui64($candidate);
# If this is the first time we're considering an EUI-64 based address,
# we unconditionally prefer it (even if it doesn't have the longest
# matching prefix), because we consider deriving the CLAT IPv6
# address from an EUI-64 based candidate to be safer than generating
# a truly random CLAT IPv6 address.
if($is_eui64 and !$seen_eui64++) {
d2("Preferring $candidate/$plen; it's the first EUI-64 seen");
$best_score = $plat_prefix_int ^ $candidate_int;
$ip = $candidate_int;
$ip_plen = $plen;
next;
}
# If we already have found an EUI-64 based address, we can reject this
# candidate outright, as it is *not* EUI-64 based.
if(!$is_eui64 and $seen_eui64) {
d2("Rejecting $candidate/$plen; we have better EUI-64 candidates");
next;
}
# Otherwise, we'll be comparing EUI-64 to EUI-64, or non EUI-64 to
# non EUI-64. If so, we prefer the current candidate if it has a better
# score than the current best match (or if there is no current best
# match).
if(!$best_score or $best_score > ($plat_prefix_int ^ $candidate_int)) {
d2("Preferring $candidate/$plen; best match so far");
$best_score = $plat_prefix_int ^ $candidate_int;
$ip = $candidate_int;
$ip_plen = $plen;
next;
}
d2("Rejecting $candidate/$plen; we've seen better matches");
}
}
close($fd)
or err("'ip -6 address list scope global dev $plat_dev' failed");
# First clear the middle 0xfffe bits of the interface ID
my $mask = Net::IP->new("ffff:ffff:ffff:ffff:ffff:ff00:00ff:ffff");
$mask = $mask->intip();
$ip &= $mask;
if(!$ip) {
err("Could not find a global IPv6 address on $plat_dev from which ",
"to derive a CLAT IPv6 address (try setting 'clat-v6-addr')");
}
# Next set them to the value 0xc1a7 and return
$mask = Net::IP->new("::c1:a700:0", 6) or err(Net::IP::Error());
$mask = $mask->intip();
$ip |= $mask;
if($seen_eui64) {
# If the chosen candidate IP is EUI-64 based, we derive a CLAT IPv6
# address by replacing the 0xffe in the middle of the Interface ID with
# 0xc1a7 ("CLAT").
# First clear the middle 0xfffe bits of the interface ID
my $mask = Net::IP->new("ffff:ffff:ffff:ffff:ffff:ff00:00ff:ffff");
$mask = $mask->intip();
$ip &= $mask;
# Next set them to the value 0xc1a7
$mask = Net::IP->new("::c1:a700:0", 6) or err(Net::IP::Error());
$mask = $mask->intip();
$ip |= $mask;
} else {
# If the chosen candidate IP is NOT EUI-64 based, we'll just make up a
# random interface ID. There is no guarantee that this will actually
# work, but it's the best thing we can try...
# First zero out the entire Interface ID
$ip >>= (128-$ip_plen);
$ip <<= (128-$ip_plen);
my $iid = int(rand(2**(128-$ip_plen)));
d2(sprintf("Using random interface ID: %x", $iid));
$ip |= $iid;
}
# Convert back the BigInt to a regular Net::IP object and return
$ip = Net::IP->new(Net::IP::ip_bintoip(Net::IP::ip_inttobin($ip, 6), 6));
return $ip->short() if $ip;
@@ -500,6 +583,7 @@ my @cleanup_accept_ra_sysctls; # accept_ra sysctls to be reset to '1'
my $cleanup_zero_proxynd_sysctl; # zero proxy_ndp sysctl if set
my $cleanup_remove_proxynd_entry, # true if having added proxynd entry
my $cleanup_remove_ip6tables_rules; # true if having added ip6tables rules
my @cleanup_restore_v4_defaultroutes; # temporarily replaced defaultroutes
sub cleanup_and_exit {
my $exitcode = shift;
@@ -539,6 +623,10 @@ sub cleanup_and_exit {
cmd(\&w, cfg("cmd-ip6tables"), qw(-D FORWARD -i), cfg("plat-dev"),
"-o", cfg("clat-dev"), qw(-j ACCEPT));
}
for my $rt (@cleanup_restore_v4_defaultroutes) {
d("Cleanup: Restoring temporarily replaced IPv4 default route");
cmd(\&w, cfg("cmd-ip"), qw(-4 route add), @{$rt});
}
exit($exitcode);
}
@@ -573,8 +661,10 @@ for (my $i = 0; $i < @ARGV;) {
splice(@ARGV, $i, 2);
next;
} elsif($ARGV[$i] =~ /^(-h|--help)$/) {
print "clatd v$VERSION - a 464XLAT (RFC 6877) CLAT implementation for ",
"Linux\n";
print <<"EOF";
clatd v$VERSION - a 464XLAT (RFC 6877) CLAT and SIIT-DC Edge Relay
(RFC 7756) implementation for Linux
EOF
print "\n";
print " Usage: clatd [-q] [-d [-d]] [-c config-file] ",
"[conf-key=val ...]\n";
@@ -654,12 +744,15 @@ p("Using CLAT IPv6 address: ", $CFG{"clat-v6-addr"});
if(!defined($CFG{"ip6tables-enable"})) {
$CFG{"ip6tables-enable"} = -e "/sys/module/ip6table_filter" ? 1 : 0;
}
if(!$CFG{"v4-defaultroute-advmss"} and cfgint("v4-defaultroute-mtu")) {
$CFG{"v4-defaultroute-advmss"} = $CFG{"v4-defaultroute-mtu"} - 40;
}
#
# Step 1: Detect if there is an IPv4 default route on the system from before.
# If so we have no need for 464XLAT, and we can just exit straight away
#
if(cfgbool("v4-conncheck-enable")) {
if(cfgbool("v4-conncheck-enable") and !cfgbool("v4-defaultroute-replace")) {
my $delay = cfgint("v4-conncheck-delay");
p("Checking if this system already has IPv4 connectivity ",
$delay ? "in $delay sec(s)" : "now");
@@ -774,18 +867,44 @@ cmd(\&err, cfg("cmd-ip"), qw(-4 address add), cfg("clat-v4-addr"),
"dev", cfg("clat-dev"));
cmd(\&err, cfg("cmd-ip"), qw(-6 route add), cfg("clat-v6-addr"),
"dev", cfg("clat-dev"));
if(cfgbool("v4-defaultroute-replace")) {
open(my $fd, '-|', cfg("cmd-ip"), qw(-4 route show default))
or err("'ip -4 route show default' failed to execute");
while(<$fd>) {
my @rt = split(/\s+/, $_);
d("Replacing pre-existing IPv4 default route: @rt");
cmd(\&err, cfg("cmd-ip"), qw(-4 route del), @rt);
push(@cleanup_restore_v4_defaultroutes, \@rt);
}
close($fd) or err("'ip -4 route show default' failed");
}
if(cfgbool("v4-defaultroute-enable")) {
my @cmdline = (qw(-4 route add default dev), cfg("clat-dev"));
if(cfgint("v4-defaultroute-metric")) {
push(@cmdline, ("metric", cfgint("v4-defaultroute-metric")))
}
if(cfgint("v4-defaultroute-mtu")) {
push(@cmdline, ("mtu", cfgint("v4-defaultroute-mtu")))
push(@cmdline, ("mtu", cfgint("v4-defaultroute-mtu")));
}
if(cfgint("v4-defaultroute-advmss")) {
push(@cmdline, ("advmss", cfgint("v4-defaultroute-advmss")));
}
p("Adding IPv4 default route via the CLAT");
cmd(\&err, cfg("cmd-ip"), @cmdline);
}
# Inject %CFG into %ENV and then run the up script
for my $key (sort keys(%CFG)) {
my $var = $key;
$var =~ y/-/_/;
d2(sprintf("Script env: %s=%s", $key, $CFG{$key} || ''));
$ENV{$var} = $CFG{$key};
}
if(cfg("script-up")) {
d("Running custom startup script: ", cfg("script-up"));
cmd(\&err, cfg("script-up"));
}
#
# All preparation done! We can now start TAYGA, which will handle the actual
# translation of IP packets.
@@ -806,6 +925,11 @@ $SIG{'INT'} = 'DEFAULT';
$SIG{'TERM'} = 'DEFAULT';
#
# TAYGA exited, probably because we're shutting down. Cleanup and exit.
# TAYGA exited, probably because we're shutting down. Run the down script, then
# cleanup and exit.
#
if(cfg("script-down")) {
d("Running custom shutdown script: ", cfg("script-down"));
cmd(\&err, cfg("script-down"));
}
cleanup_and_exit(0);

View File

@@ -7,15 +7,27 @@
# Written by Tore Anderson <tore@fud.no>
#
# Newer NetworkManager versions will run the dispatcher scripts once
# a new unmanaged interface shows up, including the 'clat' interface
# created by clatd/TAYGA. So if we're being called due to our own
# interface showing up, do nothing, otherwise we will end up
# committing suicide from the restarts below
[ "$DEVICE_IFACE" = "clat" ] && exit 0
# We're only acting on interface "up" or "down" events. NM will run the
# dispatcher scripts for other events we're not interested in, like the
# hostname being set or a DHCP lease being renewed. Ignore those.
[ "$2" != "up" ] && [ "$2" != "down" ] && exit 0
# We simply restart clatd in all situations, as no matter if an interface
# goes up or down, it may mean that the PLAT devices changes, it may mean
# goes up or down, it may mean that the PLAT device changes, it may mean
# native IPv4 appearing or disappearing, or it may mean that DNS64 became
# available or unavailable...it's far easier to simply restart always and
# start from scratch than to figure out if a restart is truly necessary
# systemd-based distros
if test -x /usr/bin/systemctl; then
/usr/bin/systemctl restart clatd.service
if which systemctl &> /dev/null; then
systemctl --no-block restart clatd.service
fi
# upstart-based distros

View File

@@ -12,6 +12,7 @@
Description=464XLAT CLAT daemon
Documentation=man:clatd(8)
After=network-online.target
StartLimitIntervalSec=0
[Service]
Type=simple