systemd: update code from upstream
This is a direct dump from systemd git on 2016-06-29, git commit 2e0d8df13b1c1deda7b5769accae9e6cd5bf5966. ====== SYSTEMD_DIR=../systemd COMMIT=2e0d8df13b1c1deda7b5769accae9e6cd5bf5966 ( cd "$SYSTEMD_DIR" git checkout "$COMMIT" git reset --hard git clean -fdx ) git ls-files :/src/systemd/src/ | xargs -d '\n' rm -f nm_copy_sd() { mkdir -p "./src/systemd/$(dirname "$1")" cp "$SYSTEMD_DIR/$1" "./src/systemd/$1" } nm_copy_sd "src/basic/alloc-util.c" nm_copy_sd "src/basic/alloc-util.h" nm_copy_sd "src/basic/async.h" nm_copy_sd "src/basic/escape.c" nm_copy_sd "src/basic/escape.h" nm_copy_sd "src/basic/ether-addr-util.c" nm_copy_sd "src/basic/ether-addr-util.h" nm_copy_sd "src/basic/extract-word.c" nm_copy_sd "src/basic/extract-word.h" nm_copy_sd "src/basic/fileio.c" nm_copy_sd "src/basic/fileio.h" nm_copy_sd "src/basic/fd-util.c" nm_copy_sd "src/basic/fd-util.h" nm_copy_sd "src/basic/fs-util.c" nm_copy_sd "src/basic/fs-util.h" nm_copy_sd "src/basic/hash-funcs.c" nm_copy_sd "src/basic/hash-funcs.h" nm_copy_sd "src/basic/hashmap.c" nm_copy_sd "src/basic/hashmap.h" nm_copy_sd "src/basic/hexdecoct.c" nm_copy_sd "src/basic/hexdecoct.h" nm_copy_sd "src/basic/hostname-util.c" nm_copy_sd "src/basic/hostname-util.h" nm_copy_sd "src/basic/in-addr-util.c" nm_copy_sd "src/basic/in-addr-util.h" nm_copy_sd "src/basic/io-util.c" nm_copy_sd "src/basic/io-util.h" nm_copy_sd "src/basic/list.h" nm_copy_sd "src/basic/log.h" nm_copy_sd "src/basic/macro.h" nm_copy_sd "src/basic/mempool.h" nm_copy_sd "src/basic/mempool.c" nm_copy_sd "src/basic/parse-util.c" nm_copy_sd "src/basic/parse-util.h" nm_copy_sd "src/basic/path-util.c" nm_copy_sd "src/basic/path-util.h" nm_copy_sd "src/basic/prioq.h" nm_copy_sd "src/basic/prioq.c" nm_copy_sd "src/basic/random-util.c" nm_copy_sd "src/basic/random-util.h" nm_copy_sd "src/basic/refcnt.h" nm_copy_sd "src/basic/set.h" nm_copy_sd "src/basic/signal-util.h" nm_copy_sd "src/basic/siphash24.c" nm_copy_sd "src/basic/siphash24.h" nm_copy_sd "src/basic/socket-util.c" nm_copy_sd "src/basic/socket-util.h" nm_copy_sd "src/basic/sparse-endian.h" nm_copy_sd "src/basic/stdio-util.h" nm_copy_sd "src/basic/string-table.c" nm_copy_sd "src/basic/string-table.h" nm_copy_sd "src/basic/string-util.c" nm_copy_sd "src/basic/string-util.h" nm_copy_sd "src/basic/strv.c" nm_copy_sd "src/basic/strv.h" nm_copy_sd "src/basic/time-util.c" nm_copy_sd "src/basic/time-util.h" nm_copy_sd "src/basic/umask-util.h" nm_copy_sd "src/basic/unaligned.h" nm_copy_sd "src/basic/utf8.c" nm_copy_sd "src/basic/utf8.h" nm_copy_sd "src/basic/util.c" nm_copy_sd "src/basic/util.h" nm_copy_sd "src/libsystemd-network/arp-util.c" nm_copy_sd "src/libsystemd-network/arp-util.h" nm_copy_sd "src/libsystemd-network/dhcp6-internal.h" nm_copy_sd "src/libsystemd-network/dhcp6-lease-internal.h" nm_copy_sd "src/libsystemd-network/dhcp6-network.c" nm_copy_sd "src/libsystemd-network/dhcp6-option.c" nm_copy_sd "src/libsystemd-network/dhcp6-protocol.h" nm_copy_sd "src/libsystemd-network/dhcp-identifier.c" nm_copy_sd "src/libsystemd-network/dhcp-identifier.h" nm_copy_sd "src/libsystemd-network/dhcp-internal.h" nm_copy_sd "src/libsystemd-network/dhcp-lease-internal.h" nm_copy_sd "src/libsystemd-network/dhcp-network.c" nm_copy_sd "src/libsystemd-network/dhcp-option.c" nm_copy_sd "src/libsystemd-network/dhcp-packet.c" nm_copy_sd "src/libsystemd-network/dhcp-protocol.h" nm_copy_sd "src/libsystemd-network/lldp-internal.h" nm_copy_sd "src/libsystemd-network/lldp-neighbor.c" nm_copy_sd "src/libsystemd-network/lldp-neighbor.h" nm_copy_sd "src/libsystemd-network/lldp-network.c" nm_copy_sd "src/libsystemd-network/lldp-network.h" nm_copy_sd "src/libsystemd-network/network-internal.c" nm_copy_sd "src/libsystemd-network/network-internal.h" nm_copy_sd "src/libsystemd-network/sd-dhcp6-client.c" nm_copy_sd "src/libsystemd-network/sd-dhcp6-lease.c" nm_copy_sd "src/libsystemd-network/sd-dhcp-client.c" nm_copy_sd "src/libsystemd-network/sd-dhcp-lease.c" nm_copy_sd "src/libsystemd-network/sd-ipv4ll.c" nm_copy_sd "src/libsystemd-network/sd-ipv4acd.c" nm_copy_sd "src/libsystemd-network/sd-lldp.c" nm_copy_sd "src/libsystemd/sd-event/sd-event.c" nm_copy_sd "src/libsystemd/sd-id128/sd-id128.c" nm_copy_sd "src/shared/dns-domain.c" nm_copy_sd "src/shared/dns-domain.h" nm_copy_sd "src/systemd/_sd-common.h" nm_copy_sd "src/systemd/sd-dhcp6-client.h" nm_copy_sd "src/systemd/sd-dhcp6-lease.h" nm_copy_sd "src/systemd/sd-dhcp-client.h" nm_copy_sd "src/systemd/sd-dhcp-lease.h" nm_copy_sd "src/systemd/sd-event.h" nm_copy_sd "src/systemd/sd-ndisc.h" nm_copy_sd "src/systemd/sd-id128.h" nm_copy_sd "src/systemd/sd-ipv4acd.h" nm_copy_sd "src/systemd/sd-ipv4ll.h" nm_copy_sd "src/systemd/sd-lldp.h"
This commit is contained in:
@@ -1764,6 +1764,9 @@ void *ordered_hashmap_next(OrderedHashmap *h, const void *key) {
|
||||
int set_consume(Set *s, void *value) {
|
||||
int r;
|
||||
|
||||
assert(s);
|
||||
assert(value);
|
||||
|
||||
r = set_put(s, value);
|
||||
if (r <= 0)
|
||||
free(value);
|
||||
@@ -1791,6 +1794,8 @@ int set_put_strdupv(Set *s, char **l) {
|
||||
int n = 0, r;
|
||||
char **i;
|
||||
|
||||
assert(s);
|
||||
|
||||
STRV_FOREACH(i, l) {
|
||||
r = set_put_strdup(s, *i);
|
||||
if (r < 0)
|
||||
@@ -1801,3 +1806,23 @@ int set_put_strdupv(Set *s, char **l) {
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
int set_put_strsplit(Set *s, const char *v, const char *separators, ExtractFlags flags) {
|
||||
const char *p = v;
|
||||
int r;
|
||||
|
||||
assert(s);
|
||||
assert(v);
|
||||
|
||||
for (;;) {
|
||||
char *word;
|
||||
|
||||
r = extract_first_word(&p, &word, separators, flags);
|
||||
if (r <= 0)
|
||||
return r;
|
||||
|
||||
r = set_consume(s, word);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
}
|
||||
|
@@ -20,26 +20,36 @@
|
||||
#include <arpa/inet.h>
|
||||
#include <endian.h>
|
||||
#include <errno.h>
|
||||
#include <net/if.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "alloc-util.h"
|
||||
#include "in-addr-util.h"
|
||||
#include "macro.h"
|
||||
#include "parse-util.h"
|
||||
#include "util.h"
|
||||
|
||||
bool in4_addr_is_null(const struct in_addr *a) {
|
||||
return a->s_addr == 0;
|
||||
}
|
||||
|
||||
bool in6_addr_is_null(const struct in6_addr *a) {
|
||||
return
|
||||
a->s6_addr32[0] == 0 &&
|
||||
a->s6_addr32[1] == 0 &&
|
||||
a->s6_addr32[2] == 0 &&
|
||||
a->s6_addr32[3] == 0;
|
||||
}
|
||||
|
||||
int in_addr_is_null(int family, const union in_addr_union *u) {
|
||||
assert(u);
|
||||
|
||||
if (family == AF_INET)
|
||||
return u->in.s_addr == 0;
|
||||
return in4_addr_is_null(&u->in);
|
||||
|
||||
if (family == AF_INET6)
|
||||
return
|
||||
u->in6.s6_addr32[0] == 0 &&
|
||||
u->in6.s6_addr32[1] == 0 &&
|
||||
u->in6.s6_addr32[2] == 0 &&
|
||||
u->in6.s6_addr32[3] == 0;
|
||||
return in6_addr_is_null(&u->in6);
|
||||
|
||||
return -EAFNOSUPPORT;
|
||||
}
|
||||
@@ -224,6 +234,48 @@ int in_addr_to_string(int family, const union in_addr_union *u, char **ret) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int in_addr_ifindex_to_string(int family, const union in_addr_union *u, int ifindex, char **ret) {
|
||||
size_t l;
|
||||
char *x;
|
||||
int r;
|
||||
|
||||
assert(u);
|
||||
assert(ret);
|
||||
|
||||
/* Much like in_addr_to_string(), but optionally appends the zone interface index to the address, to properly
|
||||
* handle IPv6 link-local addresses. */
|
||||
|
||||
if (family != AF_INET6)
|
||||
goto fallback;
|
||||
if (ifindex <= 0)
|
||||
goto fallback;
|
||||
|
||||
r = in_addr_is_link_local(family, u);
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (r == 0)
|
||||
goto fallback;
|
||||
|
||||
l = INET6_ADDRSTRLEN + 1 + DECIMAL_STR_MAX(ifindex) + 1;
|
||||
x = new(char, l);
|
||||
if (!x)
|
||||
return -ENOMEM;
|
||||
|
||||
errno = 0;
|
||||
if (!inet_ntop(family, u, x, l)) {
|
||||
free(x);
|
||||
return errno > 0 ? -errno : -EINVAL;
|
||||
}
|
||||
|
||||
sprintf(strchr(x, 0), "%%%i", ifindex);
|
||||
*ret = x;
|
||||
|
||||
return 0;
|
||||
|
||||
fallback:
|
||||
return in_addr_to_string(family, u, ret);
|
||||
}
|
||||
|
||||
int in_addr_from_string(int family, const char *s, union in_addr_union *ret) {
|
||||
|
||||
assert(s);
|
||||
@@ -261,6 +313,47 @@ int in_addr_from_string_auto(const char *s, int *family, union in_addr_union *re
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
int in_addr_ifindex_from_string_auto(const char *s, int *family, union in_addr_union *ret, int *ifindex) {
|
||||
const char *suffix;
|
||||
int r, ifi = 0;
|
||||
|
||||
assert(s);
|
||||
assert(family);
|
||||
assert(ret);
|
||||
|
||||
/* Similar to in_addr_from_string_auto() but also parses an optionally appended IPv6 zone suffix ("scope id")
|
||||
* if one is found. */
|
||||
|
||||
suffix = strchr(s, '%');
|
||||
if (suffix) {
|
||||
|
||||
if (ifindex) {
|
||||
/* If we shall return the interface index, try to parse it */
|
||||
r = parse_ifindex(suffix + 1, &ifi);
|
||||
if (r < 0) {
|
||||
unsigned u;
|
||||
|
||||
u = if_nametoindex(suffix + 1);
|
||||
if (u <= 0)
|
||||
return -errno;
|
||||
|
||||
ifi = (int) u;
|
||||
}
|
||||
}
|
||||
|
||||
s = strndupa(s, suffix - s);
|
||||
}
|
||||
|
||||
r = in_addr_from_string_auto(s, family, ret);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (ifindex)
|
||||
*ifindex = ifi;
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
unsigned char in_addr_netmask_to_prefixlen(const struct in_addr *addr) {
|
||||
assert(addr);
|
||||
|
||||
|
@@ -36,6 +36,9 @@ struct in_addr_data {
|
||||
union in_addr_union address;
|
||||
};
|
||||
|
||||
bool in4_addr_is_null(const struct in_addr *a);
|
||||
bool in6_addr_is_null(const struct in6_addr *a);
|
||||
|
||||
int in_addr_is_null(int family, const union in_addr_union *u);
|
||||
int in_addr_is_link_local(int family, const union in_addr_union *u);
|
||||
int in_addr_is_localhost(int family, const union in_addr_union *u);
|
||||
@@ -43,8 +46,10 @@ int in_addr_equal(int family, const union in_addr_union *a, const union in_addr_
|
||||
int in_addr_prefix_intersect(int family, const union in_addr_union *a, unsigned aprefixlen, const union in_addr_union *b, unsigned bprefixlen);
|
||||
int in_addr_prefix_next(int family, union in_addr_union *u, unsigned prefixlen);
|
||||
int in_addr_to_string(int family, const union in_addr_union *u, char **ret);
|
||||
int in_addr_ifindex_to_string(int family, const union in_addr_union *u, int ifindex, char **ret);
|
||||
int in_addr_from_string(int family, const char *s, union in_addr_union *ret);
|
||||
int in_addr_from_string_auto(const char *s, int *family, union in_addr_union *ret);
|
||||
int in_addr_ifindex_from_string_auto(const char *s, int *family, union in_addr_union *ret, int *ifindex);
|
||||
unsigned char in_addr_netmask_to_prefixlen(const struct in_addr *addr);
|
||||
struct in_addr* in_addr_prefixlen_to_netmask(struct in_addr *addr, unsigned char prefixlen);
|
||||
int in_addr_default_prefixlen(const struct in_addr *addr, unsigned char *prefixlen);
|
||||
|
@@ -89,6 +89,15 @@
|
||||
#define UNIQ_T(x, uniq) CONCATENATE(__unique_prefix_, CONCATENATE(x, uniq))
|
||||
#define UNIQ __COUNTER__
|
||||
|
||||
/* builtins */
|
||||
#if __SIZEOF_INT__ == 4
|
||||
#define BUILTIN_FFS_U32(x) __builtin_ffs(x);
|
||||
#elif __SIZEOF_LONG__ == 4
|
||||
#define BUILTIN_FFS_U32(x) __builtin_ffsl(x);
|
||||
#else
|
||||
#error "neither int nor long are four bytes long?!?"
|
||||
#endif
|
||||
|
||||
/* Rounds up */
|
||||
|
||||
#define ALIGN4(l) (((l) + 3) & ~3)
|
||||
|
@@ -532,3 +532,22 @@ int parse_fractional_part_u(const char **p, size_t digits, unsigned *res) {
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int parse_percent(const char *p) {
|
||||
const char *pc, *n;
|
||||
unsigned v;
|
||||
int r;
|
||||
|
||||
pc = endswith(p, "%");
|
||||
if (!pc)
|
||||
return -EINVAL;
|
||||
|
||||
n = strndupa(p, pc - p);
|
||||
r = safe_atou(n, &v);
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (v > 100)
|
||||
return -ERANGE;
|
||||
|
||||
return (int) v;
|
||||
}
|
||||
|
@@ -105,3 +105,5 @@ static inline int safe_atozu(const char *s, size_t *ret_u) {
|
||||
int safe_atod(const char *s, double *ret_d);
|
||||
|
||||
int parse_fractional_part_u(const char **s, size_t digits, unsigned *res);
|
||||
|
||||
int parse_percent(const char *p);
|
||||
|
@@ -46,7 +46,7 @@ int dev_urandom(void *p, size_t n) {
|
||||
* never block, and will always return some data from the
|
||||
* kernel, regardless if the random pool is fully initialized
|
||||
* or not. It thus makes no guarantee for the quality of the
|
||||
* returned entropy, but is good enough for or usual usecases
|
||||
* returned entropy, but is good enough for our usual usecases
|
||||
* of seeding the hash functions for hashtable */
|
||||
|
||||
/* Use the getrandom() syscall unless we know we don't have
|
||||
|
@@ -19,6 +19,7 @@
|
||||
along with systemd; If not, see <http://www.gnu.org/licenses/>.
|
||||
***/
|
||||
|
||||
#include "extract-word.h"
|
||||
#include "hashmap.h"
|
||||
#include "macro.h"
|
||||
|
||||
@@ -122,6 +123,7 @@ static inline char **set_get_strv(Set *s) {
|
||||
int set_consume(Set *s, void *value);
|
||||
int set_put_strdup(Set *s, const char *p);
|
||||
int set_put_strdupv(Set *s, char **l);
|
||||
int set_put_strsplit(Set *s, const char *v, const char *separators, ExtractFlags flags);
|
||||
|
||||
#define SET_FOREACH(e, s, i) \
|
||||
for ((i) = ITERATOR_FIRST; set_iterate((s), &(i), (void**)&(e)); )
|
||||
|
@@ -17,6 +17,8 @@
|
||||
coding style)
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include "macro.h"
|
||||
#include "siphash24.h"
|
||||
#include "unaligned.h"
|
||||
|
@@ -85,7 +85,7 @@ int socket_address_parse(SocketAddress *a, const char *s) {
|
||||
return -EINVAL;
|
||||
|
||||
a->sockaddr.in6.sin6_family = AF_INET6;
|
||||
a->sockaddr.in6.sin6_port = htons((uint16_t) u);
|
||||
a->sockaddr.in6.sin6_port = htobe16((uint16_t)u);
|
||||
a->size = sizeof(struct sockaddr_in6);
|
||||
|
||||
} else if (*s == '/') {
|
||||
@@ -133,7 +133,7 @@ int socket_address_parse(SocketAddress *a, const char *s) {
|
||||
if (r > 0) {
|
||||
/* Gotcha, it's a traditional IPv4 address */
|
||||
a->sockaddr.in.sin_family = AF_INET;
|
||||
a->sockaddr.in.sin_port = htons((uint16_t) u);
|
||||
a->sockaddr.in.sin_port = htobe16((uint16_t)u);
|
||||
a->size = sizeof(struct sockaddr_in);
|
||||
} else {
|
||||
unsigned idx;
|
||||
@@ -147,7 +147,7 @@ int socket_address_parse(SocketAddress *a, const char *s) {
|
||||
return -EINVAL;
|
||||
|
||||
a->sockaddr.in6.sin6_family = AF_INET6;
|
||||
a->sockaddr.in6.sin6_port = htons((uint16_t) u);
|
||||
a->sockaddr.in6.sin6_port = htobe16((uint16_t)u);
|
||||
a->sockaddr.in6.sin6_scope_id = idx;
|
||||
a->sockaddr.in6.sin6_addr = in6addr_any;
|
||||
a->size = sizeof(struct sockaddr_in6);
|
||||
@@ -164,12 +164,12 @@ int socket_address_parse(SocketAddress *a, const char *s) {
|
||||
|
||||
if (socket_ipv6_is_supported()) {
|
||||
a->sockaddr.in6.sin6_family = AF_INET6;
|
||||
a->sockaddr.in6.sin6_port = htons((uint16_t) u);
|
||||
a->sockaddr.in6.sin6_port = htobe16((uint16_t)u);
|
||||
a->sockaddr.in6.sin6_addr = in6addr_any;
|
||||
a->size = sizeof(struct sockaddr_in6);
|
||||
} else {
|
||||
a->sockaddr.in.sin_family = AF_INET;
|
||||
a->sockaddr.in.sin_port = htons((uint16_t) u);
|
||||
a->sockaddr.in.sin_port = htobe16((uint16_t)u);
|
||||
a->sockaddr.in.sin_addr.s_addr = INADDR_ANY;
|
||||
a->size = sizeof(struct sockaddr_in);
|
||||
}
|
||||
@@ -488,9 +488,7 @@ int sockaddr_port(const struct sockaddr *_sa) {
|
||||
if (!IN_SET(sa->sa.sa_family, AF_INET, AF_INET6))
|
||||
return -EAFNOSUPPORT;
|
||||
|
||||
return ntohs(sa->sa.sa_family == AF_INET6 ?
|
||||
sa->in6.sin6_port :
|
||||
sa->in.sin_port);
|
||||
return be16toh(sa->sa.sa_family == AF_INET6 ? sa->in6.sin6_port : sa->in.sin_port);
|
||||
}
|
||||
|
||||
int sockaddr_pretty(const struct sockaddr *_sa, socklen_t salen, bool translate_ipv6, bool include_port, char **ret) {
|
||||
@@ -506,13 +504,13 @@ int sockaddr_pretty(const struct sockaddr *_sa, socklen_t salen, bool translate_
|
||||
case AF_INET: {
|
||||
uint32_t a;
|
||||
|
||||
a = ntohl(sa->in.sin_addr.s_addr);
|
||||
a = be32toh(sa->in.sin_addr.s_addr);
|
||||
|
||||
if (include_port)
|
||||
r = asprintf(&p,
|
||||
"%u.%u.%u.%u:%u",
|
||||
a >> 24, (a >> 16) & 0xFF, (a >> 8) & 0xFF, a & 0xFF,
|
||||
ntohs(sa->in.sin_port));
|
||||
be16toh(sa->in.sin_port));
|
||||
else
|
||||
r = asprintf(&p,
|
||||
"%u.%u.%u.%u",
|
||||
@@ -534,7 +532,7 @@ int sockaddr_pretty(const struct sockaddr *_sa, socklen_t salen, bool translate_
|
||||
r = asprintf(&p,
|
||||
"%u.%u.%u.%u:%u",
|
||||
a[0], a[1], a[2], a[3],
|
||||
ntohs(sa->in6.sin6_port));
|
||||
be16toh(sa->in6.sin6_port));
|
||||
else
|
||||
r = asprintf(&p,
|
||||
"%u.%u.%u.%u",
|
||||
@@ -550,7 +548,7 @@ int sockaddr_pretty(const struct sockaddr *_sa, socklen_t salen, bool translate_
|
||||
r = asprintf(&p,
|
||||
"[%s]:%u",
|
||||
a,
|
||||
ntohs(sa->in6.sin6_port));
|
||||
be16toh(sa->in6.sin6_port));
|
||||
if (r < 0)
|
||||
return -ENOMEM;
|
||||
} else {
|
||||
@@ -988,7 +986,7 @@ ssize_t next_datagram_size_fd(int fd) {
|
||||
|
||||
l = recv(fd, NULL, 0, MSG_PEEK|MSG_TRUNC);
|
||||
if (l < 0) {
|
||||
if (errno == EOPNOTSUPP)
|
||||
if (errno == EOPNOTSUPP || errno == EFAULT)
|
||||
goto fallback;
|
||||
|
||||
return -errno;
|
||||
|
@@ -48,6 +48,8 @@ ssize_t string_table_lookup(const char * const *table, size_t len, const char *k
|
||||
#define _DEFINE_STRING_TABLE_LOOKUP_FROM_STRING_WITH_BOOLEAN(name,type,yes,scope) \
|
||||
scope type name##_from_string(const char *s) { \
|
||||
int b; \
|
||||
if (!s) \
|
||||
return -1; \
|
||||
b = parse_boolean(s); \
|
||||
if (b == 0) \
|
||||
return (type) 0; \
|
||||
|
@@ -66,6 +66,10 @@ static inline bool isempty(const char *p) {
|
||||
return !p || !p[0];
|
||||
}
|
||||
|
||||
static inline const char *empty_to_null(const char *p) {
|
||||
return isempty(p) ? NULL : p;
|
||||
}
|
||||
|
||||
static inline char *startswith(const char *s, const char *prefix) {
|
||||
size_t l;
|
||||
|
||||
|
@@ -139,16 +139,16 @@ char **strv_new_ap(const char *x, va_list ap) {
|
||||
va_list aq;
|
||||
|
||||
/* As a special trick we ignore all listed strings that equal
|
||||
* (const char*) -1. This is supposed to be used with the
|
||||
* STRV_IGNORE. This is supposed to be used with the
|
||||
* STRV_IFNOTNULL() macro to include possibly NULL strings in
|
||||
* the string list. */
|
||||
|
||||
if (x) {
|
||||
n = x == (const char*) -1 ? 0 : 1;
|
||||
n = x == STRV_IGNORE ? 0 : 1;
|
||||
|
||||
va_copy(aq, ap);
|
||||
while ((s = va_arg(aq, const char*))) {
|
||||
if (s == (const char*) -1)
|
||||
if (s == STRV_IGNORE)
|
||||
continue;
|
||||
|
||||
n++;
|
||||
@@ -162,7 +162,7 @@ char **strv_new_ap(const char *x, va_list ap) {
|
||||
return NULL;
|
||||
|
||||
if (x) {
|
||||
if (x != (const char*) -1) {
|
||||
if (x != STRV_IGNORE) {
|
||||
a[i] = strdup(x);
|
||||
if (!a[i])
|
||||
goto fail;
|
||||
@@ -171,7 +171,7 @@ char **strv_new_ap(const char *x, va_list ap) {
|
||||
|
||||
while ((s = va_arg(ap, const char*))) {
|
||||
|
||||
if (s == (const char*) -1)
|
||||
if (s == STRV_IGNORE)
|
||||
continue;
|
||||
|
||||
a[i] = strdup(s);
|
||||
@@ -804,11 +804,7 @@ char **strv_reverse(char **l) {
|
||||
return l;
|
||||
|
||||
for (i = 0; i < n / 2; i++) {
|
||||
char *t;
|
||||
|
||||
t = l[i];
|
||||
l[i] = l[n-1-i];
|
||||
l[n-1-i] = t;
|
||||
SWAP_TWO(l[i], l[n-1-i]);
|
||||
}
|
||||
|
||||
return l;
|
||||
@@ -838,7 +834,7 @@ bool strv_fnmatch(char* const* patterns, const char *s, int flags) {
|
||||
char* const* p;
|
||||
|
||||
STRV_FOREACH(p, patterns)
|
||||
if (fnmatch(*p, s, 0) == 0)
|
||||
if (fnmatch(*p, s, flags) == 0)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
|
@@ -69,8 +69,10 @@ bool strv_equal(char **a, char **b);
|
||||
char **strv_new(const char *x, ...) _sentinel_;
|
||||
char **strv_new_ap(const char *x, va_list ap);
|
||||
|
||||
#define STRV_IGNORE ((const char *) -1)
|
||||
|
||||
static inline const char* STRV_IFNOTNULL(const char *x) {
|
||||
return x ? x : (const char *) -1;
|
||||
return x ? x : STRV_IGNORE;
|
||||
}
|
||||
|
||||
static inline bool strv_isempty(char * const *l) {
|
||||
|
@@ -87,6 +87,16 @@ dual_timestamp* dual_timestamp_get(dual_timestamp *ts) {
|
||||
return ts;
|
||||
}
|
||||
|
||||
triple_timestamp* triple_timestamp_get(triple_timestamp *ts) {
|
||||
assert(ts);
|
||||
|
||||
ts->realtime = now(CLOCK_REALTIME);
|
||||
ts->monotonic = now(CLOCK_MONOTONIC);
|
||||
ts->boottime = clock_boottime_supported() ? now(CLOCK_BOOTTIME) : USEC_INFINITY;
|
||||
|
||||
return ts;
|
||||
}
|
||||
|
||||
dual_timestamp* dual_timestamp_from_realtime(dual_timestamp *ts, usec_t u) {
|
||||
int64_t delta;
|
||||
assert(ts);
|
||||
@@ -104,6 +114,24 @@ dual_timestamp* dual_timestamp_from_realtime(dual_timestamp *ts, usec_t u) {
|
||||
return ts;
|
||||
}
|
||||
|
||||
triple_timestamp* triple_timestamp_from_realtime(triple_timestamp *ts, usec_t u) {
|
||||
int64_t delta;
|
||||
|
||||
assert(ts);
|
||||
|
||||
if (u == USEC_INFINITY || u <= 0) {
|
||||
ts->realtime = ts->monotonic = ts->boottime = u;
|
||||
return ts;
|
||||
}
|
||||
|
||||
ts->realtime = u;
|
||||
delta = (int64_t) now(CLOCK_REALTIME) - (int64_t) u;
|
||||
ts->monotonic = usec_sub(now(CLOCK_MONOTONIC), delta);
|
||||
ts->boottime = clock_boottime_supported() ? usec_sub(now(CLOCK_BOOTTIME), delta) : USEC_INFINITY;
|
||||
|
||||
return ts;
|
||||
}
|
||||
|
||||
dual_timestamp* dual_timestamp_from_monotonic(dual_timestamp *ts, usec_t u) {
|
||||
int64_t delta;
|
||||
assert(ts);
|
||||
@@ -136,6 +164,26 @@ dual_timestamp* dual_timestamp_from_boottime_or_monotonic(dual_timestamp *ts, us
|
||||
return ts;
|
||||
}
|
||||
|
||||
usec_t triple_timestamp_by_clock(triple_timestamp *ts, clockid_t clock) {
|
||||
|
||||
switch (clock) {
|
||||
|
||||
case CLOCK_REALTIME:
|
||||
case CLOCK_REALTIME_ALARM:
|
||||
return ts->realtime;
|
||||
|
||||
case CLOCK_MONOTONIC:
|
||||
return ts->monotonic;
|
||||
|
||||
case CLOCK_BOOTTIME:
|
||||
case CLOCK_BOOTTIME_ALARM:
|
||||
return ts->boottime;
|
||||
|
||||
default:
|
||||
return USEC_INFINITY;
|
||||
}
|
||||
}
|
||||
|
||||
usec_t timespec_load(const struct timespec *ts) {
|
||||
assert(ts);
|
||||
|
||||
@@ -1107,6 +1155,30 @@ clockid_t clock_boottime_or_monotonic(void) {
|
||||
return CLOCK_MONOTONIC;
|
||||
}
|
||||
|
||||
bool clock_supported(clockid_t clock) {
|
||||
struct timespec ts;
|
||||
|
||||
switch (clock) {
|
||||
|
||||
case CLOCK_MONOTONIC:
|
||||
case CLOCK_REALTIME:
|
||||
return true;
|
||||
|
||||
case CLOCK_BOOTTIME:
|
||||
return clock_boottime_supported();
|
||||
|
||||
case CLOCK_BOOTTIME_ALARM:
|
||||
if (!clock_boottime_supported())
|
||||
return false;
|
||||
|
||||
/* fall through, after checking the cached value for CLOCK_BOOTTIME. */
|
||||
|
||||
default:
|
||||
/* For everything else, check properly */
|
||||
return clock_gettime(clock, &ts) >= 0;
|
||||
}
|
||||
}
|
||||
|
||||
int get_timezone(char **tz) {
|
||||
_cleanup_free_ char *t = NULL;
|
||||
const char *e;
|
||||
|
@@ -39,6 +39,12 @@ typedef struct dual_timestamp {
|
||||
usec_t monotonic;
|
||||
} dual_timestamp;
|
||||
|
||||
typedef struct triple_timestamp {
|
||||
usec_t realtime;
|
||||
usec_t monotonic;
|
||||
usec_t boottime;
|
||||
} triple_timestamp;
|
||||
|
||||
#define USEC_INFINITY ((usec_t) -1)
|
||||
#define NSEC_INFINITY ((nsec_t) -1)
|
||||
|
||||
@@ -69,7 +75,8 @@ typedef struct dual_timestamp {
|
||||
|
||||
#define TIME_T_MAX (time_t)((UINTMAX_C(1) << ((sizeof(time_t) << 3) - 1)) - 1)
|
||||
|
||||
#define DUAL_TIMESTAMP_NULL ((struct dual_timestamp) { 0ULL, 0ULL })
|
||||
#define DUAL_TIMESTAMP_NULL ((struct dual_timestamp) {})
|
||||
#define TRIPLE_TIMESTAMP_NULL ((struct triple_timestamp) {})
|
||||
|
||||
usec_t now(clockid_t clock);
|
||||
nsec_t now_nsec(clockid_t clock);
|
||||
@@ -79,11 +86,28 @@ dual_timestamp* dual_timestamp_from_realtime(dual_timestamp *ts, usec_t u);
|
||||
dual_timestamp* dual_timestamp_from_monotonic(dual_timestamp *ts, usec_t u);
|
||||
dual_timestamp* dual_timestamp_from_boottime_or_monotonic(dual_timestamp *ts, usec_t u);
|
||||
|
||||
triple_timestamp* triple_timestamp_get(triple_timestamp *ts);
|
||||
triple_timestamp* triple_timestamp_from_realtime(triple_timestamp *ts, usec_t u);
|
||||
|
||||
#define DUAL_TIMESTAMP_HAS_CLOCK(clock) \
|
||||
IN_SET(clock, CLOCK_REALTIME, CLOCK_REALTIME_ALARM, CLOCK_MONOTONIC)
|
||||
|
||||
#define TRIPLE_TIMESTAMP_HAS_CLOCK(clock) \
|
||||
IN_SET(clock, CLOCK_REALTIME, CLOCK_REALTIME_ALARM, CLOCK_MONOTONIC, CLOCK_BOOTTIME, CLOCK_BOOTTIME_ALARM)
|
||||
|
||||
static inline bool dual_timestamp_is_set(dual_timestamp *ts) {
|
||||
return ((ts->realtime > 0 && ts->realtime != USEC_INFINITY) ||
|
||||
(ts->monotonic > 0 && ts->monotonic != USEC_INFINITY));
|
||||
}
|
||||
|
||||
static inline bool triple_timestamp_is_set(triple_timestamp *ts) {
|
||||
return ((ts->realtime > 0 && ts->realtime != USEC_INFINITY) ||
|
||||
(ts->monotonic > 0 && ts->monotonic != USEC_INFINITY) ||
|
||||
(ts->boottime > 0 && ts->boottime != USEC_INFINITY));
|
||||
}
|
||||
|
||||
usec_t triple_timestamp_by_clock(triple_timestamp *ts, clockid_t clock);
|
||||
|
||||
usec_t timespec_load(const struct timespec *ts) _pure_;
|
||||
struct timespec *timespec_store(struct timespec *ts, usec_t u);
|
||||
|
||||
@@ -113,6 +137,7 @@ int get_timezones(char ***l);
|
||||
bool timezone_is_valid(const char *name);
|
||||
|
||||
bool clock_boottime_supported(void);
|
||||
bool clock_supported(clockid_t clock);
|
||||
clockid_t clock_boottime_or_monotonic(void);
|
||||
|
||||
#define xstrftime(buf, fmt, tm) \
|
||||
|
@@ -109,3 +109,21 @@ static inline void unaligned_write_le64(void *_u, uint64_t a) {
|
||||
unaligned_write_le32(u, (uint32_t) a);
|
||||
unaligned_write_le32(u + 4, (uint32_t) (a >> 32));
|
||||
}
|
||||
|
||||
#if __BYTE_ORDER == __BIG_ENDIAN
|
||||
#define unaligned_read_ne16 unaligned_read_be16
|
||||
#define unaligned_read_ne32 unaligned_read_be32
|
||||
#define unaligned_read_ne64 unaligned_read_be64
|
||||
|
||||
#define unaligned_write_ne16 unaligned_write_be16
|
||||
#define unaligned_write_ne32 unaligned_write_be32
|
||||
#define unaligned_write_ne64 unaligned_write_be64
|
||||
#else
|
||||
#define unaligned_read_ne16 unaligned_read_le16
|
||||
#define unaligned_read_ne32 unaligned_read_le32
|
||||
#define unaligned_read_ne64 unaligned_read_le64
|
||||
|
||||
#define unaligned_write_ne16 unaligned_write_le16
|
||||
#define unaligned_write_ne32 unaligned_write_le32
|
||||
#define unaligned_write_ne64 unaligned_write_le64
|
||||
#endif
|
||||
|
@@ -36,6 +36,7 @@
|
||||
|
||||
#include "alloc-util.h"
|
||||
#include "build.h"
|
||||
#include "cgroup-util.h"
|
||||
#include "def.h"
|
||||
#include "dirent-util.h"
|
||||
#include "fd-util.h"
|
||||
@@ -64,6 +65,7 @@ assert_cc(EAGAIN == EWOULDBLOCK);
|
||||
|
||||
int saved_argc = 0;
|
||||
char **saved_argv = NULL;
|
||||
static int saved_in_initrd = -1;
|
||||
|
||||
size_t page_size(void) {
|
||||
static thread_local size_t pgsz = 0;
|
||||
@@ -454,11 +456,10 @@ int fork_agent(pid_t *pid, const int except[], unsigned n_except, const char *pa
|
||||
}
|
||||
|
||||
bool in_initrd(void) {
|
||||
static int saved = -1;
|
||||
struct statfs s;
|
||||
|
||||
if (saved >= 0)
|
||||
return saved;
|
||||
if (saved_in_initrd >= 0)
|
||||
return saved_in_initrd;
|
||||
|
||||
/* We make two checks here:
|
||||
*
|
||||
@@ -470,11 +471,15 @@ bool in_initrd(void) {
|
||||
* emptying when transititioning to the main systemd.
|
||||
*/
|
||||
|
||||
saved = access("/etc/initrd-release", F_OK) >= 0 &&
|
||||
statfs("/", &s) >= 0 &&
|
||||
is_temporary_fs(&s);
|
||||
saved_in_initrd = access("/etc/initrd-release", F_OK) >= 0 &&
|
||||
statfs("/", &s) >= 0 &&
|
||||
is_temporary_fs(&s);
|
||||
|
||||
return saved;
|
||||
return saved_in_initrd;
|
||||
}
|
||||
|
||||
void in_initrd_force(bool value) {
|
||||
saved_in_initrd = value;
|
||||
}
|
||||
|
||||
/* hey glibc, APIs with callbacks without a user pointer are so useless */
|
||||
@@ -767,15 +772,64 @@ int namespace_enter(int pidns_fd, int mntns_fd, int netns_fd, int userns_fd, int
|
||||
}
|
||||
|
||||
uint64_t physical_memory(void) {
|
||||
long mem;
|
||||
_cleanup_free_ char *root = NULL, *value = NULL;
|
||||
uint64_t mem, lim;
|
||||
size_t ps;
|
||||
long sc;
|
||||
|
||||
/* We return this as uint64_t in case we are running as 32bit
|
||||
* process on a 64bit kernel with huge amounts of memory */
|
||||
/* We return this as uint64_t in case we are running as 32bit process on a 64bit kernel with huge amounts of
|
||||
* memory.
|
||||
*
|
||||
* In order to support containers nicely that have a configured memory limit we'll take the minimum of the
|
||||
* physically reported amount of memory and the limit configured for the root cgroup, if there is any. */
|
||||
|
||||
mem = sysconf(_SC_PHYS_PAGES);
|
||||
assert(mem > 0);
|
||||
sc = sysconf(_SC_PHYS_PAGES);
|
||||
assert(sc > 0);
|
||||
|
||||
return (uint64_t) mem * (uint64_t) page_size();
|
||||
ps = page_size();
|
||||
mem = (uint64_t) sc * (uint64_t) ps;
|
||||
|
||||
if (cg_get_root_path(&root) < 0)
|
||||
return mem;
|
||||
|
||||
if (cg_get_attribute("memory", root, "memory.limit_in_bytes", &value))
|
||||
return mem;
|
||||
|
||||
if (safe_atou64(value, &lim) < 0)
|
||||
return mem;
|
||||
|
||||
/* Make sure the limit is a multiple of our own page size */
|
||||
lim /= ps;
|
||||
lim *= ps;
|
||||
|
||||
return MIN(mem, lim);
|
||||
}
|
||||
|
||||
uint64_t physical_memory_scale(uint64_t v, uint64_t max) {
|
||||
uint64_t p, m, ps, r;
|
||||
|
||||
assert(max > 0);
|
||||
|
||||
/* Returns the physical memory size, multiplied by v divided by max. Returns UINT64_MAX on overflow. On success
|
||||
* the result is a multiple of the page size (rounds down). */
|
||||
|
||||
ps = page_size();
|
||||
assert(ps > 0);
|
||||
|
||||
p = physical_memory() / ps;
|
||||
assert(p > 0);
|
||||
|
||||
m = p * v;
|
||||
if (m / p != v)
|
||||
return UINT64_MAX;
|
||||
|
||||
m /= max;
|
||||
|
||||
r = m * ps;
|
||||
if (r / ps != m)
|
||||
return UINT64_MAX;
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
int update_reboot_parameter_and_warn(const char *param) {
|
||||
|
@@ -86,6 +86,7 @@ int prot_from_flags(int flags) _const_;
|
||||
int fork_agent(pid_t *pid, const int except[], unsigned n_except, const char *path, ...);
|
||||
|
||||
bool in_initrd(void);
|
||||
void in_initrd_force(bool value);
|
||||
|
||||
void *xbsearch_r(const void *key, const void *base, size_t nmemb, size_t size,
|
||||
int (*compar) (const void *, const void *, void *),
|
||||
@@ -183,6 +184,7 @@ int namespace_open(pid_t pid, int *pidns_fd, int *mntns_fd, int *netns_fd, int *
|
||||
int namespace_enter(int pidns_fd, int mntns_fd, int netns_fd, int userns_fd, int root_fd);
|
||||
|
||||
uint64_t physical_memory(void);
|
||||
uint64_t physical_memory_scale(uint64_t v, uint64_t max);
|
||||
|
||||
int update_reboot_parameter_and_warn(const char *param);
|
||||
|
||||
|
@@ -79,7 +79,7 @@ int arp_network_bind_raw_socket(int ifindex, be32_t address, const struct ether_
|
||||
};
|
||||
union sockaddr_union link = {
|
||||
.ll.sll_family = AF_PACKET,
|
||||
.ll.sll_protocol = htons(ETH_P_ARP),
|
||||
.ll.sll_protocol = htobe16(ETH_P_ARP),
|
||||
.ll.sll_ifindex = ifindex,
|
||||
.ll.sll_halen = ETH_ALEN,
|
||||
.ll.sll_addr = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff },
|
||||
@@ -112,17 +112,17 @@ static int arp_send_packet(int fd, int ifindex,
|
||||
bool announce) {
|
||||
union sockaddr_union link = {
|
||||
.ll.sll_family = AF_PACKET,
|
||||
.ll.sll_protocol = htons(ETH_P_ARP),
|
||||
.ll.sll_protocol = htobe16(ETH_P_ARP),
|
||||
.ll.sll_ifindex = ifindex,
|
||||
.ll.sll_halen = ETH_ALEN,
|
||||
.ll.sll_addr = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff },
|
||||
};
|
||||
struct ether_arp arp = {
|
||||
.ea_hdr.ar_hrd = htons(ARPHRD_ETHER), /* HTYPE */
|
||||
.ea_hdr.ar_pro = htons(ETHERTYPE_IP), /* PTYPE */
|
||||
.ea_hdr.ar_hrd = htobe16(ARPHRD_ETHER), /* HTYPE */
|
||||
.ea_hdr.ar_pro = htobe16(ETHERTYPE_IP), /* PTYPE */
|
||||
.ea_hdr.ar_hln = ETH_ALEN, /* HLEN */
|
||||
.ea_hdr.ar_pln = sizeof(be32_t), /* PLEN */
|
||||
.ea_hdr.ar_op = htons(ARPOP_REQUEST), /* REQUEST */
|
||||
.ea_hdr.ar_op = htobe16(ARPOP_REQUEST), /* REQUEST */
|
||||
};
|
||||
int r;
|
||||
|
||||
|
@@ -107,9 +107,9 @@ static int _bind_raw_socket(int ifindex, union sockaddr_union *link,
|
||||
return -errno;
|
||||
|
||||
link->ll.sll_family = AF_PACKET;
|
||||
link->ll.sll_protocol = htons(ETH_P_IP);
|
||||
link->ll.sll_protocol = htobe16(ETH_P_IP);
|
||||
link->ll.sll_ifindex = ifindex;
|
||||
link->ll.sll_hatype = htons(arp_type);
|
||||
link->ll.sll_hatype = htobe16(arp_type);
|
||||
link->ll.sll_halen = mac_addr_len;
|
||||
memcpy(link->ll.sll_addr, bcast_addr, mac_addr_len);
|
||||
|
||||
|
@@ -28,6 +28,8 @@
|
||||
#include "prioq.h"
|
||||
|
||||
struct sd_lldp {
|
||||
unsigned n_ref;
|
||||
|
||||
int ifindex;
|
||||
int fd;
|
||||
|
||||
|
@@ -360,9 +360,16 @@ end_marker:
|
||||
void lldp_neighbor_start_ttl(sd_lldp_neighbor *n) {
|
||||
assert(n);
|
||||
|
||||
if (n->ttl > 0)
|
||||
n->until = usec_add(now(clock_boottime_or_monotonic()), n->ttl * USEC_PER_SEC);
|
||||
else
|
||||
if (n->ttl > 0) {
|
||||
usec_t base;
|
||||
|
||||
/* Use the packet's timestamp if there is one known */
|
||||
base = triple_timestamp_by_clock(&n->timestamp, clock_boottime_or_monotonic());
|
||||
if (base <= 0 || base == USEC_INFINITY)
|
||||
base = now(clock_boottime_or_monotonic()); /* Otherwise, take the current time */
|
||||
|
||||
n->until = usec_add(base, n->ttl * USEC_PER_SEC);
|
||||
} else
|
||||
n->until = 0;
|
||||
|
||||
if (n->lldp)
|
||||
@@ -588,11 +595,11 @@ done:
|
||||
return 0;
|
||||
}
|
||||
|
||||
_public_ int sd_lldp_neighbor_get_ttl(sd_lldp_neighbor *n, uint16_t *ret) {
|
||||
_public_ int sd_lldp_neighbor_get_ttl(sd_lldp_neighbor *n, uint16_t *ret_sec) {
|
||||
assert_return(n, -EINVAL);
|
||||
assert_return(ret, -EINVAL);
|
||||
assert_return(ret_sec, -EINVAL);
|
||||
|
||||
*ret = n->ttl;
|
||||
*ret_sec = n->ttl;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -651,7 +658,7 @@ _public_ int sd_lldp_neighbor_get_enabled_capabilities(sd_lldp_neighbor *n, uint
|
||||
return 0;
|
||||
}
|
||||
|
||||
int sd_lldp_neighbor_from_raw(sd_lldp_neighbor **ret, const void *raw, size_t raw_size) {
|
||||
_public_ int sd_lldp_neighbor_from_raw(sd_lldp_neighbor **ret, const void *raw, size_t raw_size) {
|
||||
_cleanup_(sd_lldp_neighbor_unrefp) sd_lldp_neighbor *n = NULL;
|
||||
int r;
|
||||
|
||||
@@ -668,7 +675,7 @@ int sd_lldp_neighbor_from_raw(sd_lldp_neighbor **ret, const void *raw, size_t ra
|
||||
return r;
|
||||
|
||||
*ret = n;
|
||||
n = 0;
|
||||
n = NULL;
|
||||
|
||||
return r;
|
||||
}
|
||||
@@ -679,7 +686,7 @@ _public_ int sd_lldp_neighbor_tlv_rewind(sd_lldp_neighbor *n) {
|
||||
assert(n->raw_size >= sizeof(struct ether_header));
|
||||
n->rindex = sizeof(struct ether_header);
|
||||
|
||||
return 0;
|
||||
return n->rindex < n->raw_size;
|
||||
}
|
||||
|
||||
_public_ int sd_lldp_neighbor_tlv_next(sd_lldp_neighbor *n) {
|
||||
@@ -693,7 +700,7 @@ _public_ int sd_lldp_neighbor_tlv_next(sd_lldp_neighbor *n) {
|
||||
if (n->rindex + 2 > n->raw_size) /* Truncated message */
|
||||
return -EBADMSG;
|
||||
|
||||
length = LLDP_NEIGHBOR_LENGTH(n);
|
||||
length = LLDP_NEIGHBOR_TLV_LENGTH(n);
|
||||
if (n->rindex + 2 + length > n->raw_size)
|
||||
return -EBADMSG;
|
||||
|
||||
@@ -711,7 +718,7 @@ _public_ int sd_lldp_neighbor_tlv_get_type(sd_lldp_neighbor *n, uint8_t *type) {
|
||||
if (n->rindex + 2 > n->raw_size)
|
||||
return -EBADMSG;
|
||||
|
||||
*type = LLDP_NEIGHBOR_TYPE(n);
|
||||
*type = LLDP_NEIGHBOR_TLV_TYPE(n);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -743,14 +750,14 @@ _public_ int sd_lldp_neighbor_tlv_get_oui(sd_lldp_neighbor *n, uint8_t oui[3], u
|
||||
if (r == 0)
|
||||
return -ENXIO;
|
||||
|
||||
length = LLDP_NEIGHBOR_LENGTH(n);
|
||||
length = LLDP_NEIGHBOR_TLV_LENGTH(n);
|
||||
if (length < 4)
|
||||
return -EBADMSG;
|
||||
|
||||
if (n->rindex + 2 + length > n->raw_size)
|
||||
return -EBADMSG;
|
||||
|
||||
d = LLDP_NEIGHBOR_DATA(n);
|
||||
d = LLDP_NEIGHBOR_TLV_DATA(n);
|
||||
memcpy(oui, d, 3);
|
||||
*subtype = d[3];
|
||||
|
||||
@@ -782,8 +789,7 @@ _public_ int sd_lldp_neighbor_tlv_get_raw(sd_lldp_neighbor *n, const void **ret,
|
||||
if (n->rindex + 2 > n->raw_size)
|
||||
return -EBADMSG;
|
||||
|
||||
length = LLDP_NEIGHBOR_LENGTH(n);
|
||||
|
||||
length = LLDP_NEIGHBOR_TLV_LENGTH(n);
|
||||
if (n->rindex + 2 + length > n->raw_size)
|
||||
return -EBADMSG;
|
||||
|
||||
@@ -792,3 +798,16 @@ _public_ int sd_lldp_neighbor_tlv_get_raw(sd_lldp_neighbor *n, const void **ret,
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
_public_ int sd_lldp_neighbor_get_timestamp(sd_lldp_neighbor *n, clockid_t clock, uint64_t *ret) {
|
||||
assert_return(n, -EINVAL);
|
||||
assert_return(TRIPLE_TIMESTAMP_HAS_CLOCK(clock), -EOPNOTSUPP);
|
||||
assert_return(clock_supported(clock), -EOPNOTSUPP);
|
||||
assert_return(ret, -EINVAL);
|
||||
|
||||
if (!triple_timestamp_is_set(&n->timestamp))
|
||||
return -ENODATA;
|
||||
|
||||
*ret = triple_timestamp_by_clock(&n->timestamp, clock);
|
||||
return 0;
|
||||
}
|
||||
|
@@ -43,6 +43,8 @@ struct sd_lldp_neighbor {
|
||||
sd_lldp *lldp;
|
||||
unsigned n_ref;
|
||||
|
||||
triple_timestamp timestamp;
|
||||
|
||||
usec_t until;
|
||||
unsigned prioq_idx;
|
||||
|
||||
@@ -81,18 +83,18 @@ static inline void *LLDP_NEIGHBOR_RAW(const sd_lldp_neighbor *n) {
|
||||
return (uint8_t*) n + ALIGN(sizeof(sd_lldp_neighbor));
|
||||
}
|
||||
|
||||
static inline uint8_t LLDP_NEIGHBOR_TYPE(const sd_lldp_neighbor *n) {
|
||||
static inline uint8_t LLDP_NEIGHBOR_TLV_TYPE(const sd_lldp_neighbor *n) {
|
||||
return ((uint8_t*) LLDP_NEIGHBOR_RAW(n))[n->rindex] >> 1;
|
||||
}
|
||||
|
||||
static inline size_t LLDP_NEIGHBOR_LENGTH(const sd_lldp_neighbor *n) {
|
||||
static inline size_t LLDP_NEIGHBOR_TLV_LENGTH(const sd_lldp_neighbor *n) {
|
||||
uint8_t *p;
|
||||
|
||||
p = (uint8_t*) LLDP_NEIGHBOR_RAW(n) + n->rindex;
|
||||
return p[1] + (((size_t) (p[0] & 1)) << 8);
|
||||
}
|
||||
|
||||
static inline void* LLDP_NEIGHBOR_DATA(const sd_lldp_neighbor *n) {
|
||||
static inline void* LLDP_NEIGHBOR_TLV_DATA(const sd_lldp_neighbor *n) {
|
||||
return ((uint8_t*) LLDP_NEIGHBOR_RAW(n)) + n->rindex + 2;
|
||||
}
|
||||
|
||||
|
@@ -57,7 +57,8 @@ int lldp_network_bind_raw_socket(int ifindex) {
|
||||
|
||||
assert(ifindex > 0);
|
||||
|
||||
fd = socket(PF_PACKET, SOCK_RAW|SOCK_CLOEXEC|SOCK_NONBLOCK, htons(ETHERTYPE_LLDP));
|
||||
fd = socket(PF_PACKET, SOCK_RAW|SOCK_CLOEXEC|SOCK_NONBLOCK,
|
||||
htobe16(ETHERTYPE_LLDP));
|
||||
if (fd < 0)
|
||||
return -errno;
|
||||
|
||||
|
@@ -27,7 +27,7 @@
|
||||
#include "condition.h"
|
||||
#include "conf-parser.h"
|
||||
#include "dhcp-lease-internal.h"
|
||||
#include "ether-addr-util.c"
|
||||
#include "ether-addr-util.h"
|
||||
#include "hexdecoct.h"
|
||||
#include "log.h"
|
||||
#include "network-internal.h"
|
||||
@@ -380,18 +380,21 @@ int deserialize_in_addrs(struct in_addr **ret, const char *string) {
|
||||
return size;
|
||||
}
|
||||
|
||||
void serialize_in6_addrs(FILE *f, const struct in6_addr *addresses,
|
||||
size_t size) {
|
||||
void serialize_in6_addrs(FILE *f, const struct in6_addr *addresses, size_t size) {
|
||||
unsigned i;
|
||||
|
||||
assert(f);
|
||||
assert(addresses);
|
||||
assert(size);
|
||||
|
||||
for (i = 0; i < size; i++)
|
||||
fprintf(f, SD_NDISC_ADDRESS_FORMAT_STR"%s",
|
||||
SD_NDISC_ADDRESS_FORMAT_VAL(addresses[i]),
|
||||
(i < (size - 1)) ? " ": "");
|
||||
for (i = 0; i < size; i++) {
|
||||
char buffer[INET6_ADDRSTRLEN];
|
||||
|
||||
fputs(inet_ntop(AF_INET6, addresses+i, buffer, sizeof(buffer)), f);
|
||||
|
||||
if (i < size - 1)
|
||||
fputc(' ', f);
|
||||
}
|
||||
}
|
||||
|
||||
int deserialize_in6_addrs(struct in6_addr **ret, const char *string) {
|
||||
|
@@ -43,7 +43,6 @@ static void lldp_flush_neighbors(sd_lldp *lldp) {
|
||||
|
||||
static void lldp_callback(sd_lldp *lldp, sd_lldp_event event, sd_lldp_neighbor *n) {
|
||||
assert(lldp);
|
||||
assert(n);
|
||||
|
||||
log_lldp("Invoking callback for '%c'.", event);
|
||||
|
||||
@@ -138,6 +137,7 @@ static int lldp_add_neighbor(sd_lldp *lldp, sd_lldp_neighbor *n) {
|
||||
|
||||
if (lldp_neighbor_equal(n, old)) {
|
||||
/* Is this equal, then restart the TTL counter, but don't do anyting else. */
|
||||
old->timestamp = n->timestamp;
|
||||
lldp_start_timer(lldp, old);
|
||||
lldp_callback(lldp, SD_LLDP_EVENT_REFRESHED, old);
|
||||
return 0;
|
||||
@@ -171,7 +171,7 @@ static int lldp_add_neighbor(sd_lldp *lldp, sd_lldp_neighbor *n) {
|
||||
|
||||
finish:
|
||||
if (old)
|
||||
lldp_callback(lldp, SD_LLDP_EVENT_REMOVED, n);
|
||||
lldp_callback(lldp, SD_LLDP_EVENT_REMOVED, old);
|
||||
|
||||
return r;
|
||||
}
|
||||
@@ -202,6 +202,7 @@ static int lldp_receive_datagram(sd_event_source *s, int fd, uint32_t revents, v
|
||||
_cleanup_(sd_lldp_neighbor_unrefp) sd_lldp_neighbor *n = NULL;
|
||||
ssize_t space, length;
|
||||
sd_lldp *lldp = userdata;
|
||||
struct timespec ts;
|
||||
|
||||
assert(fd >= 0);
|
||||
assert(lldp);
|
||||
@@ -215,21 +216,41 @@ static int lldp_receive_datagram(sd_event_source *s, int fd, uint32_t revents, v
|
||||
return -ENOMEM;
|
||||
|
||||
length = recv(fd, LLDP_NEIGHBOR_RAW(n), n->raw_size, MSG_DONTWAIT);
|
||||
if (length < 0)
|
||||
if (length < 0) {
|
||||
if (errno == EAGAIN || errno == EINTR)
|
||||
return 0;
|
||||
|
||||
return log_lldp_errno(errno, "Failed to read LLDP datagram: %m");
|
||||
}
|
||||
|
||||
if ((size_t) length != n->raw_size) {
|
||||
log_lldp("Packet size mismatch.");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* Try to get the timestamp of this packet if it is known */
|
||||
if (ioctl(fd, SIOCGSTAMPNS, &ts) >= 0)
|
||||
triple_timestamp_from_realtime(&n->timestamp, timespec_load(&ts));
|
||||
else
|
||||
triple_timestamp_get(&n->timestamp);
|
||||
|
||||
return lldp_handle_datagram(lldp, n);
|
||||
}
|
||||
|
||||
static void lldp_reset(sd_lldp *lldp) {
|
||||
assert(lldp);
|
||||
|
||||
lldp->timer_event_source = sd_event_source_unref(lldp->timer_event_source);
|
||||
lldp->io_event_source = sd_event_source_unref(lldp->io_event_source);
|
||||
lldp->fd = safe_close(lldp->fd);
|
||||
}
|
||||
|
||||
_public_ int sd_lldp_start(sd_lldp *lldp) {
|
||||
int r;
|
||||
|
||||
assert_return(lldp, -EINVAL);
|
||||
assert_return(lldp->event, -EINVAL);
|
||||
assert_return(lldp->ifindex > 0, -EINVAL);
|
||||
|
||||
if (lldp->fd >= 0)
|
||||
return 0;
|
||||
@@ -240,24 +261,21 @@ _public_ int sd_lldp_start(sd_lldp *lldp) {
|
||||
if (lldp->fd < 0)
|
||||
return lldp->fd;
|
||||
|
||||
if (lldp->event) {
|
||||
r = sd_event_add_io(lldp->event, &lldp->io_event_source, lldp->fd, EPOLLIN, lldp_receive_datagram, lldp);
|
||||
if (r < 0)
|
||||
goto fail;
|
||||
r = sd_event_add_io(lldp->event, &lldp->io_event_source, lldp->fd, EPOLLIN, lldp_receive_datagram, lldp);
|
||||
if (r < 0)
|
||||
goto fail;
|
||||
|
||||
r = sd_event_source_set_priority(lldp->io_event_source, lldp->event_priority);
|
||||
if (r < 0)
|
||||
goto fail;
|
||||
r = sd_event_source_set_priority(lldp->io_event_source, lldp->event_priority);
|
||||
if (r < 0)
|
||||
goto fail;
|
||||
|
||||
(void) sd_event_source_set_description(lldp->io_event_source, "lldp-io");
|
||||
}
|
||||
(void) sd_event_source_set_description(lldp->io_event_source, "lldp-io");
|
||||
|
||||
log_lldp("Started LLDP client");
|
||||
return 1;
|
||||
|
||||
fail:
|
||||
lldp->io_event_source = sd_event_source_unref(lldp->io_event_source);
|
||||
lldp->fd = safe_close(lldp->fd);
|
||||
|
||||
lldp_reset(lldp);
|
||||
return r;
|
||||
}
|
||||
|
||||
@@ -267,10 +285,9 @@ _public_ int sd_lldp_stop(sd_lldp *lldp) {
|
||||
if (lldp->fd < 0)
|
||||
return 0;
|
||||
|
||||
lldp->timer_event_source = sd_event_source_unref(lldp->timer_event_source);
|
||||
lldp->io_event_source = sd_event_source_unref(lldp->io_event_source);
|
||||
lldp->fd = safe_close(lldp->fd);
|
||||
log_lldp("Stopping LLDP client");
|
||||
|
||||
lldp_reset(lldp);
|
||||
lldp_flush_neighbors(lldp);
|
||||
|
||||
return 1;
|
||||
@@ -305,6 +322,12 @@ _public_ int sd_lldp_detach_event(sd_lldp *lldp) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
_public_ sd_event* sd_lldp_get_event(sd_lldp *lldp) {
|
||||
assert_return(lldp, NULL);
|
||||
|
||||
return lldp->event;
|
||||
}
|
||||
|
||||
_public_ int sd_lldp_set_callback(sd_lldp *lldp, sd_lldp_callback_t cb, void *userdata) {
|
||||
assert_return(lldp, -EINVAL);
|
||||
|
||||
@@ -314,39 +337,60 @@ _public_ int sd_lldp_set_callback(sd_lldp *lldp, sd_lldp_callback_t cb, void *us
|
||||
return 0;
|
||||
}
|
||||
|
||||
_public_ int sd_lldp_set_ifindex(sd_lldp *lldp, int ifindex) {
|
||||
assert_return(lldp, -EINVAL);
|
||||
assert_return(ifindex > 0, -EINVAL);
|
||||
assert_return(lldp->fd < 0, -EBUSY);
|
||||
|
||||
lldp->ifindex = ifindex;
|
||||
return 0;
|
||||
}
|
||||
|
||||
_public_ sd_lldp* sd_lldp_ref(sd_lldp *lldp) {
|
||||
|
||||
if (!lldp)
|
||||
return NULL;
|
||||
|
||||
assert(lldp->n_ref > 0);
|
||||
lldp->n_ref++;
|
||||
|
||||
return lldp;
|
||||
}
|
||||
|
||||
_public_ sd_lldp* sd_lldp_unref(sd_lldp *lldp) {
|
||||
|
||||
if (!lldp)
|
||||
return NULL;
|
||||
|
||||
assert(lldp->n_ref > 0);
|
||||
lldp->n_ref --;
|
||||
|
||||
if (lldp->n_ref > 0)
|
||||
return NULL;
|
||||
|
||||
lldp_reset(lldp);
|
||||
sd_lldp_detach_event(lldp);
|
||||
lldp_flush_neighbors(lldp);
|
||||
|
||||
hashmap_free(lldp->neighbor_by_id);
|
||||
prioq_free(lldp->neighbor_by_expiry);
|
||||
|
||||
sd_event_source_unref(lldp->io_event_source);
|
||||
sd_event_source_unref(lldp->timer_event_source);
|
||||
sd_event_unref(lldp->event);
|
||||
safe_close(lldp->fd);
|
||||
|
||||
free(lldp);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
_public_ int sd_lldp_new(sd_lldp **ret, int ifindex) {
|
||||
_public_ int sd_lldp_new(sd_lldp **ret) {
|
||||
_cleanup_(sd_lldp_unrefp) sd_lldp *lldp = NULL;
|
||||
int r;
|
||||
|
||||
assert_return(ret, -EINVAL);
|
||||
assert_return(ifindex > 0, -EINVAL);
|
||||
|
||||
lldp = new0(sd_lldp, 1);
|
||||
if (!lldp)
|
||||
return -ENOMEM;
|
||||
|
||||
lldp->n_ref = 1;
|
||||
lldp->fd = -1;
|
||||
lldp->ifindex = ifindex;
|
||||
lldp->neighbors_max = LLDP_DEFAULT_NEIGHBORS_MAX;
|
||||
lldp->capability_mask = (uint16_t) -1;
|
||||
|
||||
@@ -486,11 +530,10 @@ _public_ int sd_lldp_set_filter_address(sd_lldp *lldp, const struct ether_addr *
|
||||
/* In order to deal nicely with bridges that send back our own packets, allow one address to be filtered, so
|
||||
* that our own can be filtered out here. */
|
||||
|
||||
if (!addr) {
|
||||
if (addr)
|
||||
lldp->filter_address = *addr;
|
||||
else
|
||||
zero(lldp->filter_address);
|
||||
return 0;
|
||||
}
|
||||
|
||||
lldp->filter_address = *addr;
|
||||
return 0;
|
||||
}
|
||||
|
@@ -216,8 +216,7 @@ struct sd_event {
|
||||
pid_t original_pid;
|
||||
|
||||
unsigned iteration;
|
||||
dual_timestamp timestamp;
|
||||
usec_t timestamp_boottime;
|
||||
triple_timestamp timestamp;
|
||||
int state;
|
||||
|
||||
bool exit_requested:1;
|
||||
@@ -1072,16 +1071,16 @@ _public_ int sd_event_add_time(
|
||||
assert_return(e->state != SD_EVENT_FINISHED, -ESTALE);
|
||||
assert_return(!event_pid_changed(e), -ECHILD);
|
||||
|
||||
if (IN_SET(clock, CLOCK_BOOTTIME, CLOCK_BOOTTIME_ALARM) &&
|
||||
!clock_boottime_supported())
|
||||
if (!clock_supported(clock)) /* Checks whether the kernel supports the clock */
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
type = clock_to_event_source_type(clock); /* checks whether sd-event supports this clock */
|
||||
if (type < 0)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
if (!callback)
|
||||
callback = time_exit_callback;
|
||||
|
||||
type = clock_to_event_source_type(clock);
|
||||
assert_return(type >= 0, -EOPNOTSUPP);
|
||||
|
||||
d = event_get_clock_data(e, type);
|
||||
assert(d);
|
||||
|
||||
@@ -2530,9 +2529,7 @@ _public_ int sd_event_wait(sd_event *e, uint64_t timeout) {
|
||||
goto finish;
|
||||
}
|
||||
|
||||
dual_timestamp_get(&e->timestamp);
|
||||
if (clock_boottime_supported())
|
||||
e->timestamp_boottime = now(CLOCK_BOOTTIME);
|
||||
triple_timestamp_get(&e->timestamp);
|
||||
|
||||
for (i = 0; i < m; i++) {
|
||||
|
||||
@@ -2573,7 +2570,7 @@ _public_ int sd_event_wait(sd_event *e, uint64_t timeout) {
|
||||
if (r < 0)
|
||||
goto finish;
|
||||
|
||||
r = process_timer(e, e->timestamp_boottime, &e->boottime);
|
||||
r = process_timer(e, e->timestamp.boottime, &e->boottime);
|
||||
if (r < 0)
|
||||
goto finish;
|
||||
|
||||
@@ -2585,7 +2582,7 @@ _public_ int sd_event_wait(sd_event *e, uint64_t timeout) {
|
||||
if (r < 0)
|
||||
goto finish;
|
||||
|
||||
r = process_timer(e, e->timestamp_boottime, &e->boottime_alarm);
|
||||
r = process_timer(e, e->timestamp.boottime, &e->boottime_alarm);
|
||||
if (r < 0)
|
||||
goto finish;
|
||||
|
||||
@@ -2759,43 +2756,24 @@ _public_ int sd_event_now(sd_event *e, clockid_t clock, uint64_t *usec) {
|
||||
assert_return(e, -EINVAL);
|
||||
assert_return(usec, -EINVAL);
|
||||
assert_return(!event_pid_changed(e), -ECHILD);
|
||||
assert_return(IN_SET(clock,
|
||||
CLOCK_REALTIME,
|
||||
CLOCK_REALTIME_ALARM,
|
||||
CLOCK_MONOTONIC,
|
||||
CLOCK_BOOTTIME,
|
||||
CLOCK_BOOTTIME_ALARM), -EOPNOTSUPP);
|
||||
|
||||
if (!TRIPLE_TIMESTAMP_HAS_CLOCK(clock))
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
/* Generate a clean error in case CLOCK_BOOTTIME is not available. Note that don't use clock_supported() here,
|
||||
* for a reason: there are systems where CLOCK_BOOTTIME is supported, but CLOCK_BOOTTIME_ALARM is not, but for
|
||||
* the purpose of getting the time this doesn't matter. */
|
||||
if (IN_SET(clock, CLOCK_BOOTTIME, CLOCK_BOOTTIME_ALARM) && !clock_boottime_supported())
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
if (!dual_timestamp_is_set(&e->timestamp)) {
|
||||
if (!triple_timestamp_is_set(&e->timestamp)) {
|
||||
/* Implicitly fall back to now() if we never ran
|
||||
* before and thus have no cached time. */
|
||||
*usec = now(clock);
|
||||
return 1;
|
||||
}
|
||||
|
||||
switch (clock) {
|
||||
|
||||
case CLOCK_REALTIME:
|
||||
case CLOCK_REALTIME_ALARM:
|
||||
*usec = e->timestamp.realtime;
|
||||
break;
|
||||
|
||||
case CLOCK_MONOTONIC:
|
||||
*usec = e->timestamp.monotonic;
|
||||
break;
|
||||
|
||||
case CLOCK_BOOTTIME:
|
||||
case CLOCK_BOOTTIME_ALARM:
|
||||
*usec = e->timestamp_boottime;
|
||||
break;
|
||||
|
||||
default:
|
||||
assert_not_reached("Unknown clock?");
|
||||
}
|
||||
|
||||
*usec = triple_timestamp_by_clock(&e->timestamp, clock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@@ -23,6 +23,7 @@
|
||||
|
||||
#include <inttypes.h>
|
||||
#include <net/ethernet.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#include "sd-event.h"
|
||||
|
||||
@@ -30,9 +31,6 @@
|
||||
|
||||
_SD_BEGIN_DECLARATIONS;
|
||||
|
||||
typedef struct sd_lldp sd_lldp;
|
||||
typedef struct sd_lldp_neighbor sd_lldp_neighbor;
|
||||
|
||||
/* IEEE 802.3AB Clause 9: TLV Types */
|
||||
enum {
|
||||
SD_LLDP_TYPE_END = 0,
|
||||
@@ -111,6 +109,9 @@ enum {
|
||||
SD_LLDP_OUI_802_1_SUBTYPE_LINK_AGGREGATION = 7,
|
||||
};
|
||||
|
||||
typedef struct sd_lldp sd_lldp;
|
||||
typedef struct sd_lldp_neighbor sd_lldp_neighbor;
|
||||
|
||||
typedef enum sd_lldp_event {
|
||||
SD_LLDP_EVENT_ADDED = 'a',
|
||||
SD_LLDP_EVENT_REMOVED = 'r',
|
||||
@@ -120,7 +121,8 @@ typedef enum sd_lldp_event {
|
||||
|
||||
typedef void (*sd_lldp_callback_t)(sd_lldp *lldp, sd_lldp_event event, sd_lldp_neighbor *n, void *userdata);
|
||||
|
||||
int sd_lldp_new(sd_lldp **ret, int ifindex);
|
||||
int sd_lldp_new(sd_lldp **ret);
|
||||
sd_lldp* sd_lldp_ref(sd_lldp *lldp);
|
||||
sd_lldp* sd_lldp_unref(sd_lldp *lldp);
|
||||
|
||||
int sd_lldp_start(sd_lldp *lldp);
|
||||
@@ -128,8 +130,10 @@ int sd_lldp_stop(sd_lldp *lldp);
|
||||
|
||||
int sd_lldp_attach_event(sd_lldp *lldp, sd_event *event, int64_t priority);
|
||||
int sd_lldp_detach_event(sd_lldp *lldp);
|
||||
sd_event *sd_lldp_get_event(sd_lldp *lldp);
|
||||
|
||||
int sd_lldp_set_callback(sd_lldp *lldp, sd_lldp_callback_t cb, void *userdata);
|
||||
int sd_lldp_set_ifindex(sd_lldp *lldp, int ifindex);
|
||||
|
||||
/* Controls how much and what to store in the neighbors database */
|
||||
int sd_lldp_set_neighbors_max(sd_lldp *lldp, uint64_t n);
|
||||
@@ -145,6 +149,7 @@ sd_lldp_neighbor *sd_lldp_neighbor_unref(sd_lldp_neighbor *n);
|
||||
/* Access to LLDP frame metadata */
|
||||
int sd_lldp_neighbor_get_source_address(sd_lldp_neighbor *n, struct ether_addr* address);
|
||||
int sd_lldp_neighbor_get_destination_address(sd_lldp_neighbor *n, struct ether_addr* address);
|
||||
int sd_lldp_neighbor_get_timestamp(sd_lldp_neighbor *n, clockid_t clock, uint64_t *ret);
|
||||
int sd_lldp_neighbor_get_raw(sd_lldp_neighbor *n, const void **ret, size_t *size);
|
||||
|
||||
/* High-level, direct, parsed out field access. These fields exist at most once, hence may be queried directly. */
|
||||
@@ -152,7 +157,7 @@ int sd_lldp_neighbor_get_chassis_id(sd_lldp_neighbor *n, uint8_t *type, const vo
|
||||
int sd_lldp_neighbor_get_chassis_id_as_string(sd_lldp_neighbor *n, const char **ret);
|
||||
int sd_lldp_neighbor_get_port_id(sd_lldp_neighbor *n, uint8_t *type, const void **ret, size_t *size);
|
||||
int sd_lldp_neighbor_get_port_id_as_string(sd_lldp_neighbor *n, const char **ret);
|
||||
int sd_lldp_neighbor_get_ttl(sd_lldp_neighbor *n, uint16_t *ret);
|
||||
int sd_lldp_neighbor_get_ttl(sd_lldp_neighbor *n, uint16_t *ret_sec);
|
||||
int sd_lldp_neighbor_get_system_name(sd_lldp_neighbor *n, const char **ret);
|
||||
int sd_lldp_neighbor_get_system_description(sd_lldp_neighbor *n, const char **ret);
|
||||
int sd_lldp_neighbor_get_port_description(sd_lldp_neighbor *n, const char **ret);
|
||||
|
@@ -22,6 +22,8 @@
|
||||
|
||||
#include <inttypes.h>
|
||||
#include <net/ethernet.h>
|
||||
#include <netinet/in.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#include "sd-event.h"
|
||||
|
||||
@@ -29,55 +31,99 @@
|
||||
|
||||
_SD_BEGIN_DECLARATIONS;
|
||||
|
||||
/* Neightbor Discovery Options, RFC 4861, Section 4.6 and
|
||||
* https://www.iana.org/assignments/icmpv6-parameters/icmpv6-parameters.xhtml#icmpv6-parameters-5 */
|
||||
enum {
|
||||
SD_NDISC_EVENT_STOP = 0,
|
||||
SD_NDISC_EVENT_TIMEOUT = 1,
|
||||
SD_NDISC_OPTION_SOURCE_LL_ADDRESS = 1,
|
||||
SD_NDISC_OPTION_TARGET_LL_ADDRESS = 2,
|
||||
SD_NDISC_OPTION_PREFIX_INFORMATION = 3,
|
||||
SD_NDISC_OPTION_MTU = 5,
|
||||
SD_NDISC_OPTION_ROUTE_INFORMATION = 24,
|
||||
SD_NDISC_OPTION_RDNSS = 25,
|
||||
SD_NDISC_OPTION_FLAGS_EXTENSION = 26,
|
||||
SD_NDISC_OPTION_DNSSL = 31,
|
||||
SD_NDISC_OPTION_CAPTIVE_PORTAL = 37,
|
||||
};
|
||||
|
||||
/* Route preference, RFC 4191, Section 2.1 */
|
||||
enum {
|
||||
SD_NDISC_PREFERENCE_LOW = 3U,
|
||||
SD_NDISC_PREFERENCE_MEDIUM = 0U,
|
||||
SD_NDISC_PREFERENCE_HIGH = 1U,
|
||||
};
|
||||
|
||||
typedef struct sd_ndisc sd_ndisc;
|
||||
typedef struct sd_ndisc_router sd_ndisc_router;
|
||||
|
||||
typedef void(*sd_ndisc_router_callback_t)(sd_ndisc *nd, uint8_t flags, const struct in6_addr *gateway, unsigned lifetime, int pref, void *userdata);
|
||||
typedef void(*sd_ndisc_prefix_onlink_callback_t)(sd_ndisc *nd, const struct in6_addr *prefix, unsigned prefixlen,
|
||||
unsigned lifetime, void *userdata);
|
||||
typedef void(*sd_ndisc_prefix_autonomous_callback_t)(sd_ndisc *nd, const struct in6_addr *prefix, unsigned prefixlen,
|
||||
unsigned lifetime_prefered, unsigned lifetime_valid, void *userdata);
|
||||
typedef void(*sd_ndisc_callback_t)(sd_ndisc *nd, int event, void *userdata);
|
||||
typedef enum sd_ndisc_event {
|
||||
SD_NDISC_EVENT_TIMEOUT = 't',
|
||||
SD_NDISC_EVENT_ROUTER = 'r',
|
||||
} sd_ndisc_event;
|
||||
|
||||
int sd_ndisc_set_callback(sd_ndisc *nd,
|
||||
sd_ndisc_router_callback_t rcb,
|
||||
sd_ndisc_prefix_onlink_callback_t plcb,
|
||||
sd_ndisc_prefix_autonomous_callback_t pacb,
|
||||
sd_ndisc_callback_t cb,
|
||||
void *userdata);
|
||||
int sd_ndisc_set_ifindex(sd_ndisc *nd, int interface_index);
|
||||
int sd_ndisc_set_mac(sd_ndisc *nd, const struct ether_addr *mac_addr);
|
||||
typedef void (*sd_ndisc_callback_t)(sd_ndisc *nd, sd_ndisc_event event, sd_ndisc_router *rt, void *userdata);
|
||||
|
||||
int sd_ndisc_new(sd_ndisc **ret);
|
||||
sd_ndisc *sd_ndisc_ref(sd_ndisc *nd);
|
||||
sd_ndisc *sd_ndisc_unref(sd_ndisc *nd);
|
||||
|
||||
int sd_ndisc_start(sd_ndisc *nd);
|
||||
int sd_ndisc_stop(sd_ndisc *nd);
|
||||
|
||||
int sd_ndisc_attach_event(sd_ndisc *nd, sd_event *event, int64_t priority);
|
||||
int sd_ndisc_detach_event(sd_ndisc *nd);
|
||||
sd_event *sd_ndisc_get_event(sd_ndisc *nd);
|
||||
|
||||
sd_ndisc *sd_ndisc_ref(sd_ndisc *nd);
|
||||
sd_ndisc *sd_ndisc_unref(sd_ndisc *nd);
|
||||
int sd_ndisc_new(sd_ndisc **ret);
|
||||
int sd_ndisc_set_callback(sd_ndisc *nd, sd_ndisc_callback_t cb, void *userdata);
|
||||
int sd_ndisc_set_ifindex(sd_ndisc *nd, int interface_index);
|
||||
int sd_ndisc_set_mac(sd_ndisc *nd, const struct ether_addr *mac_addr);
|
||||
|
||||
int sd_ndisc_get_mtu(sd_ndisc *nd, uint32_t *mtu);
|
||||
int sd_ndisc_get_mtu(sd_ndisc *nd, uint32_t *ret);
|
||||
int sd_ndisc_get_hop_limit(sd_ndisc *nd, uint8_t *ret);
|
||||
|
||||
int sd_ndisc_stop(sd_ndisc *nd);
|
||||
int sd_ndisc_router_discovery_start(sd_ndisc *nd);
|
||||
int sd_ndisc_router_from_raw(sd_ndisc_router **ret, const void *raw, size_t raw_size);
|
||||
sd_ndisc_router *sd_ndisc_router_ref(sd_ndisc_router *rt);
|
||||
sd_ndisc_router *sd_ndisc_router_unref(sd_ndisc_router *rt);
|
||||
|
||||
#define SD_NDISC_ADDRESS_FORMAT_STR "%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x"
|
||||
int sd_ndisc_router_get_address(sd_ndisc_router *rt, struct in6_addr *ret_addr);
|
||||
int sd_ndisc_router_get_timestamp(sd_ndisc_router *rt, clockid_t clock, uint64_t *ret);
|
||||
int sd_ndisc_router_get_raw(sd_ndisc_router *rt, const void **ret, size_t *size);
|
||||
|
||||
#define SD_NDISC_ADDRESS_FORMAT_VAL(address) \
|
||||
be16toh((address).s6_addr16[0]), \
|
||||
be16toh((address).s6_addr16[1]), \
|
||||
be16toh((address).s6_addr16[2]), \
|
||||
be16toh((address).s6_addr16[3]), \
|
||||
be16toh((address).s6_addr16[4]), \
|
||||
be16toh((address).s6_addr16[5]), \
|
||||
be16toh((address).s6_addr16[6]), \
|
||||
be16toh((address).s6_addr16[7])
|
||||
int sd_ndisc_router_get_hop_limit(sd_ndisc_router *rt, uint8_t *ret);
|
||||
int sd_ndisc_router_get_flags(sd_ndisc_router *rt, uint64_t *ret_flags);
|
||||
int sd_ndisc_router_get_preference(sd_ndisc_router *rt, unsigned *ret);
|
||||
int sd_ndisc_router_get_lifetime(sd_ndisc_router *rt, uint16_t *ret_lifetime);
|
||||
int sd_ndisc_router_get_mtu(sd_ndisc_router *rt, uint32_t *ret);
|
||||
|
||||
/* Generic option access */
|
||||
int sd_ndisc_router_option_rewind(sd_ndisc_router *rt);
|
||||
int sd_ndisc_router_option_next(sd_ndisc_router *rt);
|
||||
int sd_ndisc_router_option_get_type(sd_ndisc_router *rt, uint8_t *ret);
|
||||
int sd_ndisc_router_option_is_type(sd_ndisc_router *rt, uint8_t type);
|
||||
int sd_ndisc_router_option_get_raw(sd_ndisc_router *rt, const void **ret, size_t *size);
|
||||
|
||||
/* Specific option access: SD_NDISC_OPTION_PREFIX_INFORMATION */
|
||||
int sd_ndisc_router_prefix_get_valid_lifetime(sd_ndisc_router *rt, uint32_t *ret);
|
||||
int sd_ndisc_router_prefix_get_preferred_lifetime(sd_ndisc_router *rt, uint32_t *ret);
|
||||
int sd_ndisc_router_prefix_get_flags(sd_ndisc_router *rt, uint8_t *ret);
|
||||
int sd_ndisc_router_prefix_get_address(sd_ndisc_router *rt, struct in6_addr *ret_addr);
|
||||
int sd_ndisc_router_prefix_get_prefixlen(sd_ndisc_router *rt, unsigned *prefixlen);
|
||||
|
||||
/* Specific option access: SD_NDISC_OPTION_ROUTE_INFORMATION */
|
||||
int sd_ndisc_router_route_get_lifetime(sd_ndisc_router *rt, uint32_t *ret);
|
||||
int sd_ndisc_router_route_get_address(sd_ndisc_router *rt, struct in6_addr *ret_addr);
|
||||
int sd_ndisc_router_route_get_prefixlen(sd_ndisc_router *rt, unsigned *prefixlen);
|
||||
int sd_ndisc_router_route_get_preference(sd_ndisc_router *rt, unsigned *ret);
|
||||
|
||||
/* Specific option access: SD_NDISC_OPTION_RDNSS */
|
||||
int sd_ndisc_router_rdnss_get_addresses(sd_ndisc_router *rt, const struct in6_addr **ret);
|
||||
int sd_ndisc_router_rdnss_get_lifetime(sd_ndisc_router *rt, uint32_t *ret);
|
||||
|
||||
/* Specific option access: SD_NDISC_OPTION_DNSSL */
|
||||
int sd_ndisc_router_dnssl_get_domains(sd_ndisc_router *rt, char ***ret);
|
||||
int sd_ndisc_router_dnssl_get_lifetime(sd_ndisc_router *rt, uint32_t *ret);
|
||||
|
||||
_SD_DEFINE_POINTER_CLEANUP_FUNC(sd_ndisc, sd_ndisc_unref);
|
||||
_SD_DEFINE_POINTER_CLEANUP_FUNC(sd_ndisc_router, sd_ndisc_router_unref);
|
||||
|
||||
_SD_END_DECLARATIONS;
|
||||
|
||||
|
Reference in New Issue
Block a user