Compare commits

...

32 Commits

Author SHA1 Message Date
Zbigniew Jędrzejewski-Szmek ad161cd6bb
Merge pull request #16951 from yuwata/resolve-follow-ups-for-extra-dns-stub-listener
resolve: follow-ups for extra DNS stub listener
2020-09-05 15:55:22 +02:00
Zbigniew Jędrzejewski-Szmek 5615e92efa
Merge pull request #16854 from yuwata/sd-bus-error-set-errnofv
sd-bus: rework sd_bus_error_set_errnofv()
2020-09-05 15:47:37 +02:00
Zbigniew Jędrzejewski-Szmek 7de6b05160
Merge pull request #16957 from poettering/sd-bus-proto-def-move
three unrelated, minor fixes
2020-09-05 12:06:15 +02:00
Lennart Poettering 8d91b2206c varlink: properly allocate connection event source
Let's make sure we keep a reference to the event source

(Note that this code is currently not used, which is why this was never
used: in all cases we do not add listener fds after the event is
attached, but before. In that case this code is not called.)
2020-09-04 23:54:14 +02:00
Lennart Poettering 1ba37106b3 ptyfwd: don't set prio if event source that might not exist
We support read-only ptyfwd options, and on those the input event source
won't be allocated. Deal with that and don't invoke a function on it
that will then instantly fail.
2020-09-04 23:52:41 +02:00
Lennart Poettering fb2cfa6c13 sd-bus: move SD_BUS_MAXIMUM_(SIGNATURE|NAME)_LENGTH to sd-bus-protocol.h
So far we kept all defines directly originating from the spec in
sd-bus-protocol.h, do this for this too.

The precise place doesn't matter much API-wise given that sd-bus.h includes
sd-bus-protocol.h, hence let's just clean this up.
2020-09-04 23:51:21 +02:00
Yu Watanabe 89f7435d0c resolve: use correct fd for UDP stub listner 2020-09-04 23:54:35 +09:00
Yu Watanabe d1fb8cdae2 resolve: do not check sender and destination for packet received by extra DNS stub listner 2020-09-04 23:54:35 +09:00
Yu Watanabe 7216a3b5dc resolve: use sd_event_source_set_io_fd_own() for stub listners 2020-09-04 23:54:35 +09:00
Yu Watanabe bf22f231cf resolve: introduce dns_stub_listener_extra_free() and set it as a key destructor 2020-09-04 23:54:35 +09:00
Yu Watanabe 1c17bcb3ad resolve: adjust error messages 2020-09-04 23:54:35 +09:00
Yu Watanabe af8b138422 resolve: do not set IPv4 specific options on IPv6 socket 2020-09-04 23:54:30 +09:00
Yu Watanabe d40f00d798 resolve: do not set IP_TTL for extra DNS stub listeners 2020-09-04 23:53:22 +09:00
Yu Watanabe 180c22328b missing: add IPV6_FREEBIND 2020-09-04 23:53:18 +09:00
Yu Watanabe fc7676e313 util: drop unused socket_addr_port_from_string_auto() 2020-09-04 20:05:58 +09:00
Yu Watanabe ca8b62b522 resolve: use in_addr_union to store addresses for extra dns stub listeners 2020-09-04 20:05:58 +09:00
Yu Watanabe b4b7ea1b32 resolve: fix indentation 2020-09-04 20:05:58 +09:00
Yu Watanabe 4e0a46f65e util: introduce SOCKADDR_LEN() macro 2020-09-04 20:05:58 +09:00
Yu Watanabe fc6021554b test: add tests for in_addr_port_from_string_auto() 2020-09-04 20:05:58 +09:00
Yu Watanabe 23c5aeaac3 test: move several tests from test-socket-util.c 2020-09-04 20:05:58 +09:00
Yu Watanabe c4fe658366 util: introduce in_addr_port_to_string() 2020-09-04 20:05:58 +09:00
Yu Watanabe c364cefb3a util: make in_addr_ifindex_to_string() an alias of in_addr_port_ifindex_name_to_string() 2020-09-04 20:05:58 +09:00
Yu Watanabe 355e884ded util: introduce in_addr_port_from_string_auto() 2020-09-04 20:05:58 +09:00
Yu Watanabe 4650582657 resolve: stop extra stub listners before freeing information about them 2020-09-04 20:05:58 +09:00
Yu Watanabe 7314b39746 resolve: set DNS_STUB_LISTENER_YES if no protocol is specified in DNSStubListenExtra= 2020-09-04 20:05:58 +09:00
Yu Watanabe dce65cd40f resolve: Manager::dns_stub_listener_mode is not relevant to extra stub listeners 2020-09-04 20:05:58 +09:00
Yu Watanabe 88d2cb7c0e resolve: make DnsStubListenerMode bitfield 2020-09-04 20:05:58 +09:00
Yu Watanabe 8ae07803a0 resolve: rename dns_stub_extra_event_source -> event_source
As the name is too redundant.
2020-09-04 20:05:58 +09:00
Yu Watanabe 6421194b31 man: update DNSStubListenerExtra= 2020-09-04 20:05:54 +09:00
Yu Watanabe aea4660af8 test: add tests for sd_bus_error_set_errnof() 2020-09-04 19:15:50 +09:00
Yu Watanabe caf4ba83d5 sd-bus: use _cleanup_free_ macro in sd_bus_error_set_errnofv()
No functional change.
2020-09-04 19:15:45 +09:00
Amitanand.Chikorde c9f0e1ce5f sd-bus: drop unnecessary free()
As `e->message` here is always NULL.
2020-09-04 12:23:29 +09:00
23 changed files with 695 additions and 629 deletions

View File

@ -271,27 +271,27 @@
<varlistentry>
<term><varname>DNSStubListenerExtra=</varname></term>
<listitem><para>Takes an IPv4 or IPv6 address to listen on. The address may optionally be prefixed by <literal>:</literal> and
a protocol name (<literal>udp</literal> or <literal>tcp</literal>). When an IPv6 address is specified with a port number, then the
address must be in the square brackets. This option can be specified multiple times. If an empty string is assigned, then the all
previous assignments are cleared. It may also be optionally suffixed by a numeric port number with separator <literal>:</literal>.
If the protocol is not specified, the service will listen on both <literal>UDP</literal> and <literal>TCP</literal>. If the port is not
specified, then the service takes port as 53. This option may be used multiple times. Note that this is independent of the
primary DNS stub configured with <varname>DNSStubListener=</varname>, and only configures <emphasis>additional</emphasis>
sockets to listen on. Defaults to unset.</para>
<listitem><para>Takes an IPv4 or IPv6 address to listen on. The address may be optionally
prefixed with a protocol name (<literal>udp</literal> or <literal>tcp</literal>) separated with
<literal>:</literal>. If the protocol is not specified, the service will listen on both UDP and
TCP. It may be also optionally suffixed by a numeric port number with separator
<literal>:</literal>. When an IPv6 address is specified with a port number, then the address
must be in the square brackets. If the port is not specified, then the service uses port 53.
Note that this is independent of the primary DNS stub configured with
<varname>DNSStubListener=</varname>, and only configures <emphasis>additional</emphasis>
sockets to listen on. This option can be specified multiple times. If an empty string is
assigned, then the all previous assignments are cleared. Defaults to unset.</para>
<para>If the string in the format <literal>udp</literal>:[<replaceable>x</replaceable>]:<replaceable>y</replaceable>,
it is read as protocol <literal>udp</literal> and IPv6 address x on a port y.</para>
<para>If the string in the format [<replaceable>x</replaceable>]:<replaceable>y</replaceable>, it is read as both protocol
<literal>udp</literal> and <literal>tcp</literal>, IPv6 address x on a port y.</para>
<para>If the string in the format <replaceable>x</replaceable>, it is read as protocol both <literal>udp</literal> and
<literal>tcp</literal>, IPv6/IPv4 address x on a port 53.</para>
<para>If the string in the format <literal>udp</literal>:<replaceable>x</replaceable>:<replaceable>y</replaceable>,
it is read as protocol <literal>udp</literal> and IPv4 address x on a port y.</para>
</listitem>
<para>Examples:
<programlisting>DNSStubListenerExtra=192.168.10.10
DNSStubListenerExtra=2001:db8:0:f102::10
DNSStubListenerExtra=192.168.10.11:9953
DNSStubListenerExtra=[2001:db8:0:f102::11]:9953
DNSStubListenerExtra=tcp:192.168.10.12
DNSStubListenerExtra=udp:2001:db8:0:f102::12
DNSStubListenerExtra=tcp:192.168.10.13:9953
DNSStubListenerExtra=udp:[2001:db8:0:f102::13]:9953</programlisting>
</para></listitem>
</varlistentry>
<varlistentry>

View File

