Systemd/src/basic/string-table.h

112 lines
6.4 KiB
C
Raw Normal View History

/* SPDX-License-Identifier: LGPL-2.1-or-later */
#pragma once
#include <errno.h>
#include <stddef.h>
#include <stdio.h>
#include <sys/types.h>
#include "macro.h"
#include "parse-util.h"
#include "string-util.h"
ssize_t string_table_lookup(const char * const *table, size_t len, const char *key);
/* For basic lookup tables with strictly enumerated entries */
#define _DEFINE_STRING_TABLE_LOOKUP_TO_STRING(name,type,scope) \
scope const char *name##_to_string(type i) { \
if (i < 0 || i >= (type) ELEMENTSOF(name##_table)) \
return NULL; \
return name##_table[i]; \
}
#define _DEFINE_STRING_TABLE_LOOKUP_FROM_STRING(name,type,scope) \
scope type name##_from_string(const char *s) { \
return (type) string_table_lookup(name##_table, ELEMENTSOF(name##_table), s); \
}
#define _DEFINE_STRING_TABLE_LOOKUP_FROM_STRING_WITH_BOOLEAN(name,type,yes,scope) \
scope type name##_from_string(const char *s) { \
if (!s) \
return -1; \
networkd: merge ll addressing fallback modes into normal "boolean" values They are not really boolean, because we have both ipv4 and ipv6, but for each protocol we have either unset, no, and yes. From https://github.com/systemd/systemd/issues/13316#issuecomment-582906817: LinkLocalAddressing must be a boolean option, at least for ipv4: - LinkLocalAddressing=no => no LL at all. - LinkLocalAddressing=yes + Static Address => invalid configuration, warn and interpret as LinkLocalAddressing=no, no LL at all. (we check that during parsing and reject) - LinkLocalAddressing=yes + DHCP => LL process should be subordinated to the DHCP one, an LL address must be acquired at start or after a short N unsuccessful DHCP attemps, and must not stop DHCP to keeping trying. When a DHCP address is acquired, drop the LL address. If the DHCP address is lost, re-adquire a new LL address. (next patch will move in this direction) - LinkLocalAddressing=fallback has no reason to exist, because LL address must always be allocated as a fallback option when using DHCP. Having both DHCP and LL address at the same time is an RFC violation, so LinkLocalAdressing=yes correctly implemented is already the "fallback" behavior. The fallback option must be deprecated and if present in older configs must be interpreted as LinkLocalAddressing=yes. (removed) - And for IPv6, the LinkLocalAddress option has any sense at all? IPv6-LL address aren't required to be always set for every IPv6 enabled interface (in this case, coexisting with static or dynamic address if any)? Shouldn't be always =yes? (good question) This effectively reverts 29e81083bd2fcb2dbf83f67ef358c7d25adf7e9d. There is no special "fallback" mode now, so the check doesn't make sense anymore.
2020-10-08 16:59:26 +02:00
int b = parse_boolean(s); \
if (b == 0) \
return (type) 0; \
networkd: merge ll addressing fallback modes into normal "boolean" values They are not really boolean, because we have both ipv4 and ipv6, but for each protocol we have either unset, no, and yes. From https://github.com/systemd/systemd/issues/13316#issuecomment-582906817: LinkLocalAddressing must be a boolean option, at least for ipv4: - LinkLocalAddressing=no => no LL at all. - LinkLocalAddressing=yes + Static Address => invalid configuration, warn and interpret as LinkLocalAddressing=no, no LL at all. (we check that during parsing and reject) - LinkLocalAddressing=yes + DHCP => LL process should be subordinated to the DHCP one, an LL address must be acquired at start or after a short N unsuccessful DHCP attemps, and must not stop DHCP to keeping trying. When a DHCP address is acquired, drop the LL address. If the DHCP address is lost, re-adquire a new LL address. (next patch will move in this direction) - LinkLocalAddressing=fallback has no reason to exist, because LL address must always be allocated as a fallback option when using DHCP. Having both DHCP and LL address at the same time is an RFC violation, so LinkLocalAdressing=yes correctly implemented is already the "fallback" behavior. The fallback option must be deprecated and if present in older configs must be interpreted as LinkLocalAddressing=yes. (removed) - And for IPv6, the LinkLocalAddress option has any sense at all? IPv6-LL address aren't required to be always set for every IPv6 enabled interface (in this case, coexisting with static or dynamic address if any)? Shouldn't be always =yes? (good question) This effectively reverts 29e81083bd2fcb2dbf83f67ef358c7d25adf7e9d. There is no special "fallback" mode now, so the check doesn't make sense anymore.
2020-10-08 16:59:26 +02:00
if (b > 0) \
return yes; \
return (type) string_table_lookup(name##_table, ELEMENTSOF(name##_table), s); \
}
2016-03-04 17:28:04 +01:00
#define _DEFINE_STRING_TABLE_LOOKUP_TO_STRING_FALLBACK(name,type,max,scope) \
scope int name##_to_string_alloc(type i, char **str) { \
char *s; \
if (i < 0 || i > max) \
return -ERANGE; \
if (i < (type) ELEMENTSOF(name##_table) && name##_table[i]) { \
s = strdup(name##_table[i]); \
if (!s) \
return -ENOMEM; \
} else { \
if (asprintf(&s, "%i", i) < 0) \
return -ENOMEM; \
} \
*str = s; \
return 0; \
2016-03-04 17:28:04 +01:00
}
#define _DEFINE_STRING_TABLE_LOOKUP_FROM_STRING_FALLBACK(name,type,max,scope) \
scope type name##_from_string(const char *s) { \
unsigned u = 0; \
type i; \
if (!s) \
return (type) -1; \
i = (type) string_table_lookup(name##_table, ELEMENTSOF(name##_table), s); \
if (i >= 0) \
return i; \
if (safe_atou(s, &u) >= 0 && u <= max) \
return (type) u; \
return (type) -1; \
} \
2016-03-04 17:28:04 +01:00
#define _DEFINE_STRING_TABLE_LOOKUP(name,type,scope) \
_DEFINE_STRING_TABLE_LOOKUP_TO_STRING(name,type,scope) \
_DEFINE_STRING_TABLE_LOOKUP_FROM_STRING(name,type,scope)
2016-03-04 17:28:04 +01:00
#define _DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(name,type,yes,scope) \
_DEFINE_STRING_TABLE_LOOKUP_TO_STRING(name,type,scope) \
_DEFINE_STRING_TABLE_LOOKUP_FROM_STRING_WITH_BOOLEAN(name,type,yes,scope)
2016-03-04 17:28:04 +01:00
#define DEFINE_STRING_TABLE_LOOKUP(name,type) _DEFINE_STRING_TABLE_LOOKUP(name,type,)
hostnamed,shared/hostname-setup: expose the origin of the current hostname In hostnamed this is exposed as a dbus property, and in the logs in both places. This is of interest to network management software and such: if the fallback hostname is used, it's not as useful as the real configured thing. Right now various programs try to guess the source of hostname by looking at the string. E.g. "localhost" is assumed to be not the real hostname, but "fedora" is. Any such attempts are bound to fail, because we cannot distinguish "fedora" (a fallback value set by a distro), from "fedora" (received from reverse dns), from "fedora" read from /etc/hostname. /run/systemd/fallback-hostname is written with the fallback hostname when either pid1 or hostnamed sets the kernel hostname to the fallback value. Why remember the fallback value and not the transient hostname in /run/hostname instead? We have three hostname types: "static", "transient", fallback". – Distinguishing "static" is easy: the hostname that is set matches what is in /etc/hostname. – Distingiushing "transient" and "fallback" is not easy. And the "transient" hostname may be set outside of pid1+hostnamed. In particular, it may be set by container manager, some non-systemd tool in the initramfs, or even by a direct call. All those mechanisms count as "transient". Trying to get those cases to write /run/hostname is futile. It is much easier to isolate the "fallback" case which is mostly under our control. And since the file is only used as a flag to mark the hostname as fallback, it can be hidden inside of our /run/systemd directory. For https://bugzilla.redhat.com/show_bug.cgi?id=1892235.
2020-12-04 19:40:34 +01:00
#define DEFINE_STRING_TABLE_LOOKUP_TO_STRING(name,type) _DEFINE_STRING_TABLE_LOOKUP_TO_STRING(name,type,)
2016-03-04 17:28:04 +01:00
#define DEFINE_PRIVATE_STRING_TABLE_LOOKUP(name,type) _DEFINE_STRING_TABLE_LOOKUP(name,type,static)
#define DEFINE_PRIVATE_STRING_TABLE_LOOKUP_TO_STRING(name,type) _DEFINE_STRING_TABLE_LOOKUP_TO_STRING(name,type,static)
#define DEFINE_PRIVATE_STRING_TABLE_LOOKUP_FROM_STRING(name,type) _DEFINE_STRING_TABLE_LOOKUP_FROM_STRING(name,type,static)
#define DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(name,type,yes) _DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(name,type,yes,)
/* For string conversions where numbers are also acceptable */
#define DEFINE_STRING_TABLE_LOOKUP_WITH_FALLBACK(name,type,max) \
_DEFINE_STRING_TABLE_LOOKUP_TO_STRING_FALLBACK(name,type,max,) \
_DEFINE_STRING_TABLE_LOOKUP_FROM_STRING_FALLBACK(name,type,max,)
2016-03-04 17:28:04 +01:00
#define DEFINE_PRIVATE_STRING_TABLE_LOOKUP_TO_STRING_FALLBACK(name,type,max) \
_DEFINE_STRING_TABLE_LOOKUP_TO_STRING_FALLBACK(name,type,max,static)
#define DEFINE_PRIVATE_STRING_TABLE_LOOKUP_FROM_STRING_FALLBACK(name,type,max) \
_DEFINE_STRING_TABLE_LOOKUP_FROM_STRING_FALLBACK(name,type,max,static)
#define DUMP_STRING_TABLE(name,type,max) \
do { \
type _k; \
flockfile(stdout); \
for (_k = 0; _k < (max); _k++) { \
const char *_t; \
_t = name##_to_string(_k); \
if (!_t) \
continue; \
fputs_unlocked(_t, stdout); \
fputc_unlocked('\n', stdout); \
} \
funlockfile(stdout); \
} while(false)