mirror of
https://github.com/kernelkit/infix.git
synced 2026-07-22 01:13:00 +02:00
confd: add support for IPv4LL request-address option
This patch allows a user to specify a specific 169.254/16 address that the zeroconf client starts with when probing for a free address. If the probe fails it falls back to its default algorithm. Fixes #628 Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
This commit is contained in:
@@ -598,6 +598,13 @@ As shown, the link-local IPv4 address is configured with `set autconf
|
||||
enabled true`. The resulting address (169.254.1.3/16) is of type
|
||||
*random* ([ietf-ip.yang][2]).
|
||||
|
||||
The IPv4LL client also supports a `request-address` setting which can be
|
||||
used to "seed" the client's starting address. If the address is free it
|
||||
will be used, otherwise it falls back to the default algorithm.
|
||||
|
||||
admin@example:/config/interface/eth0/ipv4/> set autoconf request-address 169.254.1.2
|
||||
|
||||
|
||||
#### Use of DHCP for IPv4 address assignment
|
||||
|
||||

|
||||
|
||||
@@ -45,8 +45,10 @@ endif
|
||||
|
||||
ifeq ($(BR2_PACKAGE_AVAHI_AUTOIPD),y)
|
||||
define SKELETON_INIT_FINIT_SET_AVAHI_AUTOIPD
|
||||
echo "service [2345789] name:zeroconf :%i avahi-autoipd --force-bind --syslog %i -- ZeroConf for %i" \
|
||||
> $(FINIT_D)/available/zeroconf@.conf
|
||||
echo 'service name:zeroconf :%i env:-/etc/default/zeroconf-%i \' >$(FINIT_D)/available/zeroconf@.conf
|
||||
echo ' <!> kill:5 pid:!/run/avahi-autoipd.%i.pid \'>>$(FINIT_D)/available/zeroconf@.conf
|
||||
echo ' [2345789] log avahi-autoipd $$ZEROCONF_ARGS %i \'>>$(FINIT_D)/available/zeroconf@.conf
|
||||
echo ' -- ZeroConf for %i' >>$(FINIT_D)/available/zeroconf@.conf
|
||||
endef
|
||||
SKELETON_INIT_FINIT_POST_INSTALL_TARGET_HOOKS += SKELETON_INIT_FINIT_SET_AVAHI_AUTOIPD
|
||||
endif
|
||||
|
||||
@@ -537,45 +537,89 @@ static int netdag_gen_ipv6_autoconf(struct dagger *net, struct lyd_node *cif,
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Check if ipv4 is enabled, only then can autoconf be enabled, in all
|
||||
* other cases it must be disabled. Since we have multiple settings in
|
||||
* autoconf, we check if either is modified (diff), in which case we not
|
||||
* only enable, but also "touch" the Finit service for avahi-autoipd to
|
||||
* ensure it is (re)started.
|
||||
*
|
||||
* Note: in Infix, regardless of the IPv4 configuration, any link-local
|
||||
* link-local address is disabled when the interface is being used
|
||||
* as a bridge port.
|
||||
*
|
||||
* Also, IPv4LL is not defined for loopback, so always skip there.
|
||||
*/
|
||||
static int netdag_gen_ipv4_autoconf(struct dagger *net, struct lyd_node *cif,
|
||||
struct lyd_node *dif)
|
||||
{
|
||||
struct lyd_node *ipconf = lydx_get_child(cif, "ipv4");
|
||||
struct lyd_node *ipdiff = lydx_get_child(dif, "ipv4");
|
||||
const char *ifname = lydx_get_cattr(dif, "name");
|
||||
struct lyd_node *node, *zcip;
|
||||
struct lydx_diff nd;
|
||||
struct lyd_node *zcip;
|
||||
char defaults[64];
|
||||
FILE *initctl;
|
||||
int err = 0;
|
||||
|
||||
if (!strcmp(ifname, "lo"))
|
||||
return 0;
|
||||
|
||||
/* client defults for this interface, needed in both cases */
|
||||
snprintf(defaults, sizeof(defaults), "/etc/default/zeroconf-%s", ifname);
|
||||
|
||||
/* no ipv4 at all, ipv4 selectively disabled, or interface is a bridge port */
|
||||
if (!ipconf || !lydx_is_enabled(ipconf, "enabled") || is_bridge_port(cif))
|
||||
goto disable;
|
||||
|
||||
if (lydx_get_op(lydx_get_child(ipdiff, "enabled")) == LYDX_OP_REPLACE) {
|
||||
node = lydx_get_child(ipconf, "autoconf");
|
||||
if (node && lydx_is_enabled(node, "enabled"))
|
||||
goto enable;
|
||||
goto disable;
|
||||
}
|
||||
/*
|
||||
* when enabled, we may have been enabled before, but skipped
|
||||
* for various reasons: was bridge port, ipv4 was disabled...
|
||||
*/
|
||||
zcip = lydx_get_child(ipconf, "autoconf");
|
||||
if (zcip && lydx_is_enabled(zcip, "enabled")) {
|
||||
struct lyd_node *node;
|
||||
const char *addr;
|
||||
int diff = 0;
|
||||
FILE *fp;
|
||||
|
||||
zcip = lydx_get_child(ipdiff, "autoconf");
|
||||
if (!zcip || !(node = lydx_get_child(zcip, "enabled")))
|
||||
return 0;
|
||||
/* check for any changes in this container */
|
||||
node = lydx_get_child(ipdiff, "autoconf");
|
||||
if (node) {
|
||||
const struct lyd_node *tmp;
|
||||
|
||||
lydx_get_diff(node, &nd);
|
||||
if (nd.new && !strcmp(nd.val, "true")) {
|
||||
enable:
|
||||
initctl = dagger_fopen_next(net, "init", ifname,
|
||||
60, "zeroconf-up.sh");
|
||||
tmp = lydx_get_child(node, "enabled");
|
||||
if (tmp)
|
||||
diff++;
|
||||
tmp = lydx_get_child(node, "request-address");
|
||||
if (tmp)
|
||||
diff++;
|
||||
}
|
||||
|
||||
fp = fopen(defaults, "w");
|
||||
if (!fp) {
|
||||
ERRNO("Failed creating %s, cannot enable IPv4LL on %s", defaults, ifname);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
fprintf(fp, "ZEROCONF_ARGS=\"--force-bind --syslog ");
|
||||
addr = lydx_get_cattr(zcip, "request-address");
|
||||
if (addr)
|
||||
fprintf(fp, "--start=%s", addr);
|
||||
fprintf(fp, "\"\n");
|
||||
fclose(fp);
|
||||
|
||||
initctl = dagger_fopen_next(net, "init", ifname, 60, "zeroconf-up.sh");
|
||||
if (!initctl)
|
||||
return -EIO;
|
||||
|
||||
fprintf(initctl,
|
||||
"initctl -bnq enable zeroconf@%s.conf\n", ifname);
|
||||
/* on enable, or reactivation, it is enough to ensure the service is enabled */
|
||||
fprintf(initctl, "initctl -bnq enable zeroconf@%s.conf\n", ifname);
|
||||
/* on changes to autoconf we must ensure Finit restarts the service */
|
||||
if (diff)
|
||||
fprintf(initctl, "initctl -bnq touch zeroconf@%s.conf\n", ifname);
|
||||
} else {
|
||||
disable:
|
||||
initctl = dagger_fopen_current(net, "exit", ifname,
|
||||
40, "zeroconf-down.sh");
|
||||
initctl = dagger_fopen_current(net, "exit", ifname, 40, "zeroconf-down.sh");
|
||||
if (!initctl) {
|
||||
/* check if in bootstrap (pre gen 0) */
|
||||
if (errno == EUNATCH)
|
||||
@@ -583,9 +627,8 @@ static int netdag_gen_ipv4_autoconf(struct dagger *net, struct lyd_node *cif,
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
fprintf(initctl,
|
||||
"initctl -bnq disable zeroconf@%s.conf\n", ifname);
|
||||
|
||||
fprintf(initctl, "initctl -bnq disable zeroconf@%s.conf\n", ifname);
|
||||
fprintf(initctl, "rm -f %s\n", defaults);
|
||||
err = netdag_exit_reload(net);
|
||||
}
|
||||
|
||||
|
||||
@@ -25,7 +25,7 @@ MODULES=(
|
||||
"ietf-hardware@2018-03-13.yang -e hardware-state"
|
||||
"infix-hardware@2024-04-25.yang"
|
||||
"ieee802-dot1q-types@2022-10-29.yang"
|
||||
"infix-ip@2023-09-14.yang"
|
||||
"infix-ip@2024-09-16.yang"
|
||||
"infix-if-type@2024-01-29.yang"
|
||||
"infix-routing@2024-09-20.yang"
|
||||
"ieee802-dot1ab-lldp@2022-03-15.yang"
|
||||
|
||||
@@ -1,68 +0,0 @@
|
||||
module infix-ip {
|
||||
yang-version 1.1;
|
||||
namespace "urn:infix:params:xml:ns:yang:infix-ip";
|
||||
prefix infix-ip;
|
||||
|
||||
import ietf-interfaces {
|
||||
prefix if;
|
||||
}
|
||||
import ietf-ip {
|
||||
prefix ip;
|
||||
}
|
||||
import ietf-inet-types {
|
||||
prefix inet;
|
||||
}
|
||||
import ietf-yang-types {
|
||||
prefix yang;
|
||||
}
|
||||
|
||||
description
|
||||
"This module augments ietf-ip with an IPv4 link-local autoconf";
|
||||
|
||||
revision 2023-09-14 {
|
||||
description
|
||||
"Added deviations for unsupported parts of ietf-ip.";
|
||||
}
|
||||
|
||||
revision 2023-04-24 {
|
||||
description
|
||||
"Initial revision.";
|
||||
reference
|
||||
"RFC 7277: A YANG Data Model for IP Management";
|
||||
}
|
||||
|
||||
/*
|
||||
* Data nodes
|
||||
*/
|
||||
augment "/if:interfaces/if:interface/ip:ipv4" {
|
||||
container autoconf {
|
||||
description
|
||||
"Parameters to control the autoconfiguration of IPv4 address.";
|
||||
|
||||
leaf enabled {
|
||||
type boolean;
|
||||
default false;
|
||||
description
|
||||
"Use a ZeroConf/IPv4LL agent to retrieve an 169.254/16 address.";
|
||||
reference
|
||||
"RFC 3927: Dynamic Configuration of IPv4 Link-Local Addresses";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
deviation "/if:interfaces/if:interface/ip:ipv4/ip:address/ip:subnet/ip:netmask" {
|
||||
deviate not-supported;
|
||||
}
|
||||
|
||||
deviation "/if:interfaces/if:interface/ip:ipv4/ip:neighbor" {
|
||||
deviate not-supported;
|
||||
}
|
||||
|
||||
deviation "/if:interfaces/if:interface/ip:ipv6/ip:address/ip:status" {
|
||||
deviate not-supported;
|
||||
}
|
||||
|
||||
deviation "/if:interfaces/if:interface/ip:ipv6/ip:neighbor" {
|
||||
deviate not-supported;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
module infix-ip {
|
||||
yang-version 1.1;
|
||||
namespace "urn:infix:params:xml:ns:yang:infix-ip";
|
||||
prefix infix-ip;
|
||||
|
||||
import ietf-interfaces {
|
||||
prefix if;
|
||||
}
|
||||
import ietf-ip {
|
||||
prefix ip;
|
||||
}
|
||||
import ietf-inet-types {
|
||||
prefix inet;
|
||||
}
|
||||
import ietf-yang-types {
|
||||
prefix yang;
|
||||
}
|
||||
|
||||
description "This module augments ietf-ip with Infix extensions and deviations.";
|
||||
|
||||
revision 2024-09-16 {
|
||||
description "Add support for IPv4LL request-address.";
|
||||
reference "Internal.";
|
||||
}
|
||||
revision 2023-09-14 {
|
||||
description "Added deviations for unsupported parts of ietf-ip.";
|
||||
reference "Internal.";
|
||||
}
|
||||
revision 2023-04-24 {
|
||||
description "Initial revision.";
|
||||
reference "RFC 7277: A YANG Data Model for IP Management";
|
||||
}
|
||||
|
||||
/*
|
||||
* Data nodes
|
||||
*/
|
||||
augment "/if:interfaces/if:interface/ip:ipv4" {
|
||||
container autoconf {
|
||||
description "Parameters to control the autoconfiguration of IPv4 address.";
|
||||
reference "RFC 3927: Dynamic Configuration of IPv4 Link-Local Addresses";
|
||||
|
||||
leaf enabled {
|
||||
description "Use a ZeroConf/IPv4LL agent to retrieve an 169.254/16 address.";
|
||||
type boolean;
|
||||
}
|
||||
|
||||
leaf request-address {
|
||||
description "Try to acquire the specified IP address, if available.
|
||||
|
||||
With this setting the IPv4LL client will start by
|
||||
requesting this address. However, if it is not
|
||||
available it falls back to the default algorithm.";
|
||||
type inet:ipv4-address;
|
||||
must "substring(., 1, 7) = '169.254'" {
|
||||
error-message "Must be from the IPv4LL range 169.254.0.0/16.";
|
||||
}
|
||||
must "not(substring(., string-length(.) - 1, 2) = '.0' or substring(., string-length(.) - 3, 4) = '.255')" {
|
||||
error-message "Addresses ending in .0 or .255 are reserved.";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
deviation "/if:interfaces/if:interface/ip:ipv4/ip:address/ip:subnet/ip:netmask" {
|
||||
deviate not-supported;
|
||||
}
|
||||
|
||||
deviation "/if:interfaces/if:interface/ip:ipv4/ip:neighbor" {
|
||||
deviate not-supported;
|
||||
}
|
||||
|
||||
deviation "/if:interfaces/if:interface/ip:ipv6/ip:address/ip:status" {
|
||||
deviate not-supported;
|
||||
}
|
||||
|
||||
deviation "/if:interfaces/if:interface/ip:ipv6/ip:neighbor" {
|
||||
deviate not-supported;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user