@ -402,46 +402,6 @@ int in_addr_prefix_to_string(int family, const union in_addr_union *u, unsigned
return 0;
}
int in_addr_ifindex_to_string(int family, const union in_addr_union *u, int ifindex, char **ret) {
_cleanup_free_ char *x = NULL;
size_t l;
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))
return errno_or_else(EINVAL);
sprintf(strchr(x, 0), "%%%i", ifindex);
*ret = TAKE_PTR(x);
return 0;
fallback:
return in_addr_to_string(family, u, ret);
}
int in_addr_port_ifindex_name_to_string(int family, const union in_addr_union *u, uint16_t port, int ifindex, const char *server_name, char **ret) {
_cleanup_free_ char *ip_str = NULL, *x = NULL;
int r;

View File

@ -41,8 +41,13 @@ int in_addr_prefix_nth(int family, union in_addr_union *u, unsigned prefixlen, u
int in_addr_random_prefix(int family, union in_addr_union *u, unsigned prefixlen_fixed_part, unsigned prefixlen);
int in_addr_to_string(int family, const union in_addr_union *u, char **ret);
int in_addr_prefix_to_string(int family, const union in_addr_union *u, unsigned prefixlen, char **ret);
int in_addr_ifindex_to_string(int family, const union in_addr_union *u, int ifindex, char **ret);
int in_addr_port_ifindex_name_to_string(int family, const union in_addr_union *u, uint16_t port, int ifindex, const char *server_name, char **ret);
static inline int in_addr_ifindex_to_string(int family, const union in_addr_union *u, int ifindex, char **ret) {
return in_addr_port_ifindex_name_to_string(family, u, 0, ifindex, NULL, ret);
}
static inline int in_addr_port_to_string(int family, const union in_addr_union *u, uint16_t port, char **ret) {
return in_addr_port_ifindex_name_to_string(family, u, port, 0, NULL, 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 *ret_family, union in_addr_union *ret);

View File

@ -63,6 +63,10 @@ struct sockaddr_vm {
#define IP_TRANSPARENT 19
#endif
#ifndef IPV6_FREEBIND
#define IPV6_FREEBIND 78
#endif
/* linux/sockios.h */
#ifndef SIOCGSKNS
#define SIOCGSKNS 0x894C

View File

@ -205,6 +205,35 @@ struct cmsghdr* cmsg_find(struct msghdr *mh, int level, int type, socklen_t leng
strnlen(_sa->sun_path, sizeof(_sa->sun_path))+1); \
})
#define SOCKADDR_LEN(sa) \
({ \
const union sockaddr_union *__sa = &(sa); \
size_t _len; \
switch(__sa->sa.sa_family) { \
case AF_INET: \
_len = sizeof(struct sockaddr_in); \
break; \
case AF_INET6: \
_len = sizeof(struct sockaddr_in6); \
break; \
case AF_UNIX: \
_len = SOCKADDR_UN_LEN(__sa->un); \
break; \
case AF_PACKET: \
_len = SOCKADDR_LL_LEN(__sa->ll); \
break; \
case AF_NETLINK: \
_len = sizeof(struct sockaddr_nl); \
break; \
case AF_VSOCK: \
_len = sizeof(struct sockaddr_vm); \
break; \
default: \
assert_not_reached("invalid socket family"); \
} \
_len; \
})
int socket_ioctl_fd(void);
int sockaddr_un_set_path(struct sockaddr_un *ret, const char *path);

View File

@ -484,7 +484,6 @@ _public_ int sd_bus_error_set_errno(sd_bus_error *e, int error) {
_public_ int sd_bus_error_set_errnofv(sd_bus_error *e, int error, const char *format, va_list ap) {
PROTECT_ERRNO;
int r;
if (error < 0)
error = -error;
@ -515,34 +514,30 @@ _public_ int sd_bus_error_set_errnofv(sd_bus_error *e, int error, const char *fo
}
if (format) {
char *m;
_cleanup_free_ char *m = NULL;
/* Then, let's try to fill in the supplied message */
errno = error; /* Make sure that %m resolves to the specified error */
r = vasprintf(&m, format, ap);
if (r >= 0) {
if (vasprintf(&m, format, ap) < 0)
goto fail;
if (e->_need_free <= 0) {
char *t;
t = strdup(e->name);
if (t) {
if (!t)
goto fail;
e->_need_free = 1;
e->name = t;
e->message = m;
}
e->message = TAKE_PTR(m);
return -error;
}
free(m);
} else {
free((char*) e->message);
e->message = m;
return -error;
}
}
}
fail:
/* If that didn't work, use strerror() for the message */
bus_error_strerror(e, error);
return -error;

View File

@ -213,12 +213,87 @@ static void test_errno_mapping_custom(void) {
assert_se(sd_bus_error_add_map(test_errors_bad2) == -EINVAL);
}
static void test_sd_bus_error_set_errnof(void) {
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
_cleanup_free_ char *str = NULL;
assert_se(sd_bus_error_set_errnof(NULL, 0, NULL) == 0);
assert_se(sd_bus_error_set_errnof(NULL, ENOANO, NULL) == -ENOANO);
assert_se(sd_bus_error_set_errnof(&error, 0, NULL) == 0);
assert_se(!bus_error_is_dirty(&error));
assert_se(sd_bus_error_set_errnof(&error, EACCES, NULL) == -EACCES);
assert_se(sd_bus_error_has_name(&error, SD_BUS_ERROR_ACCESS_DENIED));
errno = EACCES;
assert_se(asprintf(&str, "%m") >= 0);
assert_se(streq(error.message, str));
assert_se(error._need_free == 0);
str = mfree(str);
sd_bus_error_free(&error);
assert_se(sd_bus_error_set_errnof(&error, ENOANO, NULL) == -ENOANO);
assert_se(sd_bus_error_has_name(&error, "System.Error.ENOANO"));
errno = ENOANO;
assert_se(asprintf(&str, "%m") >= 0);
assert_se(streq(error.message, str));
assert_se(error._need_free == 1);
str = mfree(str);
sd_bus_error_free(&error);
assert_se(sd_bus_error_set_errnof(&error, 100000, NULL) == -100000);
assert_se(sd_bus_error_has_name(&error, SD_BUS_ERROR_FAILED));
errno = 100000;
assert_se(asprintf(&str, "%m") >= 0);
assert_se(streq(error.message, str));
assert_se(error._need_free == 1);
str = mfree(str);
sd_bus_error_free(&error);
assert_se(sd_bus_error_set_errnof(NULL, 0, "hoge %s: %m", "foo") == 0);
assert_se(sd_bus_error_set_errnof(NULL, ENOANO, "hoge %s: %m", "foo") == -ENOANO);
assert_se(sd_bus_error_set_errnof(&error, 0, "hoge %s: %m", "foo") == 0);
assert_se(!bus_error_is_dirty(&error));
assert_se(sd_bus_error_set_errnof(&error, EACCES, "hoge %s: %m", "foo") == -EACCES);
assert_se(sd_bus_error_has_name(&error, SD_BUS_ERROR_ACCESS_DENIED));
errno = EACCES;
assert_se(asprintf(&str, "hoge %s: %m", "foo") >= 0);
assert_se(streq(error.message, str));
assert_se(error._need_free == 1);
str = mfree(str);
sd_bus_error_free(&error);
assert_se(sd_bus_error_set_errnof(&error, ENOANO, "hoge %s: %m", "foo") == -ENOANO);
assert_se(sd_bus_error_has_name(&error, "System.Error.ENOANO"));
errno = ENOANO;
assert_se(asprintf(&str, "hoge %s: %m", "foo") >= 0);
assert_se(streq(error.message, str));
assert_se(error._need_free == 1);
str = mfree(str);
sd_bus_error_free(&error);
assert_se(sd_bus_error_set_errnof(&error, 100000, "hoge %s: %m", "foo") == -100000);
assert_se(sd_bus_error_has_name(&error, SD_BUS_ERROR_FAILED));
errno = 100000;
assert_se(asprintf(&str, "hoge %s: %m", "foo") >= 0);
assert_se(streq(error.message, str));
assert_se(error._need_free == 1);
}
int main(int argc, char *argv[]) {
dump_mapping_table();
test_error();
test_errno_mapping_standard();
test_errno_mapping_custom();
test_sd_bus_error_set_errnof();
return 0;
}

View File

@ -30,20 +30,15 @@ static const char* const dns_stub_listener_mode_table[_DNS_STUB_LISTENER_MODE_MA
DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(dns_stub_listener_mode, DnsStubListenerMode, DNS_STUB_LISTENER_YES);
static void dns_stub_listener_extra_hash_func(const DNSStubListenerExtra *a, struct siphash *state) {
unsigned port;
assert(a);
siphash24_compress(&a->mode, sizeof(a->mode), state);
siphash24_compress(&socket_address_family(&a->address), sizeof(a->address.type), state);
siphash24_compress(&a->address, FAMILY_ADDRESS_SIZE(socket_address_family(&a->address)), state);
(void) sockaddr_port(&a->address.sockaddr.sa, &port);
siphash24_compress(&port, sizeof(port), state);
siphash24_compress(&a->family, sizeof(a->family), state);
siphash24_compress(&a->address, FAMILY_ADDRESS_SIZE(a->family), state);
siphash24_compress(&a->port, sizeof(a->port), state);
}
static int dns_stub_listener_extra_compare_func(const DNSStubListenerExtra *a, const DNSStubListenerExtra *b) {
unsigned p, q;
int r;
assert(a);
@ -53,18 +48,15 @@ static int dns_stub_listener_extra_compare_func(const DNSStubListenerExtra *a, c
if (r != 0)
return r;
r = CMP(socket_address_family(&a->address), socket_address_family(&b->address));
r = CMP(a->family, b->family);
if (r != 0)
return r;
r = memcmp(&a->address, &b->address, FAMILY_ADDRESS_SIZE(socket_address_family(&a->address)));
r = memcmp(&a->address, &b->address, FAMILY_ADDRESS_SIZE(a->family));
if (r != 0)
return r;
(void) sockaddr_port(&a->address.sockaddr.sa, &p);
(void) sockaddr_port(&b->address.sockaddr.sa, &q);
return CMP(p, q);
return CMP(a->port, b->port);
}
DEFINE_PRIVATE_HASH_OPS_WITH_KEY_DESTRUCTOR(
@ -72,7 +64,7 @@ DEFINE_PRIVATE_HASH_OPS_WITH_KEY_DESTRUCTOR(
DNSStubListenerExtra,
dns_stub_listener_extra_hash_func,
dns_stub_listener_extra_compare_func,
free);
dns_stub_listener_extra_free);
static int manager_add_dns_server_by_string(Manager *m, DnsServerType type, const char *word) {
_cleanup_free_ char *server_name = NULL;
@ -444,10 +436,8 @@ int config_parse_dns_stub_listener_extra(
void *data,
void *userdata) {
_cleanup_free_ DNSStubListenerExtra *udp = NULL, *tcp = NULL;
_cleanup_free_ char *word = NULL;
_cleanup_free_ DNSStubListenerExtra *stub = NULL;
Manager *m = userdata;
bool both = false;
const char *p;
int r;
@ -461,78 +451,41 @@ int config_parse_dns_stub_listener_extra(
return 0;
}
p = rvalue;
r = extract_first_word(&p, &word, ":", 0);
if (r == -ENOMEM)
r = dns_stub_listener_extra_new(&stub);
if (r < 0)
return log_oom();
if (r <= 0) {
p = startswith(rvalue, "udp:");
if (p)
stub->mode = DNS_STUB_LISTENER_UDP;
else {
p = startswith(rvalue, "tcp:");
if (p)
stub->mode = DNS_STUB_LISTENER_TCP;
else {
stub->mode = DNS_STUB_LISTENER_YES;
p = rvalue;
}
}
r = in_addr_port_from_string_auto(p, &stub->family, &stub->address, &stub->port);
if (r < 0) {
log_syntax(unit, LOG_WARNING, filename, line, r,
"Invalid DNSStubListenExtra='%s', ignoring assignment", rvalue);
"Failed to parse address in %s=%s, ignoring assignment: %m",
lvalue, rvalue);
return 0;
}
/* First look for udp/tcp. If not specified then turn both TCP and UDP */
if (!STR_IN_SET(word, "tcp", "udp")) {
both = true;
p = rvalue;
}
if (streq(word, "tcp") || both) {
r = dns_stub_extra_new(&tcp);
if (r < 0)
return log_oom();
tcp->mode = DNS_STUB_LISTENER_TCP;
}
if (streq(word, "udp") || both) {
r = dns_stub_extra_new(&udp);
if (r < 0)
return log_oom();
udp->mode = DNS_STUB_LISTENER_UDP;
}
if (tcp) {
r = socket_addr_port_from_string_auto(p, 53, &tcp->address);
if (r < 0) {
log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse address in DNSStubListenExtra='%s', ignoring", rvalue);
return 0;
}
}
if (udp) {
r = socket_addr_port_from_string_auto(p, 53, &udp->address);
if (r < 0) {
log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse address in DNSStubListenExtra='%s', ignoring", rvalue);
return 0;
}
}
if (tcp) {
r = ordered_set_ensure_put(&m->dns_extra_stub_listeners, &dns_stub_listener_extra_hash_ops, tcp);
if (r < 0) {
r = ordered_set_ensure_put(&m->dns_extra_stub_listeners, &dns_stub_listener_extra_hash_ops, stub);
if (r == -ENOMEM)
return log_oom();
log_warning_errno(r, "Failed to store TCP DNSStubListenExtra='%s', ignoring assignment: %m", rvalue);
return 0;
}
}
if (udp) {
r = ordered_set_ensure_put(&m->dns_extra_stub_listeners, &dns_stub_listener_extra_hash_ops, udp);
if (r < 0) {
if (r == -ENOMEM)
return log_oom();
log_warning_errno(r, "Failed to store UDP DNSStubListenExtra='%s', ignoring assignment: %m", rvalue);
log_syntax(unit, LOG_WARNING, filename, line, r,
"Failed to store %s=%s, ignoring assignment: %m", lvalue, rvalue);
return 0;
}
}
TAKE_PTR(tcp);
TAKE_PTR(udp);
TAKE_PTR(stub);
return 0;
}

View File

@ -7,9 +7,9 @@ typedef enum DnsStubListenerMode DnsStubListenerMode;
enum DnsStubListenerMode {
DNS_STUB_LISTENER_NO,
DNS_STUB_LISTENER_UDP,
DNS_STUB_LISTENER_TCP,
DNS_STUB_LISTENER_YES,
DNS_STUB_LISTENER_UDP = 1 << 0,
DNS_STUB_LISTENER_TCP = 1 << 1,
DNS_STUB_LISTENER_YES = DNS_STUB_LISTENER_UDP | DNS_STUB_LISTENER_TCP,
_DNS_STUB_LISTENER_MODE_MAX,
_DNS_STUB_LISTENER_MODE_INVALID = -1
};

View File

@ -66,6 +66,7 @@ struct DnsPacket {
DnsResourceRecord *opt;
/* Packet reception metadata */
int fd; /* Used by UDP extra DNS stub listners */
int ifindex;
int family, ipproto;
union in_addr_union sender, destination;

View File

@ -1,8 +1,11 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#include <net/if_arp.h>
#include "errno-util.h"
#include "fd-util.h"
#include "missing_network.h"
#include "missing_socket.h"
#include "resolved-dns-stub.h"
#include "socket-netlink.h"
#include "socket-util.h"
@ -11,25 +14,28 @@
* IP and UDP header sizes */
#define ADVERTISE_DATAGRAM_SIZE_MAX (65536U-14U-20U-8U)
static int manager_dns_stub_udp_fd(Manager *m);
static int manager_dns_stub_tcp_fd(Manager *m);
int dns_stub_extra_new(DNSStubListenerExtra **ret) {
int dns_stub_listener_extra_new(DNSStubListenerExtra **ret) {
DNSStubListenerExtra *l;
l = new(DNSStubListenerExtra, 1);
l = new0(DNSStubListenerExtra, 1);
if (!l)
return -ENOMEM;
*l = (DNSStubListenerExtra) {
.fd = -1,
};
*ret = TAKE_PTR(l);
return 0;
}
DNSStubListenerExtra *dns_stub_listener_extra_free(DNSStubListenerExtra *p) {
if (!p)
return NULL;
p->udp_event_source = sd_event_source_unref(p->udp_event_source);
p->tcp_event_source = sd_event_source_unref(p->tcp_event_source);
return mfree(p);
}
static int dns_stub_make_reply_packet(
DnsPacket **p,
size_t max_size,
@ -155,17 +161,11 @@ static int dns_stub_send(Manager *m, DnsStream *s, DnsPacket *p, DnsPacket *repl
if (s)
r = dns_stream_write_packet(s, reply);
else {
int fd;
fd = manager_dns_stub_udp_fd(m);
if (fd < 0)
return log_debug_errno(fd, "Failed to get reply socket: %m");
/* Note that it is essential here that we explicitly choose the source IP address for this packet. This
* is because otherwise the kernel will choose it automatically based on the routing table and will
* thus pick 127.0.0.1 rather than 127.0.0.53. */
r = manager_send(m, fd, LOOPBACK_IFINDEX, p->family, &p->sender, p->sender_port, &p->destination, reply);
r = manager_send(m, p->fd, p->ifindex, p->family, &p->sender, p->sender_port, &p->destination, reply);
}
if (r < 0)
return log_debug_errno(r, "Failed to send reply packet: %m");
@ -294,7 +294,7 @@ static int dns_stub_stream_complete(DnsStream *s, int error) {
return 0;
}
static void dns_stub_process_query(Manager *m, DnsStream *s, DnsPacket *p) {
static void dns_stub_process_query(Manager *m, DnsStream *s, DnsPacket *p, bool is_extra) {
_cleanup_(dns_query_freep) DnsQuery *q = NULL;
int r;
@ -302,8 +302,9 @@ static void dns_stub_process_query(Manager *m, DnsStream *s, DnsPacket *p) {
assert(p);
assert(p->protocol == DNS_PROTOCOL_DNS);
if (in_addr_is_localhost(p->family, &p->sender) <= 0 ||
in_addr_is_localhost(p->family, &p->destination) <= 0) {
if (!is_extra &&
(in_addr_is_localhost(p->family, &p->sender) <= 0 ||
in_addr_is_localhost(p->family, &p->destination) <= 0)) {
log_error("Got packet on unexpected IP range, refusing.");
dns_stub_send_failure(m, s, p, DNS_RCODE_SERVFAIL, false);
return;
@ -384,9 +385,8 @@ static void dns_stub_process_query(Manager *m, DnsStream *s, DnsPacket *p) {
TAKE_PTR(q);
}
static int on_dns_stub_packet(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
static int on_dns_stub_packet_internal(sd_event_source *s, int fd, uint32_t revents, Manager *m, bool is_extra) {
_cleanup_(dns_packet_unrefp) DnsPacket *p = NULL;
Manager *m = userdata;
int r;
r = manager_recv(m, fd, DNS_PROTOCOL_DNS, &p);
@ -396,27 +396,50 @@ static int on_dns_stub_packet(sd_event_source *s, int fd, uint32_t revents, void
if (dns_packet_validate_query(p) > 0) {
log_debug("Got DNS stub UDP query packet for id %u", DNS_PACKET_ID(p));
dns_stub_process_query(m, NULL, p);
dns_stub_process_query(m, NULL, p, is_extra);
} else
log_debug("Invalid DNS stub UDP packet, ignoring.");
return 0;
}
static int set_dns_stub_common_socket_options(int fd) {
static int on_dns_stub_packet(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
return on_dns_stub_packet_internal(s, fd, revents, userdata, false);
}
static int on_dns_stub_packet_extra(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
return on_dns_stub_packet_internal(s, fd, revents, userdata, true);
}
static int set_dns_stub_common_socket_options(int fd, int family) {
int r;
assert(fd >= 0);
assert(IN_SET(family, AF_INET, AF_INET6));
r = setsockopt_int(fd, SOL_SOCKET, SO_REUSEADDR, true);
if (r < 0)
return r;
if (family == AF_INET) {
r = setsockopt_int(fd, IPPROTO_IP, IP_PKTINFO, true);
if (r < 0)
return r;
return setsockopt_int(fd, IPPROTO_IP, IP_RECVTTL, true);
r = setsockopt_int(fd, IPPROTO_IP, IP_RECVTTL, true);
if (r < 0)
return r;
} else {
r = setsockopt_int(fd, IPPROTO_IPV6, IPV6_RECVPKTINFO, true);
if (r < 0)
return r;
r = setsockopt_int(fd, IPPROTO_IPV6, IPV6_RECVHOPLIMIT, true);
if (r < 0)
return r;
}
return 0;
}
static int manager_dns_stub_udp_fd(Manager *m) {
@ -428,14 +451,14 @@ static int manager_dns_stub_udp_fd(Manager *m) {
_cleanup_close_ int fd = -1;
int r;
if (m->dns_stub_udp_fd >= 0)
return m->dns_stub_udp_fd;
if (m->dns_stub_udp_event_source)
return sd_event_source_get_io_fd(m->dns_stub_udp_event_source);
fd = socket(AF_INET, SOCK_DGRAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0);
if (fd < 0)
return -errno;
r = set_dns_stub_common_socket_options(fd);
r = set_dns_stub_common_socket_options(fd, AF_INET);
if (r < 0)
return r;
@ -451,70 +474,84 @@ static int manager_dns_stub_udp_fd(Manager *m) {
if (r < 0)
return r;
r = sd_event_source_set_io_fd_own(m->dns_stub_udp_event_source, true);
if (r < 0)
return r;
(void) sd_event_source_set_description(m->dns_stub_udp_event_source, "dns-stub-udp");
return m->dns_stub_udp_fd = TAKE_FD(fd);
return TAKE_FD(fd);
}
static int manager_dns_stub_udp_fd_extra(Manager *m, DNSStubListenerExtra *l) {
_cleanup_free_ char *pretty = NULL;
_cleanup_close_ int fd = -1;
union sockaddr_union sa;
int r;
if (l->fd >= 0)
if (l->udp_event_source)
return 0;
fd = socket(socket_address_family(&l->address), SOCK_DGRAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0);
if (l->family == AF_INET)
sa = (union sockaddr_union) {
.in.sin_family = l->family,
.in.sin_port = htobe16(l->port != 0 ? l->port : 53U),
.in.sin_addr = l->address.in,
};
else
sa = (union sockaddr_union) {
.in6.sin6_family = l->family,
.in6.sin6_port = htobe16(l->port != 0 ? l->port : 53U),
.in6.sin6_addr = l->address.in6,
};
fd = socket(l->family, SOCK_DGRAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0);
if (fd < 0) {
r = -errno;
goto fail;
}
if (l->family == AF_INET) {
r = setsockopt_int(fd, IPPROTO_IP, IP_FREEBIND, true);
if (r < 0)
goto fail;
}
r = set_dns_stub_common_socket_options(fd);
r = set_dns_stub_common_socket_options(fd, l->family);
if (r < 0)
goto fail;
if (bind(fd, &l->address.sockaddr.sa, l->address.size) < 0) {
if (bind(fd, &sa.sa, SOCKADDR_LEN(sa)) < 0) {
r = -errno;
goto fail;
}
r = sd_event_add_io(m->event, &l->dns_stub_extra_event_source, fd, EPOLLIN, on_dns_stub_packet, m);
r = sd_event_add_io(m->event, &l->udp_event_source, fd, EPOLLIN, on_dns_stub_packet_extra, m);
if (r < 0)
goto fail;
(void) sd_event_source_set_description(l->dns_stub_extra_event_source, "dns-stub-udp-extra");
r = sd_event_source_set_io_fd_own(l->udp_event_source, true);
if (r < 0)
goto fail;
l->fd = TAKE_FD(fd);
(void) sd_event_source_set_description(l->udp_event_source, "dns-stub-udp-extra");
if (DEBUG_LOGGING) {
(void) sockaddr_pretty(&l->address.sockaddr.sa, FAMILY_ADDRESS_SIZE(l->address.sockaddr.sa.sa_family), true, true, &pretty);
(void) in_addr_port_to_string(l->family, &l->address, l->port, &pretty);
log_debug("Listening on UDP socket %s.", strnull(pretty));
}
return 0;
return TAKE_FD(fd);
fail:
(void) sockaddr_pretty(&l->address.sockaddr.sa, FAMILY_ADDRESS_SIZE(l->address.sockaddr.sa.sa_family), true, true, &pretty);
if (r == -EADDRINUSE)
return log_warning_errno(r,
"Another process is already listening on UDP socket %s.\n"
"Turning off local DNS stub extra support.", strnull(pretty));
if (r == -EPERM)
return log_warning_errno(r,
"Failed to listen on UDP socket %s: %m.\n"
"Turning off local DNS stub extra support.", strnull(pretty));
assert(r < 0);
return log_warning_errno(r, "Failed to listen on UDP socket %s, ignoring: %m", strnull(pretty));
(void) in_addr_port_to_string(l->family, &l->address, l->port, &pretty);
if (r == -EADDRINUSE)
return log_warning_errno(r, "Another process is already listening on UDP socket %s: %m", strnull(pretty));
return log_warning_errno(r, "Failed to listen on UDP socket %s: %m", strnull(pretty));
}
static int on_dns_stub_stream_packet(DnsStream *s) {
static int on_dns_stub_stream_packet_internal(DnsStream *s, bool is_extra) {
_cleanup_(dns_packet_unrefp) DnsPacket *p = NULL;
assert(s);
@ -525,16 +562,23 @@ static int on_dns_stub_stream_packet(DnsStream *s) {
if (dns_packet_validate_query(p) > 0) {
log_debug("Got DNS stub TCP query packet for id %u", DNS_PACKET_ID(p));
dns_stub_process_query(s->manager, s, p);
dns_stub_process_query(s->manager, s, p, is_extra);
} else
log_debug("Invalid DNS stub TCP packet, ignoring.");
return 0;
}
static int on_dns_stub_stream(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
static int on_dns_stub_stream_packet(DnsStream *s) {
return on_dns_stub_stream_packet_internal(s, false);
}
static int on_dns_stub_stream_packet_extra(DnsStream *s) {
return on_dns_stub_stream_packet_internal(s, true);
}
static int on_dns_stub_stream_internal(sd_event_source *s, int fd, uint32_t revents, Manager *m, bool is_extra) {
DnsStream *stream;
Manager *m = userdata;
int cfd, r;
cfd = accept4(fd, NULL, NULL, SOCK_NONBLOCK|SOCK_CLOEXEC);
@ -551,7 +595,7 @@ static int on_dns_stub_stream(sd_event_source *s, int fd, uint32_t revents, void
return r;
}
stream->on_packet = on_dns_stub_stream_packet;
stream->on_packet = is_extra ? on_dns_stub_stream_packet_extra : on_dns_stub_stream_packet;
stream->complete = dns_stub_stream_complete;
/* We let the reference to the stream dangle here, it will be dropped later by the complete callback. */
@ -559,6 +603,14 @@ static int on_dns_stub_stream(sd_event_source *s, int fd, uint32_t revents, void
return 0;
}
static int on_dns_stub_stream(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
return on_dns_stub_stream_internal(s, fd, revents, userdata, false);
}
static int on_dns_stub_stream_extra(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
return on_dns_stub_stream_internal(s, fd, revents, userdata, true);
}
static int manager_dns_stub_tcp_fd(Manager *m) {
union sockaddr_union sa = {
.in.sin_family = AF_INET,
@ -568,14 +620,14 @@ static int manager_dns_stub_tcp_fd(Manager *m) {
_cleanup_close_ int fd = -1;
int r;
if (m->dns_stub_tcp_fd >= 0)
return m->dns_stub_tcp_fd;
if (m->dns_stub_tcp_event_source)
return sd_event_source_get_io_fd(m->dns_stub_tcp_event_source);
fd = socket(AF_INET, SOCK_STREAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0);
if (fd < 0)
return -errno;
r = set_dns_stub_common_socket_options(fd);
r = set_dns_stub_common_socket_options(fd, AF_INET);
if (r < 0)
return r;
@ -598,38 +650,58 @@ static int manager_dns_stub_tcp_fd(Manager *m) {
if (r < 0)
return r;
r = sd_event_source_set_io_fd_own(m->dns_stub_tcp_event_source, true);
if (r < 0)
return r;
(void) sd_event_source_set_description(m->dns_stub_tcp_event_source, "dns-stub-tcp");
return m->dns_stub_tcp_fd = TAKE_FD(fd);
return TAKE_FD(fd);
}
static int manager_dns_stub_tcp_fd_extra(Manager *m, DNSStubListenerExtra *l) {
_cleanup_free_ char *pretty = NULL;
_cleanup_close_ int fd = -1;
union sockaddr_union sa;
int r;
if (l->fd >= 0)
return 0;
if (l->tcp_event_source)
return sd_event_source_get_io_fd(l->tcp_event_source);;
fd = socket(socket_address_family(&l->address), SOCK_STREAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0);
if (l->family == AF_INET)
sa = (union sockaddr_union) {
.in.sin_family = l->family,
.in.sin_port = htobe16(l->port != 0 ? l->port : 53U),
.in.sin_addr = l->address.in,
};
else
sa = (union sockaddr_union) {
.in6.sin6_family = l->family,
.in6.sin6_port = htobe16(l->port != 0 ? l->port : 53U),
.in6.sin6_addr = l->address.in6,
};
fd = socket(l->family, SOCK_STREAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0);
if (fd < 0) {
r = -errno;
goto fail;
}
r = set_dns_stub_common_socket_options(fd);
r = set_dns_stub_common_socket_options(fd, l->family);
if (r < 0)
goto fail;
r = setsockopt_int(fd, IPPROTO_IP, IP_TTL, 1);
if (r < 0)
goto fail;
/* Do not set IP_TTL for extra DNS stub listners, as the address may not be local and in that
* case people may want ttl > 1. */
if (l->family == AF_INET)
r = setsockopt_int(fd, IPPROTO_IP, IP_FREEBIND, true);
else
r = setsockopt_int(fd, IPPROTO_IPV6, IPV6_FREEBIND, true);
if (r < 0)
goto fail;
if (bind(fd, &l->address.sockaddr.sa, l->address.size) < 0) {
if (bind(fd, &sa.sa, SOCKADDR_LEN(sa)) < 0) {
r = -errno;
goto fail;
}
@ -639,35 +711,29 @@ static int manager_dns_stub_tcp_fd_extra(Manager *m, DNSStubListenerExtra *l) {
goto fail;
}
r = sd_event_add_io(m->event, &l->dns_stub_extra_event_source, fd, EPOLLIN, on_dns_stub_packet, m);
r = sd_event_add_io(m->event, &l->tcp_event_source, fd, EPOLLIN, on_dns_stub_stream_extra, m);
if (r < 0)
goto fail;
(void) sd_event_source_set_description(l->dns_stub_extra_event_source, "dns-stub-tcp-extra");
r = sd_event_source_set_io_fd_own(l->tcp_event_source, true);
if (r < 0)
goto fail;
l->fd = TAKE_FD(fd);
(void) sd_event_source_set_description(l->tcp_event_source, "dns-stub-tcp-extra");
if (DEBUG_LOGGING) {
(void) sockaddr_pretty(&l->address.sockaddr.sa, FAMILY_ADDRESS_SIZE(l->address.sockaddr.sa.sa_family), true, true, &pretty);
(void) in_addr_port_to_string(l->family, &l->address, l->port, &pretty);
log_debug("Listening on TCP socket %s.", strnull(pretty));
}
return 0;
return TAKE_FD(fd);
fail:
(void) sockaddr_pretty(&l->address.sockaddr.sa, FAMILY_ADDRESS_SIZE(l->address.sockaddr.sa.sa_family), true, true, &pretty);
if (r == -EADDRINUSE)
return log_warning_errno(r,
"Another process is already listening on TCP socket %s.\n"
"Turning off local DNS stub extra support.", strnull(pretty));
if (r == -EPERM)
return log_warning_errno(r,
"Failed to listen on TCP socket %s: %m.\n"
"Turning off local DNS stub extra support.", strnull(pretty));
assert(r < 0);
return log_warning_errno(r, "Failed to listen on TCP socket %s, ignoring: %m", strnull(pretty));
(void) in_addr_port_to_string(l->family, &l->address, l->port, &pretty);
if (r == -EADDRINUSE)
return log_warning_errno(r, "Another process is already listening on TCP socket %s: %m", strnull(pretty));
return log_warning_errno(r, "Failed to listen on TCP socket %s: %m", strnull(pretty));
}
int manager_dns_stub_start(Manager *m) {
@ -684,11 +750,11 @@ int manager_dns_stub_start(Manager *m) {
m->dns_stub_listener_mode == DNS_STUB_LISTENER_TCP ? "TCP" :
"UDP/TCP");
if (IN_SET(m->dns_stub_listener_mode, DNS_STUB_LISTENER_YES, DNS_STUB_LISTENER_UDP))
if (FLAGS_SET(m->dns_stub_listener_mode, DNS_STUB_LISTENER_UDP))
r = manager_dns_stub_udp_fd(m);
if (r >= 0 &&
IN_SET(m->dns_stub_listener_mode, DNS_STUB_LISTENER_YES, DNS_STUB_LISTENER_TCP)) {
FLAGS_SET(m->dns_stub_listener_mode, DNS_STUB_LISTENER_TCP)) {
t = "TCP";
r = manager_dns_stub_tcp_fd(m);
}
@ -710,17 +776,15 @@ int manager_dns_stub_start(Manager *m) {
DNSStubListenerExtra *l;
Iterator i;
log_debug("Creating stub listener extra using %s.",
m->dns_stub_listener_mode == DNS_STUB_LISTENER_UDP ? "UDP" :
m->dns_stub_listener_mode == DNS_STUB_LISTENER_TCP ? "TCP" :
"UDP/TCP");
log_debug("Creating extra stub listeners.");
ORDERED_SET_FOREACH(l, m->dns_extra_stub_listeners, i)
if (l->mode == DNS_STUB_LISTENER_UDP)
ORDERED_SET_FOREACH(l, m->dns_extra_stub_listeners, i) {
if (FLAGS_SET(l->mode, DNS_STUB_LISTENER_UDP))
(void) manager_dns_stub_udp_fd_extra(m, l);
else
if (FLAGS_SET(l->mode, DNS_STUB_LISTENER_TCP))
(void) manager_dns_stub_tcp_fd_extra(m, l);
}
}
return 0;
}
@ -730,19 +794,4 @@ void manager_dns_stub_stop(Manager *m) {
m->dns_stub_udp_event_source = sd_event_source_unref(m->dns_stub_udp_event_source);
m->dns_stub_tcp_event_source = sd_event_source_unref(m->dns_stub_tcp_event_source);
m->dns_stub_udp_fd = safe_close(m->dns_stub_udp_fd);
m->dns_stub_tcp_fd = safe_close(m->dns_stub_tcp_fd);
}
void manager_dns_stub_stop_extra(Manager *m) {
DNSStubListenerExtra *l;
Iterator i;
assert(m);
ORDERED_SET_FOREACH(l, m->dns_extra_stub_listeners, i) {
l->dns_stub_extra_event_source = sd_event_source_unref(l->dns_stub_extra_event_source);
l->fd = safe_close(l->fd);
}
}

View File

@ -3,8 +3,8 @@
#include "resolved-manager.h"
int dns_stub_extra_new(DNSStubListenerExtra **ret);
int dns_stub_listener_extra_new(DNSStubListenerExtra **ret);
DNSStubListenerExtra *dns_stub_listener_extra_free(DNSStubListenerExtra *p);
void manager_dns_stub_stop(Manager *m);
void manager_dns_stub_stop_extra(Manager *m);
int manager_dns_stub_start(Manager *m);

View File

@ -578,8 +578,6 @@ int manager_new(Manager **ret) {
.llmnr_ipv6_tcp_fd = -1,
.mdns_ipv4_fd = -1,
.mdns_ipv6_fd = -1,
.dns_stub_udp_fd = -1,
.dns_stub_tcp_fd = -1,
.hostname_fd = -1,
.llmnr_support = DEFAULT_LLMNR_MODE,
@ -701,7 +699,6 @@ Manager *manager_free(Manager *m) {
hashmap_free(m->links);
hashmap_free(m->dns_transactions);
ordered_set_free(m->dns_extra_stub_listeners);
sd_event_source_unref(m->network_event_source);
sd_network_monitor_unref(m->network_monitor);
@ -714,7 +711,7 @@ Manager *manager_free(Manager *m) {
manager_dns_stub_stop(m);
manager_varlink_done(m);
manager_dns_stub_stop_extra(m);
ordered_set_free(m->dns_extra_stub_listeners);
bus_verify_polkit_async_registry_free(m->polkit_registry);
@ -793,6 +790,7 @@ int manager_recv(Manager *m, int fd, DnsProtocol protocol, DnsPacket **ret) {
p->size = (size_t) l;
p->fd = fd;
p->family = sa.sa.sa_family;
p->ipproto = IPPROTO_UDP;
if (p->family == AF_INET) {

View File

@ -32,11 +32,14 @@ typedef struct EtcHosts {
} EtcHosts;
typedef struct DNSStubListenerExtra {
int fd;
DnsStubListenerMode mode;
SocketAddress address;
sd_event_source *dns_stub_extra_event_source;
int family;
union in_addr_union address;
uint16_t port;
sd_event_source *udp_event_source;
sd_event_source *tcp_event_source;
} DNSStubListenerExtra;
struct Manager {
@ -141,12 +144,9 @@ struct Manager {
dev_t etc_hosts_dev;
bool read_etc_hosts;
/* Local DNS stub on 127.0.0.53:53 */
int dns_stub_udp_fd;
int dns_stub_tcp_fd;
OrderedSet *dns_extra_stub_listeners;
/* Local DNS stub on 127.0.0.53:53 */
sd_event_source *dns_stub_udp_event_source;
sd_event_source *dns_stub_tcp_event_source;

View File

@ -572,9 +572,11 @@ int pty_forward_set_priority(PTYForward *f, int64_t priority) {
int r;
assert(f);
if (f->stdin_event_source) {
r = sd_event_source_set_priority(f->stdin_event_source, priority);
if (r < 0)
return r;
}
r = sd_event_source_set_priority(f->stdout_event_source, priority);
if (r < 0)

View File

@ -235,33 +235,6 @@ int socket_address_parse_and_warn(SocketAddress *a, const char *s) {
return 0;
}
int socket_addr_port_from_string_auto(const char *s, uint16_t default_port, SocketAddress *a) {
union in_addr_union address;
uint16_t port = 0;
int family, r;
assert(a);
assert(s);
r = in_addr_port_ifindex_name_from_string_auto(s, &family, &address, &port, NULL, NULL);
if (r < 0)
return r;
if (family == AF_INET) {
memcpy(&a->sockaddr.in.sin_addr, &address.in.s_addr, sizeof(a->sockaddr.in.sin_addr));
a->sockaddr.in.sin_family = AF_INET;
a->size = sizeof(struct sockaddr_in);
a->sockaddr.in.sin_port = port ? htobe16(port) : htobe16(default_port);
} else {
memcpy(&a->sockaddr.in6.sin6_addr, &address.in6, sizeof(a->sockaddr.in6.sin6_addr));
a->sockaddr.in6.sin6_family = AF_INET6;
a->sockaddr.in6.sin6_port = port ? htobe16(port) : htobe16(default_port);
a->size = sizeof(struct sockaddr_in6);
}
return 0;
}
int socket_address_parse_netlink(SocketAddress *a, const char *s) {
_cleanup_free_ char *word = NULL;
unsigned group = 0;
@ -482,6 +455,36 @@ int in_addr_port_ifindex_name_from_string_auto(
return r;
}
int in_addr_port_from_string_auto(
const char *s,
int *ret_family,
union in_addr_union *ret_address,
uint16_t *ret_port) {
union in_addr_union addr;
int family, ifindex, r;
uint16_t port;
assert(s);
r = in_addr_port_ifindex_name_from_string_auto(s, &family, &addr, &port, &ifindex, NULL);
if (r < 0)
return r;
/* This does not accept interface specified. */
if (ifindex != 0)
return -EINVAL;
if (ret_family)
*ret_family = family;
if (ret_address)
*ret_address = addr;
if (ret_port)
*ret_port = port;
return r;
}
struct in_addr_full *in_addr_full_free(struct in_addr_full *a) {
if (!a)
return NULL;

View File

@ -16,7 +16,6 @@ int make_socket_fd(int log_level, const char* address, int type, int flags);
int socket_address_parse(SocketAddress *a, const char *s);
int socket_address_parse_and_warn(SocketAddress *a, const char *s);
int socket_address_parse_netlink(SocketAddress *a, const char *s);
int socket_addr_port_from_string_auto(const char *s, uint16_t default_port, SocketAddress *a);
bool socket_address_is(const SocketAddress *a, const char *s, int type);
bool socket_address_is_netlink(const SocketAddress *a, const char *s);
@ -34,6 +33,7 @@ static inline int in_addr_ifindex_name_from_string_auto(const char *s, int *fami
static inline int in_addr_ifindex_from_string_auto(const char *s, int *family, union in_addr_union *ret, int *ifindex) {
return in_addr_ifindex_name_from_string_auto(s, family, ret, ifindex, NULL);
}
int in_addr_port_from_string_auto(const char *s, int *ret_family, union in_addr_union *ret_address, uint16_t *ret_port);
struct in_addr_full {
int family;

View File

@ -2212,9 +2212,7 @@ int varlink_server_listen_fd(VarlinkServer *s, int fd) {
};
if (s->event) {
_cleanup_(sd_event_source_unrefp) sd_event_source *es = NULL;
r = sd_event_add_io(s->event, &es, fd, EPOLLIN, connect_callback, ss);
r = sd_event_add_io(s->event, &ss->event_source, fd, EPOLLIN, connect_callback, ss);
if (r < 0)
return r;

View File

@ -94,6 +94,12 @@ enum {
#define SD_BUS_ERROR_INTERACTIVE_AUTHORIZATION_REQUIRED \
"org.freedesktop.DBus.Error.InteractiveAuthorizationRequired"
/* https://dbus.freedesktop.org/doc/dbus-specification.html#message-protocol-marshaling-signature */
#define SD_BUS_MAXIMUM_SIGNATURE_LENGTH 255
/* https://dbus.freedesktop.org/doc/dbus-specification.html#message-protocol-names */
#define SD_BUS_MAXIMUM_NAME_LENGTH 255
_SD_END_DECLARATIONS;
#endif

View File

@ -34,12 +34,6 @@ _SD_BEGIN_DECLARATIONS;
#define SD_BUS_DEFAULT_USER ((sd_bus *) 2)
#define SD_BUS_DEFAULT_SYSTEM ((sd_bus *) 3)
/* https://dbus.freedesktop.org/doc/dbus-specification.html#message-protocol-marshaling-signature */
#define SD_BUS_MAXIMUM_SIGNATURE_LENGTH 255
/* https://dbus.freedesktop.org/doc/dbus-specification.html#message-protocol-names */
#define SD_BUS_MAXIMUM_NAME_LENGTH 255
/* Types */
typedef struct sd_bus sd_bus;

View File

@ -177,10 +177,163 @@ static void test_in_addr_random_prefix(void) {
str = mfree(str);
}
static void test_in_addr_is_null(void) {
union in_addr_union i = {};
log_info("/* %s */", __func__);
assert_se(in_addr_is_null(AF_INET, &i) == true);
assert_se(in_addr_is_null(AF_INET6, &i) == true);
i.in.s_addr = 0x1000000;
assert_se(in_addr_is_null(AF_INET, &i) == false);
assert_se(in_addr_is_null(AF_INET6, &i) == false);
assert_se(in_addr_is_null(-1, &i) == -EAFNOSUPPORT);
}
static void test_in_addr_prefix_intersect_one(unsigned f, const char *a, unsigned apl, const char *b, unsigned bpl, int result) {
union in_addr_union ua, ub;
assert_se(in_addr_from_string(f, a, &ua) >= 0);
assert_se(in_addr_from_string(f, b, &ub) >= 0);
assert_se(in_addr_prefix_intersect(f, &ua, apl, &ub, bpl) == result);
}
static void test_in_addr_prefix_intersect(void) {
log_info("/* %s */", __func__);
test_in_addr_prefix_intersect_one(AF_INET, "255.255.255.255", 32, "255.255.255.254", 32, 0);
test_in_addr_prefix_intersect_one(AF_INET, "255.255.255.255", 0, "255.255.255.255", 32, 1);
test_in_addr_prefix_intersect_one(AF_INET, "0.0.0.0", 0, "47.11.8.15", 32, 1);
test_in_addr_prefix_intersect_one(AF_INET, "1.1.1.1", 24, "1.1.1.1", 24, 1);
test_in_addr_prefix_intersect_one(AF_INET, "2.2.2.2", 24, "1.1.1.1", 24, 0);
test_in_addr_prefix_intersect_one(AF_INET, "1.1.1.1", 24, "1.1.1.127", 25, 1);
test_in_addr_prefix_intersect_one(AF_INET, "1.1.1.1", 24, "1.1.1.127", 26, 1);
test_in_addr_prefix_intersect_one(AF_INET, "1.1.1.1", 25, "1.1.1.127", 25, 1);
test_in_addr_prefix_intersect_one(AF_INET, "1.1.1.1", 25, "1.1.1.255", 25, 0);
test_in_addr_prefix_intersect_one(AF_INET6, "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff", 128, "ffff:ffff:ffff:ffff:ffff:ffff:ffff:fffe", 128, 0);
test_in_addr_prefix_intersect_one(AF_INET6, "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff", 0, "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff", 128, 1);
test_in_addr_prefix_intersect_one(AF_INET6, "::", 0, "beef:beef:beef:beef:beef:beef:beef:beef", 128, 1);
test_in_addr_prefix_intersect_one(AF_INET6, "1::2", 64, "1::2", 64, 1);
test_in_addr_prefix_intersect_one(AF_INET6, "2::2", 64, "1::2", 64, 0);
test_in_addr_prefix_intersect_one(AF_INET6, "1::1", 120, "1::007f", 121, 1);
test_in_addr_prefix_intersect_one(AF_INET6, "1::1", 120, "1::007f", 122, 1);
test_in_addr_prefix_intersect_one(AF_INET6, "1::1", 121, "1::007f", 121, 1);
test_in_addr_prefix_intersect_one(AF_INET6, "1::1", 121, "1::00ff", 121, 0);
}
static void test_in_addr_prefix_next_one(unsigned f, const char *before, unsigned pl, const char *after) {
union in_addr_union ubefore, uafter, t;
assert_se(in_addr_from_string(f, before, &ubefore) >= 0);
t = ubefore;
assert_se((in_addr_prefix_next(f, &t, pl) > 0) == !!after);
if (after) {
assert_se(in_addr_from_string(f, after, &uafter) >= 0);
assert_se(in_addr_equal(f, &t, &uafter) > 0);
}
}
static void test_in_addr_prefix_next(void) {
log_info("/* %s */", __func__);
test_in_addr_prefix_next_one(AF_INET, "192.168.0.0", 24, "192.168.1.0");
test_in_addr_prefix_next_one(AF_INET, "192.168.0.0", 16, "192.169.0.0");
test_in_addr_prefix_next_one(AF_INET, "192.168.0.0", 20, "192.168.16.0");
test_in_addr_prefix_next_one(AF_INET, "0.0.0.0", 32, "0.0.0.1");
test_in_addr_prefix_next_one(AF_INET, "255.255.255.255", 32, NULL);
test_in_addr_prefix_next_one(AF_INET, "255.255.255.0", 24, NULL);
test_in_addr_prefix_next_one(AF_INET6, "4400::", 128, "4400::0001");
test_in_addr_prefix_next_one(AF_INET6, "4400::", 120, "4400::0100");
test_in_addr_prefix_next_one(AF_INET6, "4400::", 127, "4400::0002");
test_in_addr_prefix_next_one(AF_INET6, "4400::", 8, "4500::");
test_in_addr_prefix_next_one(AF_INET6, "4400::", 7, "4600::");
test_in_addr_prefix_next_one(AF_INET6, "::", 128, "::1");
test_in_addr_prefix_next_one(AF_INET6, "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff", 128, NULL);
test_in_addr_prefix_next_one(AF_INET6, "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ff00", 120, NULL);
}
static void test_in_addr_prefix_nth_one(unsigned f, const char *before, unsigned pl, uint64_t nth, const char *after) {
union in_addr_union ubefore, uafter, t;
assert_se(in_addr_from_string(f, before, &ubefore) >= 0);
t = ubefore;
assert_se((in_addr_prefix_nth(f, &t, pl, nth) > 0) == !!after);
if (after) {
assert_se(in_addr_from_string(f, after, &uafter) >= 0);
assert_se(in_addr_equal(f, &t, &uafter) > 0);
}
}
static void test_in_addr_prefix_nth(void) {
log_info("/* %s */", __func__);
test_in_addr_prefix_nth_one(AF_INET, "192.168.0.0", 24, 0, "192.168.0.0");
test_in_addr_prefix_nth_one(AF_INET, "192.168.0.0", 24, 1, "192.168.1.0");
test_in_addr_prefix_nth_one(AF_INET, "192.168.0.0", 24, 4, "192.168.4.0");
test_in_addr_prefix_nth_one(AF_INET, "192.168.0.0", 25, 1, "192.168.0.128");
test_in_addr_prefix_nth_one(AF_INET, "192.168.255.0", 25, 1, "192.168.255.128");
test_in_addr_prefix_nth_one(AF_INET, "192.168.255.0", 24, 0, "192.168.255.0");
test_in_addr_prefix_nth_one(AF_INET, "255.255.255.255", 32, 1, NULL);
test_in_addr_prefix_nth_one(AF_INET, "255.255.255.255", 0, 1, NULL);
test_in_addr_prefix_nth_one(AF_INET6, "4400::", 8, 1, "4500::");
test_in_addr_prefix_nth_one(AF_INET6, "4400::", 7, 1, "4600::");
test_in_addr_prefix_nth_one(AF_INET6, "4400::", 64, 1, "4400:0:0:1::");
test_in_addr_prefix_nth_one(AF_INET6, "4400::", 64, 2, "4400:0:0:2::");
test_in_addr_prefix_nth_one(AF_INET6, "4400::", 64, 0xbad, "4400:0:0:0bad::");
test_in_addr_prefix_nth_one(AF_INET6, "4400:0:0:ffff::", 64, 1, "4400:0:1::");
test_in_addr_prefix_nth_one(AF_INET6, "4400::", 56, ((uint64_t)1<<48) -1, "44ff:ffff:ffff:ff00::");
test_in_addr_prefix_nth_one(AF_INET6, "0000::", 8, 255, "ff00::");
test_in_addr_prefix_nth_one(AF_INET6, "0000::", 8, 256, NULL);
test_in_addr_prefix_nth_one(AF_INET6, "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff", 128, 1, NULL);
test_in_addr_prefix_nth_one(AF_INET6, "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff", 0, 1, NULL);
}
static void test_in_addr_to_string_one(int f, const char *addr) {
union in_addr_union ua;
_cleanup_free_ char *r = NULL;
assert_se(in_addr_from_string(f, addr, &ua) >= 0);
assert_se(in_addr_to_string(f, &ua, &r) >= 0);
printf("test_in_addr_to_string_one: %s == %s\n", addr, r);
assert_se(streq(addr, r));
}
static void test_in_addr_to_string(void) {
log_info("/* %s */", __func__);
test_in_addr_to_string_one(AF_INET, "192.168.0.1");
test_in_addr_to_string_one(AF_INET, "10.11.12.13");
test_in_addr_to_string_one(AF_INET6, "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff");
test_in_addr_to_string_one(AF_INET6, "::1");
test_in_addr_to_string_one(AF_INET6, "fe80::");
}
int main(int argc, char *argv[]) {
test_in_addr_prefix_from_string();
test_in_addr_random_prefix();
test_in_addr_prefix_to_string();
test_in_addr_is_null();
test_in_addr_prefix_intersect();
test_in_addr_prefix_next();
test_in_addr_prefix_nth();
test_in_addr_to_string();
return 0;
}

View File

@ -1,6 +1,7 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#include "alloc-util.h"
#include "missing_network.h"
#include "tests.h"
#include "socket-netlink.h"
#include "string-util.h"
@ -213,39 +214,136 @@ static void test_socket_address_is_netlink(void) {
assert_se(!socket_address_is_netlink(&a, "route 1"));
}
static void test_socket_addr_port_from_string_auto_one(const char *in, uint16_t port, int ret, int family, const char *expected) {
_cleanup_free_ char *out = NULL;
SocketAddress a;
int r;
static void test_in_addr_ifindex_to_string_one(int f, const char *a, int ifindex, const char *b) {
_cleanup_free_ char *r = NULL;
union in_addr_union ua, uuaa;
int ff, ifindex2;
r = socket_addr_port_from_string_auto(in, port, &a);
if (r >= 0)
assert_se(sockaddr_pretty(&a.sockaddr.sa, a.size, false, true, &out) >= 0);
assert_se(in_addr_from_string(f, a, &ua) >= 0);
assert_se(in_addr_ifindex_to_string(f, &ua, ifindex, &r) >= 0);
printf("test_in_addr_ifindex_to_string_one: %s == %s\n", b, r);
assert_se(streq(b, r));
log_info("\"%s\" → %s → \"%s\" (expect \"%s\")", in,
r >= 0 ? "" : "", empty_to_dash(out), r >= 0 ? expected ?: in : "-");
assert_se(r == ret);
if (r >= 0) {
assert_se(a.sockaddr.sa.sa_family == family);
assert_se(streq(out, expected ?: in));
}
assert_se(in_addr_ifindex_from_string_auto(b, &ff, &uuaa, &ifindex2) >= 0);
assert_se(ff == f);
assert_se(in_addr_equal(f, &ua, &uuaa));
assert_se(ifindex2 == ifindex || ifindex2 == 0);
}
static void test_socket_addr_port_from_string_auto(void) {
static void test_in_addr_ifindex_to_string(void) {
log_info("/* %s */", __func__);
test_socket_addr_port_from_string_auto_one("junk", 51, -EINVAL, 0, NULL);
test_socket_addr_port_from_string_auto_one("192.168.1.1", 53, 0, AF_INET, "192.168.1.1:53");
test_socket_addr_port_from_string_auto_one(".168.1.1", 53, -EINVAL, 0, NULL);
test_socket_addr_port_from_string_auto_one("989.168.1.1", 53, -EINVAL, 0, NULL);
test_in_addr_ifindex_to_string_one(AF_INET, "192.168.0.1", 7, "192.168.0.1");
test_in_addr_ifindex_to_string_one(AF_INET, "10.11.12.13", 9, "10.11.12.13");
test_in_addr_ifindex_to_string_one(AF_INET6, "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff", 10, "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff");
test_in_addr_ifindex_to_string_one(AF_INET6, "::1", 11, "::1");
test_in_addr_ifindex_to_string_one(AF_INET6, "fe80::", 12, "fe80::%12");
test_in_addr_ifindex_to_string_one(AF_INET6, "fe80::", 0, "fe80::");
test_in_addr_ifindex_to_string_one(AF_INET6, "fe80::14", 12, "fe80::14%12");
test_in_addr_ifindex_to_string_one(AF_INET6, "fe80::15", -7, "fe80::15");
test_in_addr_ifindex_to_string_one(AF_INET6, "fe80::16", LOOPBACK_IFINDEX, "fe80::16%1");
}
test_socket_addr_port_from_string_auto_one("[::1]", 53, -EINVAL, 0, NULL);
test_socket_addr_port_from_string_auto_one("[::1]8888", 53, -EINVAL, 0, NULL);
test_socket_addr_port_from_string_auto_one("2001:db8:3c4d:15::1a2f:1a2b", 53, 0, AF_INET6, "[2001:db8:3c4d:15::1a2f:1a2b]:53");
test_socket_addr_port_from_string_auto_one("[2001:db8:3c4d:15::1a2f:1a2b]:2001", 53, 0, AF_INET6, "[2001:db8:3c4d:15::1a2f:1a2b]:2001");
test_socket_addr_port_from_string_auto_one("[::1]:0", 53, -EINVAL, 0, NULL);
test_socket_addr_port_from_string_auto_one("[::1]:65536", 53, -ERANGE, 0, NULL);
test_socket_addr_port_from_string_auto_one("[a:b:1]:8888", 53, -EINVAL, 0, NULL);
static void test_in_addr_ifindex_from_string_auto(void) {
int family, ifindex;
union in_addr_union ua;
log_info("/* %s */", __func__);
/* Most in_addr_ifindex_from_string_auto() invocations have already been tested above, but let's test some more */
assert_se(in_addr_ifindex_from_string_auto("fe80::17", &family, &ua, &ifindex) >= 0);
assert_se(family == AF_INET6);
assert_se(ifindex == 0);
assert_se(in_addr_ifindex_from_string_auto("fe80::18%19", &family, &ua, &ifindex) >= 0);
assert_se(family == AF_INET6);
assert_se(ifindex == 19);
assert_se(in_addr_ifindex_from_string_auto("fe80::18%lo", &family, &ua, &ifindex) >= 0);
assert_se(family == AF_INET6);
assert_se(ifindex == LOOPBACK_IFINDEX);
assert_se(in_addr_ifindex_from_string_auto("fe80::19%thisinterfacecantexist", &family, &ua, &ifindex) == -ENODEV);
}
static void test_in_addr_ifindex_name_from_string_auto_one(const char *a, const char *expected) {
int family, ifindex;
union in_addr_union ua;
_cleanup_free_ char *server_name = NULL;
assert_se(in_addr_ifindex_name_from_string_auto(a, &family, &ua, &ifindex, &server_name) >= 0);
assert_se(streq_ptr(server_name, expected));
}
static void test_in_addr_ifindex_name_from_string_auto(void) {
log_info("/* %s */", __func__);
test_in_addr_ifindex_name_from_string_auto_one("192.168.0.1", NULL);
test_in_addr_ifindex_name_from_string_auto_one("192.168.0.1#test.com", "test.com");
test_in_addr_ifindex_name_from_string_auto_one("fe80::18%19", NULL);
test_in_addr_ifindex_name_from_string_auto_one("fe80::18%19#another.test.com", "another.test.com");
}
static void test_in_addr_port_ifindex_name_from_string_auto_one(const char *str, int family, uint16_t port, int ifindex, const char *server_name) {
_cleanup_free_ char *name = NULL, *x = NULL;
union in_addr_union a;
uint16_t p;
int f, i;
assert_se(in_addr_port_ifindex_name_from_string_auto(str, &f, &a, &p, &i, &name) >= 0);
assert_se(family == f);
assert_se(port == p);
assert_se(ifindex == i);
assert_se(streq_ptr(server_name, name));
assert_se(in_addr_port_ifindex_name_to_string(f, &a, p, i, name, &x) >= 0);
assert_se(streq(str, x));
}
static void test_in_addr_port_ifindex_name_from_string_auto(void) {
log_info("/* %s */", __func__);
test_in_addr_port_ifindex_name_from_string_auto_one("192.168.0.1", AF_INET, 0, 0, NULL);
test_in_addr_port_ifindex_name_from_string_auto_one("192.168.0.1#test.com", AF_INET, 0, 0, "test.com");
test_in_addr_port_ifindex_name_from_string_auto_one("192.168.0.1:53", AF_INET, 53, 0, NULL);
test_in_addr_port_ifindex_name_from_string_auto_one("192.168.0.1:53#example.com", AF_INET, 53, 0, "example.com");
test_in_addr_port_ifindex_name_from_string_auto_one("fe80::18", AF_INET6, 0, 0, NULL);
test_in_addr_port_ifindex_name_from_string_auto_one("fe80::18#hoge.com", AF_INET6, 0, 0, "hoge.com");
test_in_addr_port_ifindex_name_from_string_auto_one("fe80::18%19", AF_INET6, 0, 19, NULL);
test_in_addr_port_ifindex_name_from_string_auto_one("[fe80::18]:53", AF_INET6, 53, 0, NULL);
test_in_addr_port_ifindex_name_from_string_auto_one("fe80::18%19#hoge.com", AF_INET6, 0, 19, "hoge.com");
test_in_addr_port_ifindex_name_from_string_auto_one("[fe80::18]:53#hoge.com", AF_INET6, 53, 0, "hoge.com");
test_in_addr_port_ifindex_name_from_string_auto_one("[fe80::18]:53%19", AF_INET6, 53, 19, NULL);
test_in_addr_port_ifindex_name_from_string_auto_one("[fe80::18]:53%19#hoge.com", AF_INET6, 53, 19, "hoge.com");
}
static void test_in_addr_port_from_string_auto_one(const char *str, int family, const char *address_string, uint16_t port) {
union in_addr_union a, b;
uint16_t p;
int f;
assert_se(in_addr_port_from_string_auto(str, &f, &a, &p) >= 0);
assert_se(family == f);
assert_se(port == p);
assert_se(in_addr_from_string(family, address_string, &b) >= 0);
assert_se(in_addr_equal(family, &a, &b) == 1);
}
static void test_in_addr_port_from_string_auto(void) {
log_info("/* %s */", __func__);
assert_se(in_addr_port_from_string_auto("192.168.0.1#test.com", NULL, NULL, NULL) < 0);
assert_se(in_addr_port_from_string_auto("192.168.0.1:53#example.com", NULL, NULL, NULL) < 0);
assert_se(in_addr_port_from_string_auto("fe80::18#hoge.com", NULL, NULL, NULL) < 0);
assert_se(in_addr_port_from_string_auto("fe80::18%19", NULL, NULL, NULL) < 0);
assert_se(in_addr_port_from_string_auto("fe80::18%19#hoge.com", NULL, NULL, NULL) < 0);
assert_se(in_addr_port_from_string_auto("[fe80::18]:53#hoge.com", NULL, NULL, NULL) < 0);
assert_se(in_addr_port_from_string_auto("[fe80::18]:53%19", NULL, NULL, NULL) < 0);
assert_se(in_addr_port_from_string_auto("[fe80::18]:53%19#hoge.com", NULL, NULL, NULL) < 0);
test_in_addr_port_from_string_auto_one("192.168.0.1", AF_INET, "192.168.0.1", 0);
test_in_addr_port_from_string_auto_one("192.168.0.1:53", AF_INET, "192.168.0.1", 53);
test_in_addr_port_from_string_auto_one("fe80::18", AF_INET6, "fe80::18", 0);
test_in_addr_port_from_string_auto_one("[fe80::18]:53", AF_INET6, "fe80::18", 53);
}
int main(int argc, char *argv[]) {
@ -257,7 +355,12 @@ int main(int argc, char *argv[]) {
test_socket_address_get_path();
test_socket_address_is();
test_socket_address_is_netlink();
test_socket_addr_port_from_string_auto();
test_in_addr_ifindex_to_string();
test_in_addr_ifindex_from_string_auto();
test_in_addr_ifindex_name_from_string_auto();
test_in_addr_port_ifindex_name_from_string_auto();
test_in_addr_port_from_string_auto();
return 0;
}

View File

@ -15,9 +15,7 @@
#include "io-util.h"
#include "log.h"
#include "macro.h"
#include "missing_network.h"
#include "process-util.h"
#include "socket-netlink.h"
#include "socket-util.h"
#include "string-util.h"
#include "tests.h"
@ -84,256 +82,6 @@ static void test_socket_print_unix(void) {
test_socket_print_unix_one("\0\a\b\n\255", 6, "@\\a\\b\\n\\255\\000");
}
static void test_in_addr_is_null(void) {
union in_addr_union i = {};
log_info("/* %s */", __func__);
assert_se(in_addr_is_null(AF_INET, &i) == true);
assert_se(in_addr_is_null(AF_INET6, &i) == true);
i.in.s_addr = 0x1000000;
assert_se(in_addr_is_null(AF_INET, &i) == false);
assert_se(in_addr_is_null(AF_INET6, &i) == false);
assert_se(in_addr_is_null(-1, &i) == -EAFNOSUPPORT);
}
static void test_in_addr_prefix_intersect_one(unsigned f, const char *a, unsigned apl, const char *b, unsigned bpl, int result) {
union in_addr_union ua, ub;
assert_se(in_addr_from_string(f, a, &ua) >= 0);
assert_se(in_addr_from_string(f, b, &ub) >= 0);
assert_se(in_addr_prefix_intersect(f, &ua, apl, &ub, bpl) == result);
}
static void test_in_addr_prefix_intersect(void) {
log_info("/* %s */", __func__);
test_in_addr_prefix_intersect_one(AF_INET, "255.255.255.255", 32, "255.255.255.254", 32, 0);
test_in_addr_prefix_intersect_one(AF_INET, "255.255.255.255", 0, "255.255.255.255", 32, 1);
test_in_addr_prefix_intersect_one(AF_INET, "0.0.0.0", 0, "47.11.8.15", 32, 1);
test_in_addr_prefix_intersect_one(AF_INET, "1.1.1.1", 24, "1.1.1.1", 24, 1);
test_in_addr_prefix_intersect_one(AF_INET, "2.2.2.2", 24, "1.1.1.1", 24, 0);
test_in_addr_prefix_intersect_one(AF_INET, "1.1.1.1", 24, "1.1.1.127", 25, 1);
test_in_addr_prefix_intersect_one(AF_INET, "1.1.1.1", 24, "1.1.1.127", 26, 1);
test_in_addr_prefix_intersect_one(AF_INET, "1.1.1.1", 25, "1.1.1.127", 25, 1);
test_in_addr_prefix_intersect_one(AF_INET, "1.1.1.1", 25, "1.1.1.255", 25, 0);
test_in_addr_prefix_intersect_one(AF_INET6, "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff", 128, "ffff:ffff:ffff:ffff:ffff:ffff:ffff:fffe", 128, 0);
test_in_addr_prefix_intersect_one(AF_INET6, "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff", 0, "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff", 128, 1);
test_in_addr_prefix_intersect_one(AF_INET6, "::", 0, "beef:beef:beef:beef:beef:beef:beef:beef", 128, 1);
test_in_addr_prefix_intersect_one(AF_INET6, "1::2", 64, "1::2", 64, 1);
test_in_addr_prefix_intersect_one(AF_INET6, "2::2", 64, "1::2", 64, 0);
test_in_addr_prefix_intersect_one(AF_INET6, "1::1", 120, "1::007f", 121, 1);
test_in_addr_prefix_intersect_one(AF_INET6, "1::1", 120, "1::007f", 122, 1);
test_in_addr_prefix_intersect_one(AF_INET6, "1::1", 121, "1::007f", 121, 1);
test_in_addr_prefix_intersect_one(AF_INET6, "1::1", 121, "1::00ff", 121, 0);
}
static void test_in_addr_prefix_next_one(unsigned f, const char *before, unsigned pl, const char *after) {
union in_addr_union ubefore, uafter, t;
assert_se(in_addr_from_string(f, before, &ubefore) >= 0);
t = ubefore;
assert_se((in_addr_prefix_next(f, &t, pl) > 0) == !!after);
if (after) {
assert_se(in_addr_from_string(f, after, &uafter) >= 0);
assert_se(in_addr_equal(f, &t, &uafter) > 0);
}
}
static void test_in_addr_prefix_next(void) {
log_info("/* %s */", __func__);
test_in_addr_prefix_next_one(AF_INET, "192.168.0.0", 24, "192.168.1.0");
test_in_addr_prefix_next_one(AF_INET, "192.168.0.0", 16, "192.169.0.0");
test_in_addr_prefix_next_one(AF_INET, "192.168.0.0", 20, "192.168.16.0");
test_in_addr_prefix_next_one(AF_INET, "0.0.0.0", 32, "0.0.0.1");
test_in_addr_prefix_next_one(AF_INET, "255.255.255.255", 32, NULL);
test_in_addr_prefix_next_one(AF_INET, "255.255.255.0", 24, NULL);
test_in_addr_prefix_next_one(AF_INET6, "4400::", 128, "4400::0001");
test_in_addr_prefix_next_one(AF_INET6, "4400::", 120, "4400::0100");
test_in_addr_prefix_next_one(AF_INET6, "4400::", 127, "4400::0002");
test_in_addr_prefix_next_one(AF_INET6, "4400::", 8, "4500::");
test_in_addr_prefix_next_one(AF_INET6, "4400::", 7, "4600::");
test_in_addr_prefix_next_one(AF_INET6, "::", 128, "::1");
test_in_addr_prefix_next_one(AF_INET6, "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff", 128, NULL);
test_in_addr_prefix_next_one(AF_INET6, "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ff00", 120, NULL);
}
static void test_in_addr_prefix_nth_one(unsigned f, const char *before, unsigned pl, uint64_t nth, const char *after) {
union in_addr_union ubefore, uafter, t;
assert_se(in_addr_from_string(f, before, &ubefore) >= 0);
t = ubefore;
assert_se((in_addr_prefix_nth(f, &t, pl, nth) > 0) == !!after);
if (after) {
assert_se(in_addr_from_string(f, after, &uafter) >= 0);
assert_se(in_addr_equal(f, &t, &uafter) > 0);
}
}
static void test_in_addr_prefix_nth(void) {
log_info("/* %s */", __func__);
test_in_addr_prefix_nth_one(AF_INET, "192.168.0.0", 24, 0, "192.168.0.0");
test_in_addr_prefix_nth_one(AF_INET, "192.168.0.0", 24, 1, "192.168.1.0");
test_in_addr_prefix_nth_one(AF_INET, "192.168.0.0", 24, 4, "192.168.4.0");
test_in_addr_prefix_nth_one(AF_INET, "192.168.0.0", 25, 1, "192.168.0.128");
test_in_addr_prefix_nth_one(AF_INET, "192.168.255.0", 25, 1, "192.168.255.128");
test_in_addr_prefix_nth_one(AF_INET, "192.168.255.0", 24, 0, "192.168.255.0");
test_in_addr_prefix_nth_one(AF_INET, "255.255.255.255", 32, 1, NULL);
test_in_addr_prefix_nth_one(AF_INET, "255.255.255.255", 0, 1, NULL);
test_in_addr_prefix_nth_one(AF_INET6, "4400::", 8, 1, "4500::");
test_in_addr_prefix_nth_one(AF_INET6, "4400::", 7, 1, "4600::");
test_in_addr_prefix_nth_one(AF_INET6, "4400::", 64, 1, "4400:0:0:1::");
test_in_addr_prefix_nth_one(AF_INET6, "4400::", 64, 2, "4400:0:0:2::");
test_in_addr_prefix_nth_one(AF_INET6, "4400::", 64, 0xbad, "4400:0:0:0bad::");
test_in_addr_prefix_nth_one(AF_INET6, "4400:0:0:ffff::", 64, 1, "4400:0:1::");
test_in_addr_prefix_nth_one(AF_INET6, "4400::", 56, ((uint64_t)1<<48) -1, "44ff:ffff:ffff:ff00::");
test_in_addr_prefix_nth_one(AF_INET6, "0000::", 8, 255, "ff00::");
test_in_addr_prefix_nth_one(AF_INET6, "0000::", 8, 256, NULL);
test_in_addr_prefix_nth_one(AF_INET6, "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff", 128, 1, NULL);
test_in_addr_prefix_nth_one(AF_INET6, "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff", 0, 1, NULL);
}
static void test_in_addr_to_string_one(int f, const char *addr) {
union in_addr_union ua;
_cleanup_free_ char *r = NULL;
assert_se(in_addr_from_string(f, addr, &ua) >= 0);
assert_se(in_addr_to_string(f, &ua, &r) >= 0);
printf("test_in_addr_to_string_one: %s == %s\n", addr, r);
assert_se(streq(addr, r));
}
static void test_in_addr_to_string(void) {
log_info("/* %s */", __func__);
test_in_addr_to_string_one(AF_INET, "192.168.0.1");
test_in_addr_to_string_one(AF_INET, "10.11.12.13");
test_in_addr_to_string_one(AF_INET6, "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff");
test_in_addr_to_string_one(AF_INET6, "::1");
test_in_addr_to_string_one(AF_INET6, "fe80::");
}
static void test_in_addr_ifindex_to_string_one(int f, const char *a, int ifindex, const char *b) {
_cleanup_free_ char *r = NULL;
union in_addr_union ua, uuaa;
int ff, ifindex2;
assert_se(in_addr_from_string(f, a, &ua) >= 0);
assert_se(in_addr_ifindex_to_string(f, &ua, ifindex, &r) >= 0);
printf("test_in_addr_ifindex_to_string_one: %s == %s\n", b, r);
assert_se(streq(b, r));
assert_se(in_addr_ifindex_from_string_auto(b, &ff, &uuaa, &ifindex2) >= 0);
assert_se(ff == f);
assert_se(in_addr_equal(f, &ua, &uuaa));
assert_se(ifindex2 == ifindex || ifindex2 == 0);
}
static void test_in_addr_ifindex_to_string(void) {
log_info("/* %s */", __func__);
test_in_addr_ifindex_to_string_one(AF_INET, "192.168.0.1", 7, "192.168.0.1");
test_in_addr_ifindex_to_string_one(AF_INET, "10.11.12.13", 9, "10.11.12.13");
test_in_addr_ifindex_to_string_one(AF_INET6, "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff", 10, "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff");
test_in_addr_ifindex_to_string_one(AF_INET6, "::1", 11, "::1");
test_in_addr_ifindex_to_string_one(AF_INET6, "fe80::", 12, "fe80::%12");
test_in_addr_ifindex_to_string_one(AF_INET6, "fe80::", 0, "fe80::");
test_in_addr_ifindex_to_string_one(AF_INET6, "fe80::14", 12, "fe80::14%12");
test_in_addr_ifindex_to_string_one(AF_INET6, "fe80::15", -7, "fe80::15");
test_in_addr_ifindex_to_string_one(AF_INET6, "fe80::16", LOOPBACK_IFINDEX, "fe80::16%1");
}
static void test_in_addr_ifindex_from_string_auto(void) {
int family, ifindex;
union in_addr_union ua;
log_info("/* %s */", __func__);
/* Most in_addr_ifindex_from_string_auto() invocations have already been tested above, but let's test some more */
assert_se(in_addr_ifindex_from_string_auto("fe80::17", &family, &ua, &ifindex) >= 0);
assert_se(family == AF_INET6);
assert_se(ifindex == 0);
assert_se(in_addr_ifindex_from_string_auto("fe80::18%19", &family, &ua, &ifindex) >= 0);
assert_se(family == AF_INET6);
assert_se(ifindex == 19);
assert_se(in_addr_ifindex_from_string_auto("fe80::18%lo", &family, &ua, &ifindex) >= 0);
assert_se(family == AF_INET6);
assert_se(ifindex == LOOPBACK_IFINDEX);
assert_se(in_addr_ifindex_from_string_auto("fe80::19%thisinterfacecantexist", &family, &ua, &ifindex) == -ENODEV);
}
static void test_in_addr_ifindex_name_from_string_auto_one(const char *a, const char *expected) {
int family, ifindex;
union in_addr_union ua;
_cleanup_free_ char *server_name = NULL;
assert_se(in_addr_ifindex_name_from_string_auto(a, &family, &ua, &ifindex, &server_name) >= 0);
assert_se(streq_ptr(server_name, expected));
}
static void test_in_addr_ifindex_name_from_string_auto(void) {
log_info("/* %s */", __func__);
test_in_addr_ifindex_name_from_string_auto_one("192.168.0.1", NULL);
test_in_addr_ifindex_name_from_string_auto_one("192.168.0.1#test.com", "test.com");
test_in_addr_ifindex_name_from_string_auto_one("fe80::18%19", NULL);
test_in_addr_ifindex_name_from_string_auto_one("fe80::18%19#another.test.com", "another.test.com");
}
static void test_in_addr_port_ifindex_name_from_string_auto_one(const char *str, int family, uint16_t port, int ifindex, const char *server_name) {
_cleanup_free_ char *name = NULL, *x = NULL;
union in_addr_union a;
uint16_t p;
int f, i;
assert_se(in_addr_port_ifindex_name_from_string_auto(str, &f, &a, &p, &i, &name) >= 0);
assert_se(family == f);
assert_se(port == p);
assert_se(ifindex == i);
assert_se(streq_ptr(server_name, name));
assert_se(in_addr_port_ifindex_name_to_string(f, &a, p, i, name, &x) >= 0);
assert_se(streq(str, x));
}
static void test_in_addr_port_ifindex_name_from_string_auto(void) {
log_info("/* %s */", __func__);
test_in_addr_port_ifindex_name_from_string_auto_one("192.168.0.1", AF_INET, 0, 0, NULL);
test_in_addr_port_ifindex_name_from_string_auto_one("192.168.0.1#test.com", AF_INET, 0, 0, "test.com");
test_in_addr_port_ifindex_name_from_string_auto_one("192.168.0.1:53", AF_INET, 53, 0, NULL);
test_in_addr_port_ifindex_name_from_string_auto_one("192.168.0.1:53#example.com", AF_INET, 53, 0, "example.com");
test_in_addr_port_ifindex_name_from_string_auto_one("fe80::18", AF_INET6, 0, 0, NULL);
test_in_addr_port_ifindex_name_from_string_auto_one("fe80::18#hoge.com", AF_INET6, 0, 0, "hoge.com");
test_in_addr_port_ifindex_name_from_string_auto_one("fe80::18%19", AF_INET6, 0, 19, NULL);
test_in_addr_port_ifindex_name_from_string_auto_one("[fe80::18]:53", AF_INET6, 53, 0, NULL);
test_in_addr_port_ifindex_name_from_string_auto_one("fe80::18%19#hoge.com", AF_INET6, 0, 19, "hoge.com");
test_in_addr_port_ifindex_name_from_string_auto_one("[fe80::18]:53#hoge.com", AF_INET6, 53, 0, "hoge.com");
test_in_addr_port_ifindex_name_from_string_auto_one("[fe80::18]:53%19", AF_INET6, 53, 19, NULL);
test_in_addr_port_ifindex_name_from_string_auto_one("[fe80::18]:53%19#hoge.com", AF_INET6, 53, 19, "hoge.com");
}
static void test_sockaddr_equal(void) {
union sockaddr_union a = {
.in.sin_family = AF_INET,
@ -759,16 +507,6 @@ int main(int argc, char *argv[]) {
test_socket_print_unix();
test_in_addr_is_null();
test_in_addr_prefix_intersect();
test_in_addr_prefix_next();
test_in_addr_prefix_nth();
test_in_addr_to_string();
test_in_addr_ifindex_to_string();
test_in_addr_ifindex_from_string_auto();
test_in_addr_ifindex_name_from_string_auto();
test_in_addr_port_ifindex_name_from_string_auto();
test_sockaddr_equal();
test_sockaddr_un_len();