Compare commits
No commits in common. "ad161cd6bb02053b7b6fd389e85eefae8533a627" and "836540070dcc1325f6159df40dc64f3cdf95e8e3" have entirely different histories.
ad161cd6bb
...
836540070d
|
@ -271,27 +271,27 @@
|
||||||
|
|
||||||
<varlistentry>
|
<varlistentry>
|
||||||
<term><varname>DNSStubListenerExtra=</varname></term>
|
<term><varname>DNSStubListenerExtra=</varname></term>
|
||||||
<listitem><para>Takes an IPv4 or IPv6 address to listen on. The address may be optionally
|
<listitem><para>Takes an IPv4 or IPv6 address to listen on. The address may optionally be prefixed by <literal>:</literal> and
|
||||||
prefixed with a protocol name (<literal>udp</literal> or <literal>tcp</literal>) separated with
|
a protocol name (<literal>udp</literal> or <literal>tcp</literal>). When an IPv6 address is specified with a port number, then the
|
||||||
<literal>:</literal>. If the protocol is not specified, the service will listen on both UDP and
|
address must be in the square brackets. This option can be specified multiple times. If an empty string is assigned, then the all
|
||||||
TCP. It may be also optionally suffixed by a numeric port number with separator
|
previous assignments are cleared. It may also be optionally suffixed by a numeric port number with separator <literal>:</literal>.
|
||||||
<literal>:</literal>. When an IPv6 address is specified with a port number, then the address
|
If the protocol is not specified, the service will listen on both <literal>UDP</literal> and <literal>TCP</literal>. If the port is not
|
||||||
must be in the square brackets. If the port is not specified, then the service uses port 53.
|
specified, then the service takes port as 53. This option may be used multiple times. Note that this is independent of the
|
||||||
Note that this is independent of the primary DNS stub configured with
|
primary DNS stub configured with <varname>DNSStubListener=</varname>, and only configures <emphasis>additional</emphasis>
|
||||||
<varname>DNSStubListener=</varname>, and only configures <emphasis>additional</emphasis>
|
sockets to listen on. Defaults to unset.</para>
|
||||||
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>Examples:
|
<para>If the string in the format <literal>udp</literal>:[<replaceable>x</replaceable>]:<replaceable>y</replaceable>,
|
||||||
<programlisting>DNSStubListenerExtra=192.168.10.10
|
it is read as protocol <literal>udp</literal> and IPv6 address x on a port y.</para>
|
||||||
DNSStubListenerExtra=2001:db8:0:f102::10
|
|
||||||
DNSStubListenerExtra=192.168.10.11:9953
|
<para>If the string in the format [<replaceable>x</replaceable>]:<replaceable>y</replaceable>, it is read as both protocol
|
||||||
DNSStubListenerExtra=[2001:db8:0:f102::11]:9953
|
<literal>udp</literal> and <literal>tcp</literal>, IPv6 address x on a port y.</para>
|
||||||
DNSStubListenerExtra=tcp:192.168.10.12
|
|
||||||
DNSStubListenerExtra=udp:2001:db8:0:f102::12
|
<para>If the string in the format <replaceable>x</replaceable>, it is read as protocol both <literal>udp</literal> and
|
||||||
DNSStubListenerExtra=tcp:192.168.10.13:9953
|
<literal>tcp</literal>, IPv6/IPv4 address x on a port 53.</para>
|
||||||
DNSStubListenerExtra=udp:[2001:db8:0:f102::13]:9953</programlisting>
|
|
||||||
</para></listitem>
|
<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>
|
||||||
</varlistentry>
|
</varlistentry>
|
||||||
|
|
||||||
<varlistentry>
|
<varlistentry>
|
||||||
|
|
|
@ -402,6 +402,46 @@ int in_addr_prefix_to_string(int family, const union in_addr_union *u, unsigned
|
||||||
return 0;
|
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) {
|
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;
|
_cleanup_free_ char *ip_str = NULL, *x = NULL;
|
||||||
int r;
|
int r;
|
||||||
|
|
|
@ -41,13 +41,8 @@ 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_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_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_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);
|
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(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);
|
int in_addr_from_string_auto(const char *s, int *ret_family, union in_addr_union *ret);
|
||||||
|
|
||||||
|
|
|
@ -63,10 +63,6 @@ struct sockaddr_vm {
|
||||||
#define IP_TRANSPARENT 19
|
#define IP_TRANSPARENT 19
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef IPV6_FREEBIND
|
|
||||||
#define IPV6_FREEBIND 78
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* linux/sockios.h */
|
/* linux/sockios.h */
|
||||||
#ifndef SIOCGSKNS
|
#ifndef SIOCGSKNS
|
||||||
#define SIOCGSKNS 0x894C
|
#define SIOCGSKNS 0x894C
|
||||||
|
|
|
@ -205,35 +205,6 @@ struct cmsghdr* cmsg_find(struct msghdr *mh, int level, int type, socklen_t leng
|
||||||
strnlen(_sa->sun_path, sizeof(_sa->sun_path))+1); \
|
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 socket_ioctl_fd(void);
|
||||||
|
|
||||||
int sockaddr_un_set_path(struct sockaddr_un *ret, const char *path);
|
int sockaddr_un_set_path(struct sockaddr_un *ret, const char *path);
|
||||||
|
|
|
@ -484,6 +484,7 @@ _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) {
|
_public_ int sd_bus_error_set_errnofv(sd_bus_error *e, int error, const char *format, va_list ap) {
|
||||||
PROTECT_ERRNO;
|
PROTECT_ERRNO;
|
||||||
|
int r;
|
||||||
|
|
||||||
if (error < 0)
|
if (error < 0)
|
||||||
error = -error;
|
error = -error;
|
||||||
|
@ -514,30 +515,34 @@ _public_ int sd_bus_error_set_errnofv(sd_bus_error *e, int error, const char *fo
|
||||||
}
|
}
|
||||||
|
|
||||||
if (format) {
|
if (format) {
|
||||||
_cleanup_free_ char *m = NULL;
|
char *m;
|
||||||
|
|
||||||
/* Then, let's try to fill in the supplied message */
|
/* Then, let's try to fill in the supplied message */
|
||||||
|
|
||||||
errno = error; /* Make sure that %m resolves to the specified error */
|
errno = error; /* Make sure that %m resolves to the specified error */
|
||||||
if (vasprintf(&m, format, ap) < 0)
|
r = vasprintf(&m, format, ap);
|
||||||
goto fail;
|
if (r >= 0) {
|
||||||
|
|
||||||
if (e->_need_free <= 0) {
|
if (e->_need_free <= 0) {
|
||||||
char *t;
|
char *t;
|
||||||
|
|
||||||
t = strdup(e->name);
|
t = strdup(e->name);
|
||||||
if (!t)
|
if (t) {
|
||||||
goto fail;
|
e->_need_free = 1;
|
||||||
|
e->name = t;
|
||||||
|
e->message = m;
|
||||||
|
return -error;
|
||||||
|
}
|
||||||
|
|
||||||
e->_need_free = 1;
|
free(m);
|
||||||
e->name = t;
|
} else {
|
||||||
|
free((char*) e->message);
|
||||||
|
e->message = m;
|
||||||
|
return -error;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
e->message = TAKE_PTR(m);
|
|
||||||
return -error;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fail:
|
|
||||||
/* If that didn't work, use strerror() for the message */
|
/* If that didn't work, use strerror() for the message */
|
||||||
bus_error_strerror(e, error);
|
bus_error_strerror(e, error);
|
||||||
return -error;
|
return -error;
|
||||||
|
|
|
@ -213,87 +213,12 @@ static void test_errno_mapping_custom(void) {
|
||||||
assert_se(sd_bus_error_add_map(test_errors_bad2) == -EINVAL);
|
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[]) {
|
int main(int argc, char *argv[]) {
|
||||||
dump_mapping_table();
|
dump_mapping_table();
|
||||||
|
|
||||||
test_error();
|
test_error();
|
||||||
test_errno_mapping_standard();
|
test_errno_mapping_standard();
|
||||||
test_errno_mapping_custom();
|
test_errno_mapping_custom();
|
||||||
test_sd_bus_error_set_errnof();
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,15 +30,20 @@ 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);
|
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) {
|
static void dns_stub_listener_extra_hash_func(const DNSStubListenerExtra *a, struct siphash *state) {
|
||||||
|
unsigned port;
|
||||||
|
|
||||||
assert(a);
|
assert(a);
|
||||||
|
|
||||||
siphash24_compress(&a->mode, sizeof(a->mode), state);
|
siphash24_compress(&a->mode, sizeof(a->mode), state);
|
||||||
siphash24_compress(&a->family, sizeof(a->family), state);
|
siphash24_compress(&socket_address_family(&a->address), sizeof(a->address.type), state);
|
||||||
siphash24_compress(&a->address, FAMILY_ADDRESS_SIZE(a->family), state);
|
siphash24_compress(&a->address, FAMILY_ADDRESS_SIZE(socket_address_family(&a->address)), state);
|
||||||
siphash24_compress(&a->port, sizeof(a->port), state);
|
|
||||||
|
(void) sockaddr_port(&a->address.sockaddr.sa, &port);
|
||||||
|
siphash24_compress(&port, sizeof(port), state);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int dns_stub_listener_extra_compare_func(const DNSStubListenerExtra *a, const DNSStubListenerExtra *b) {
|
static int dns_stub_listener_extra_compare_func(const DNSStubListenerExtra *a, const DNSStubListenerExtra *b) {
|
||||||
|
unsigned p, q;
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
assert(a);
|
assert(a);
|
||||||
|
@ -48,15 +53,18 @@ static int dns_stub_listener_extra_compare_func(const DNSStubListenerExtra *a, c
|
||||||
if (r != 0)
|
if (r != 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
r = CMP(a->family, b->family);
|
r = CMP(socket_address_family(&a->address), socket_address_family(&b->address));
|
||||||
if (r != 0)
|
if (r != 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
r = memcmp(&a->address, &b->address, FAMILY_ADDRESS_SIZE(a->family));
|
r = memcmp(&a->address, &b->address, FAMILY_ADDRESS_SIZE(socket_address_family(&a->address)));
|
||||||
if (r != 0)
|
if (r != 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
return CMP(a->port, b->port);
|
(void) sockaddr_port(&a->address.sockaddr.sa, &p);
|
||||||
|
(void) sockaddr_port(&b->address.sockaddr.sa, &q);
|
||||||
|
|
||||||
|
return CMP(p, q);
|
||||||
}
|
}
|
||||||
|
|
||||||
DEFINE_PRIVATE_HASH_OPS_WITH_KEY_DESTRUCTOR(
|
DEFINE_PRIVATE_HASH_OPS_WITH_KEY_DESTRUCTOR(
|
||||||
|
@ -64,7 +72,7 @@ DEFINE_PRIVATE_HASH_OPS_WITH_KEY_DESTRUCTOR(
|
||||||
DNSStubListenerExtra,
|
DNSStubListenerExtra,
|
||||||
dns_stub_listener_extra_hash_func,
|
dns_stub_listener_extra_hash_func,
|
||||||
dns_stub_listener_extra_compare_func,
|
dns_stub_listener_extra_compare_func,
|
||||||
dns_stub_listener_extra_free);
|
free);
|
||||||
|
|
||||||
static int manager_add_dns_server_by_string(Manager *m, DnsServerType type, const char *word) {
|
static int manager_add_dns_server_by_string(Manager *m, DnsServerType type, const char *word) {
|
||||||
_cleanup_free_ char *server_name = NULL;
|
_cleanup_free_ char *server_name = NULL;
|
||||||
|
@ -436,8 +444,10 @@ int config_parse_dns_stub_listener_extra(
|
||||||
void *data,
|
void *data,
|
||||||
void *userdata) {
|
void *userdata) {
|
||||||
|
|
||||||
_cleanup_free_ DNSStubListenerExtra *stub = NULL;
|
_cleanup_free_ DNSStubListenerExtra *udp = NULL, *tcp = NULL;
|
||||||
|
_cleanup_free_ char *word = NULL;
|
||||||
Manager *m = userdata;
|
Manager *m = userdata;
|
||||||
|
bool both = false;
|
||||||
const char *p;
|
const char *p;
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
|
@ -451,41 +461,78 @@ int config_parse_dns_stub_listener_extra(
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
r = dns_stub_listener_extra_new(&stub);
|
p = rvalue;
|
||||||
if (r < 0)
|
r = extract_first_word(&p, &word, ":", 0);
|
||||||
|
if (r == -ENOMEM)
|
||||||
return log_oom();
|
return log_oom();
|
||||||
|
if (r <= 0) {
|
||||||
|
log_syntax(unit, LOG_WARNING, filename, line, r,
|
||||||
|
"Invalid DNSStubListenExtra='%s', ignoring assignment", rvalue);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
p = startswith(rvalue, "udp:");
|
/* First look for udp/tcp. If not specified then turn both TCP and UDP */
|
||||||
if (p)
|
if (!STR_IN_SET(word, "tcp", "udp")) {
|
||||||
stub->mode = DNS_STUB_LISTENER_UDP;
|
both = true;
|
||||||
else {
|
p = rvalue;
|
||||||
p = startswith(rvalue, "tcp:");
|
}
|
||||||
if (p)
|
|
||||||
stub->mode = DNS_STUB_LISTENER_TCP;
|
if (streq(word, "tcp") || both) {
|
||||||
else {
|
r = dns_stub_extra_new(&tcp);
|
||||||
stub->mode = DNS_STUB_LISTENER_YES;
|
if (r < 0)
|
||||||
p = rvalue;
|
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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
r = in_addr_port_from_string_auto(p, &stub->family, &stub->address, &stub->port);
|
if (udp) {
|
||||||
if (r < 0) {
|
r = socket_addr_port_from_string_auto(p, 53, &udp->address);
|
||||||
log_syntax(unit, LOG_WARNING, filename, line, r,
|
if (r < 0) {
|
||||||
"Failed to parse address in %s=%s, ignoring assignment: %m",
|
log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse address in DNSStubListenExtra='%s', ignoring", rvalue);
|
||||||
lvalue, rvalue);
|
return 0;
|
||||||
return 0;
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
r = ordered_set_ensure_put(&m->dns_extra_stub_listeners, &dns_stub_listener_extra_hash_ops, stub);
|
if (tcp) {
|
||||||
if (r == -ENOMEM)
|
r = ordered_set_ensure_put(&m->dns_extra_stub_listeners, &dns_stub_listener_extra_hash_ops, tcp);
|
||||||
return log_oom();
|
if (r < 0) {
|
||||||
if (r < 0) {
|
if (r == -ENOMEM)
|
||||||
log_syntax(unit, LOG_WARNING, filename, line, r,
|
return log_oom();
|
||||||
"Failed to store %s=%s, ignoring assignment: %m", lvalue, rvalue);
|
|
||||||
return 0;
|
log_warning_errno(r, "Failed to store TCP DNSStubListenExtra='%s', ignoring assignment: %m", rvalue);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
TAKE_PTR(stub);
|
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);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TAKE_PTR(tcp);
|
||||||
|
TAKE_PTR(udp);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,9 +7,9 @@ typedef enum DnsStubListenerMode DnsStubListenerMode;
|
||||||
|
|
||||||
enum DnsStubListenerMode {
|
enum DnsStubListenerMode {
|
||||||
DNS_STUB_LISTENER_NO,
|
DNS_STUB_LISTENER_NO,
|
||||||
DNS_STUB_LISTENER_UDP = 1 << 0,
|
DNS_STUB_LISTENER_UDP,
|
||||||
DNS_STUB_LISTENER_TCP = 1 << 1,
|
DNS_STUB_LISTENER_TCP,
|
||||||
DNS_STUB_LISTENER_YES = DNS_STUB_LISTENER_UDP | DNS_STUB_LISTENER_TCP,
|
DNS_STUB_LISTENER_YES,
|
||||||
_DNS_STUB_LISTENER_MODE_MAX,
|
_DNS_STUB_LISTENER_MODE_MAX,
|
||||||
_DNS_STUB_LISTENER_MODE_INVALID = -1
|
_DNS_STUB_LISTENER_MODE_INVALID = -1
|
||||||
};
|
};
|
||||||
|
|
|
@ -66,7 +66,6 @@ struct DnsPacket {
|
||||||
DnsResourceRecord *opt;
|
DnsResourceRecord *opt;
|
||||||
|
|
||||||
/* Packet reception metadata */
|
/* Packet reception metadata */
|
||||||
int fd; /* Used by UDP extra DNS stub listners */
|
|
||||||
int ifindex;
|
int ifindex;
|
||||||
int family, ipproto;
|
int family, ipproto;
|
||||||
union in_addr_union sender, destination;
|
union in_addr_union sender, destination;
|
||||||
|
|
|
@ -1,11 +1,8 @@
|
||||||
/* SPDX-License-Identifier: LGPL-2.1+ */
|
/* SPDX-License-Identifier: LGPL-2.1+ */
|
||||||
|
|
||||||
#include <net/if_arp.h>
|
|
||||||
|
|
||||||
#include "errno-util.h"
|
#include "errno-util.h"
|
||||||
#include "fd-util.h"
|
#include "fd-util.h"
|
||||||
#include "missing_network.h"
|
#include "missing_network.h"
|
||||||
#include "missing_socket.h"
|
|
||||||
#include "resolved-dns-stub.h"
|
#include "resolved-dns-stub.h"
|
||||||
#include "socket-netlink.h"
|
#include "socket-netlink.h"
|
||||||
#include "socket-util.h"
|
#include "socket-util.h"
|
||||||
|
@ -14,28 +11,25 @@
|
||||||
* IP and UDP header sizes */
|
* IP and UDP header sizes */
|
||||||
#define ADVERTISE_DATAGRAM_SIZE_MAX (65536U-14U-20U-8U)
|
#define ADVERTISE_DATAGRAM_SIZE_MAX (65536U-14U-20U-8U)
|
||||||
|
|
||||||
int dns_stub_listener_extra_new(DNSStubListenerExtra **ret) {
|
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) {
|
||||||
DNSStubListenerExtra *l;
|
DNSStubListenerExtra *l;
|
||||||
|
|
||||||
l = new0(DNSStubListenerExtra, 1);
|
l = new(DNSStubListenerExtra, 1);
|
||||||
if (!l)
|
if (!l)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
|
*l = (DNSStubListenerExtra) {
|
||||||
|
.fd = -1,
|
||||||
|
};
|
||||||
|
|
||||||
*ret = TAKE_PTR(l);
|
*ret = TAKE_PTR(l);
|
||||||
|
|
||||||
return 0;
|
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(
|
static int dns_stub_make_reply_packet(
|
||||||
DnsPacket **p,
|
DnsPacket **p,
|
||||||
size_t max_size,
|
size_t max_size,
|
||||||
|
@ -161,11 +155,17 @@ static int dns_stub_send(Manager *m, DnsStream *s, DnsPacket *p, DnsPacket *repl
|
||||||
if (s)
|
if (s)
|
||||||
r = dns_stream_write_packet(s, reply);
|
r = dns_stream_write_packet(s, reply);
|
||||||
else {
|
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
|
/* 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
|
* 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. */
|
* thus pick 127.0.0.1 rather than 127.0.0.53. */
|
||||||
|
|
||||||
r = manager_send(m, p->fd, p->ifindex, p->family, &p->sender, p->sender_port, &p->destination, reply);
|
r = manager_send(m, fd, LOOPBACK_IFINDEX, p->family, &p->sender, p->sender_port, &p->destination, reply);
|
||||||
}
|
}
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return log_debug_errno(r, "Failed to send reply packet: %m");
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void dns_stub_process_query(Manager *m, DnsStream *s, DnsPacket *p, bool is_extra) {
|
static void dns_stub_process_query(Manager *m, DnsStream *s, DnsPacket *p) {
|
||||||
_cleanup_(dns_query_freep) DnsQuery *q = NULL;
|
_cleanup_(dns_query_freep) DnsQuery *q = NULL;
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
|
@ -302,9 +302,8 @@ static void dns_stub_process_query(Manager *m, DnsStream *s, DnsPacket *p, bool
|
||||||
assert(p);
|
assert(p);
|
||||||
assert(p->protocol == DNS_PROTOCOL_DNS);
|
assert(p->protocol == DNS_PROTOCOL_DNS);
|
||||||
|
|
||||||
if (!is_extra &&
|
if (in_addr_is_localhost(p->family, &p->sender) <= 0 ||
|
||||||
(in_addr_is_localhost(p->family, &p->sender) <= 0 ||
|
in_addr_is_localhost(p->family, &p->destination) <= 0) {
|
||||||
in_addr_is_localhost(p->family, &p->destination) <= 0)) {
|
|
||||||
log_error("Got packet on unexpected IP range, refusing.");
|
log_error("Got packet on unexpected IP range, refusing.");
|
||||||
dns_stub_send_failure(m, s, p, DNS_RCODE_SERVFAIL, false);
|
dns_stub_send_failure(m, s, p, DNS_RCODE_SERVFAIL, false);
|
||||||
return;
|
return;
|
||||||
|
@ -385,8 +384,9 @@ static void dns_stub_process_query(Manager *m, DnsStream *s, DnsPacket *p, bool
|
||||||
TAKE_PTR(q);
|
TAKE_PTR(q);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int on_dns_stub_packet_internal(sd_event_source *s, int fd, uint32_t revents, Manager *m, bool is_extra) {
|
static int on_dns_stub_packet(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
|
||||||
_cleanup_(dns_packet_unrefp) DnsPacket *p = NULL;
|
_cleanup_(dns_packet_unrefp) DnsPacket *p = NULL;
|
||||||
|
Manager *m = userdata;
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
r = manager_recv(m, fd, DNS_PROTOCOL_DNS, &p);
|
r = manager_recv(m, fd, DNS_PROTOCOL_DNS, &p);
|
||||||
|
@ -396,50 +396,27 @@ static int on_dns_stub_packet_internal(sd_event_source *s, int fd, uint32_t reve
|
||||||
if (dns_packet_validate_query(p) > 0) {
|
if (dns_packet_validate_query(p) > 0) {
|
||||||
log_debug("Got DNS stub UDP query packet for id %u", DNS_PACKET_ID(p));
|
log_debug("Got DNS stub UDP query packet for id %u", DNS_PACKET_ID(p));
|
||||||
|
|
||||||
dns_stub_process_query(m, NULL, p, is_extra);
|
dns_stub_process_query(m, NULL, p);
|
||||||
} else
|
} else
|
||||||
log_debug("Invalid DNS stub UDP packet, ignoring.");
|
log_debug("Invalid DNS stub UDP packet, ignoring.");
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int on_dns_stub_packet(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
|
static int set_dns_stub_common_socket_options(int fd) {
|
||||||
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;
|
int r;
|
||||||
|
|
||||||
assert(fd >= 0);
|
assert(fd >= 0);
|
||||||
assert(IN_SET(family, AF_INET, AF_INET6));
|
|
||||||
|
|
||||||
r = setsockopt_int(fd, SOL_SOCKET, SO_REUSEADDR, true);
|
r = setsockopt_int(fd, SOL_SOCKET, SO_REUSEADDR, true);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
if (family == AF_INET) {
|
r = setsockopt_int(fd, IPPROTO_IP, IP_PKTINFO, true);
|
||||||
r = setsockopt_int(fd, IPPROTO_IP, IP_PKTINFO, true);
|
if (r < 0)
|
||||||
if (r < 0)
|
return r;
|
||||||
return r;
|
|
||||||
|
|
||||||
r = setsockopt_int(fd, IPPROTO_IP, IP_RECVTTL, true);
|
return 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) {
|
static int manager_dns_stub_udp_fd(Manager *m) {
|
||||||
|
@ -451,14 +428,14 @@ static int manager_dns_stub_udp_fd(Manager *m) {
|
||||||
_cleanup_close_ int fd = -1;
|
_cleanup_close_ int fd = -1;
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
if (m->dns_stub_udp_event_source)
|
if (m->dns_stub_udp_fd >= 0)
|
||||||
return sd_event_source_get_io_fd(m->dns_stub_udp_event_source);
|
return m->dns_stub_udp_fd;
|
||||||
|
|
||||||
fd = socket(AF_INET, SOCK_DGRAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0);
|
fd = socket(AF_INET, SOCK_DGRAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0);
|
||||||
if (fd < 0)
|
if (fd < 0)
|
||||||
return -errno;
|
return -errno;
|
||||||
|
|
||||||
r = set_dns_stub_common_socket_options(fd, AF_INET);
|
r = set_dns_stub_common_socket_options(fd);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
|
@ -474,84 +451,70 @@ static int manager_dns_stub_udp_fd(Manager *m) {
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
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");
|
(void) sd_event_source_set_description(m->dns_stub_udp_event_source, "dns-stub-udp");
|
||||||
|
|
||||||
return TAKE_FD(fd);
|
return m->dns_stub_udp_fd = TAKE_FD(fd);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int manager_dns_stub_udp_fd_extra(Manager *m, DNSStubListenerExtra *l) {
|
static int manager_dns_stub_udp_fd_extra(Manager *m, DNSStubListenerExtra *l) {
|
||||||
_cleanup_free_ char *pretty = NULL;
|
_cleanup_free_ char *pretty = NULL;
|
||||||
_cleanup_close_ int fd = -1;
|
_cleanup_close_ int fd = -1;
|
||||||
union sockaddr_union sa;
|
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
if (l->udp_event_source)
|
if (l->fd >= 0)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (l->family == AF_INET)
|
fd = socket(socket_address_family(&l->address), SOCK_DGRAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0);
|
||||||
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) {
|
if (fd < 0) {
|
||||||
r = -errno;
|
r = -errno;
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (l->family == AF_INET) {
|
r = setsockopt_int(fd, IPPROTO_IP, IP_FREEBIND, true);
|
||||||
r = setsockopt_int(fd, IPPROTO_IP, IP_FREEBIND, true);
|
|
||||||
if (r < 0)
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
|
|
||||||
r = set_dns_stub_common_socket_options(fd, l->family);
|
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
||||||
if (bind(fd, &sa.sa, SOCKADDR_LEN(sa)) < 0) {
|
r = set_dns_stub_common_socket_options(fd);
|
||||||
|
if (r < 0)
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
if (bind(fd, &l->address.sockaddr.sa, l->address.size) < 0) {
|
||||||
r = -errno;
|
r = -errno;
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
r = sd_event_add_io(m->event, &l->udp_event_source, fd, EPOLLIN, on_dns_stub_packet_extra, m);
|
r = sd_event_add_io(m->event, &l->dns_stub_extra_event_source, fd, EPOLLIN, on_dns_stub_packet, m);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
||||||
r = sd_event_source_set_io_fd_own(l->udp_event_source, true);
|
(void) sd_event_source_set_description(l->dns_stub_extra_event_source, "dns-stub-udp-extra");
|
||||||
if (r < 0)
|
|
||||||
goto fail;
|
|
||||||
|
|
||||||
(void) sd_event_source_set_description(l->udp_event_source, "dns-stub-udp-extra");
|
l->fd = TAKE_FD(fd);
|
||||||
|
|
||||||
if (DEBUG_LOGGING) {
|
if (DEBUG_LOGGING) {
|
||||||
(void) in_addr_port_to_string(l->family, &l->address, l->port, &pretty);
|
(void) sockaddr_pretty(&l->address.sockaddr.sa, FAMILY_ADDRESS_SIZE(l->address.sockaddr.sa.sa_family), true, true, &pretty);
|
||||||
log_debug("Listening on UDP socket %s.", strnull(pretty));
|
log_debug("Listening on UDP socket %s.", strnull(pretty));
|
||||||
}
|
}
|
||||||
|
|
||||||
return TAKE_FD(fd);
|
return 0;
|
||||||
|
|
||||||
fail:
|
fail:
|
||||||
assert(r < 0);
|
(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);
|
if (r == -EADDRINUSE)
|
||||||
if (r == -EADDRINUSE)
|
return log_warning_errno(r,
|
||||||
return log_warning_errno(r, "Another process is already listening on UDP socket %s: %m", strnull(pretty));
|
"Another process is already listening on UDP socket %s.\n"
|
||||||
return log_warning_errno(r, "Failed to listen on UDP socket %s: %m", strnull(pretty));
|
"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));
|
||||||
}
|
}
|
||||||
|
|
||||||
static int on_dns_stub_stream_packet_internal(DnsStream *s, bool is_extra) {
|
static int on_dns_stub_stream_packet(DnsStream *s) {
|
||||||
_cleanup_(dns_packet_unrefp) DnsPacket *p = NULL;
|
_cleanup_(dns_packet_unrefp) DnsPacket *p = NULL;
|
||||||
|
|
||||||
assert(s);
|
assert(s);
|
||||||
|
@ -562,23 +525,16 @@ static int on_dns_stub_stream_packet_internal(DnsStream *s, bool is_extra) {
|
||||||
if (dns_packet_validate_query(p) > 0) {
|
if (dns_packet_validate_query(p) > 0) {
|
||||||
log_debug("Got DNS stub TCP query packet for id %u", DNS_PACKET_ID(p));
|
log_debug("Got DNS stub TCP query packet for id %u", DNS_PACKET_ID(p));
|
||||||
|
|
||||||
dns_stub_process_query(s->manager, s, p, is_extra);
|
dns_stub_process_query(s->manager, s, p);
|
||||||
} else
|
} else
|
||||||
log_debug("Invalid DNS stub TCP packet, ignoring.");
|
log_debug("Invalid DNS stub TCP packet, ignoring.");
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int on_dns_stub_stream_packet(DnsStream *s) {
|
static int on_dns_stub_stream(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
|
||||||
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;
|
DnsStream *stream;
|
||||||
|
Manager *m = userdata;
|
||||||
int cfd, r;
|
int cfd, r;
|
||||||
|
|
||||||
cfd = accept4(fd, NULL, NULL, SOCK_NONBLOCK|SOCK_CLOEXEC);
|
cfd = accept4(fd, NULL, NULL, SOCK_NONBLOCK|SOCK_CLOEXEC);
|
||||||
|
@ -595,7 +551,7 @@ static int on_dns_stub_stream_internal(sd_event_source *s, int fd, uint32_t reve
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
stream->on_packet = is_extra ? on_dns_stub_stream_packet_extra : on_dns_stub_stream_packet;
|
stream->on_packet = on_dns_stub_stream_packet;
|
||||||
stream->complete = dns_stub_stream_complete;
|
stream->complete = dns_stub_stream_complete;
|
||||||
|
|
||||||
/* We let the reference to the stream dangle here, it will be dropped later by the complete callback. */
|
/* We let the reference to the stream dangle here, it will be dropped later by the complete callback. */
|
||||||
|
@ -603,14 +559,6 @@ static int on_dns_stub_stream_internal(sd_event_source *s, int fd, uint32_t reve
|
||||||
return 0;
|
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) {
|
static int manager_dns_stub_tcp_fd(Manager *m) {
|
||||||
union sockaddr_union sa = {
|
union sockaddr_union sa = {
|
||||||
.in.sin_family = AF_INET,
|
.in.sin_family = AF_INET,
|
||||||
|
@ -620,14 +568,14 @@ static int manager_dns_stub_tcp_fd(Manager *m) {
|
||||||
_cleanup_close_ int fd = -1;
|
_cleanup_close_ int fd = -1;
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
if (m->dns_stub_tcp_event_source)
|
if (m->dns_stub_tcp_fd >= 0)
|
||||||
return sd_event_source_get_io_fd(m->dns_stub_tcp_event_source);
|
return m->dns_stub_tcp_fd;
|
||||||
|
|
||||||
fd = socket(AF_INET, SOCK_STREAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0);
|
fd = socket(AF_INET, SOCK_STREAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0);
|
||||||
if (fd < 0)
|
if (fd < 0)
|
||||||
return -errno;
|
return -errno;
|
||||||
|
|
||||||
r = set_dns_stub_common_socket_options(fd, AF_INET);
|
r = set_dns_stub_common_socket_options(fd);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
|
@ -650,58 +598,38 @@ static int manager_dns_stub_tcp_fd(Manager *m) {
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
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");
|
(void) sd_event_source_set_description(m->dns_stub_tcp_event_source, "dns-stub-tcp");
|
||||||
|
|
||||||
return TAKE_FD(fd);
|
return m->dns_stub_tcp_fd = TAKE_FD(fd);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int manager_dns_stub_tcp_fd_extra(Manager *m, DNSStubListenerExtra *l) {
|
static int manager_dns_stub_tcp_fd_extra(Manager *m, DNSStubListenerExtra *l) {
|
||||||
_cleanup_free_ char *pretty = NULL;
|
_cleanup_free_ char *pretty = NULL;
|
||||||
_cleanup_close_ int fd = -1;
|
_cleanup_close_ int fd = -1;
|
||||||
union sockaddr_union sa;
|
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
if (l->tcp_event_source)
|
if (l->fd >= 0)
|
||||||
return sd_event_source_get_io_fd(l->tcp_event_source);;
|
return 0;
|
||||||
|
|
||||||
if (l->family == AF_INET)
|
fd = socket(socket_address_family(&l->address), SOCK_STREAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0);
|
||||||
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) {
|
if (fd < 0) {
|
||||||
r = -errno;
|
r = -errno;
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
r = set_dns_stub_common_socket_options(fd, l->family);
|
r = set_dns_stub_common_socket_options(fd);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
||||||
/* Do not set IP_TTL for extra DNS stub listners, as the address may not be local and in that
|
r = setsockopt_int(fd, IPPROTO_IP, IP_TTL, 1);
|
||||||
* 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)
|
if (r < 0)
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
||||||
if (bind(fd, &sa.sa, SOCKADDR_LEN(sa)) < 0) {
|
r = setsockopt_int(fd, IPPROTO_IP, IP_FREEBIND, true);
|
||||||
|
if (r < 0)
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
if (bind(fd, &l->address.sockaddr.sa, l->address.size) < 0) {
|
||||||
r = -errno;
|
r = -errno;
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
@ -711,29 +639,35 @@ static int manager_dns_stub_tcp_fd_extra(Manager *m, DNSStubListenerExtra *l) {
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
r = sd_event_add_io(m->event, &l->tcp_event_source, fd, EPOLLIN, on_dns_stub_stream_extra, m);
|
r = sd_event_add_io(m->event, &l->dns_stub_extra_event_source, fd, EPOLLIN, on_dns_stub_packet, m);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
||||||
r = sd_event_source_set_io_fd_own(l->tcp_event_source, true);
|
(void) sd_event_source_set_description(l->dns_stub_extra_event_source, "dns-stub-tcp-extra");
|
||||||
if (r < 0)
|
|
||||||
goto fail;
|
|
||||||
|
|
||||||
(void) sd_event_source_set_description(l->tcp_event_source, "dns-stub-tcp-extra");
|
l->fd = TAKE_FD(fd);
|
||||||
|
|
||||||
if (DEBUG_LOGGING) {
|
if (DEBUG_LOGGING) {
|
||||||
(void) in_addr_port_to_string(l->family, &l->address, l->port, &pretty);
|
(void) sockaddr_pretty(&l->address.sockaddr.sa, FAMILY_ADDRESS_SIZE(l->address.sockaddr.sa.sa_family), true, true, &pretty);
|
||||||
log_debug("Listening on TCP socket %s.", strnull(pretty));
|
log_debug("Listening on TCP socket %s.", strnull(pretty));
|
||||||
}
|
}
|
||||||
|
|
||||||
return TAKE_FD(fd);
|
return 0;
|
||||||
|
|
||||||
fail:
|
fail:
|
||||||
assert(r < 0);
|
(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);
|
if (r == -EADDRINUSE)
|
||||||
if (r == -EADDRINUSE)
|
return log_warning_errno(r,
|
||||||
return log_warning_errno(r, "Another process is already listening on TCP socket %s: %m", strnull(pretty));
|
"Another process is already listening on TCP socket %s.\n"
|
||||||
return log_warning_errno(r, "Failed to listen on TCP socket %s: %m", strnull(pretty));
|
"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));
|
||||||
}
|
}
|
||||||
|
|
||||||
int manager_dns_stub_start(Manager *m) {
|
int manager_dns_stub_start(Manager *m) {
|
||||||
|
@ -750,11 +684,11 @@ int manager_dns_stub_start(Manager *m) {
|
||||||
m->dns_stub_listener_mode == DNS_STUB_LISTENER_TCP ? "TCP" :
|
m->dns_stub_listener_mode == DNS_STUB_LISTENER_TCP ? "TCP" :
|
||||||
"UDP/TCP");
|
"UDP/TCP");
|
||||||
|
|
||||||
if (FLAGS_SET(m->dns_stub_listener_mode, DNS_STUB_LISTENER_UDP))
|
if (IN_SET(m->dns_stub_listener_mode, DNS_STUB_LISTENER_YES, DNS_STUB_LISTENER_UDP))
|
||||||
r = manager_dns_stub_udp_fd(m);
|
r = manager_dns_stub_udp_fd(m);
|
||||||
|
|
||||||
if (r >= 0 &&
|
if (r >= 0 &&
|
||||||
FLAGS_SET(m->dns_stub_listener_mode, DNS_STUB_LISTENER_TCP)) {
|
IN_SET(m->dns_stub_listener_mode, DNS_STUB_LISTENER_YES, DNS_STUB_LISTENER_TCP)) {
|
||||||
t = "TCP";
|
t = "TCP";
|
||||||
r = manager_dns_stub_tcp_fd(m);
|
r = manager_dns_stub_tcp_fd(m);
|
||||||
}
|
}
|
||||||
|
@ -776,14 +710,16 @@ int manager_dns_stub_start(Manager *m) {
|
||||||
DNSStubListenerExtra *l;
|
DNSStubListenerExtra *l;
|
||||||
Iterator i;
|
Iterator i;
|
||||||
|
|
||||||
log_debug("Creating extra stub listeners.");
|
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");
|
||||||
|
|
||||||
ORDERED_SET_FOREACH(l, m->dns_extra_stub_listeners, i) {
|
ORDERED_SET_FOREACH(l, m->dns_extra_stub_listeners, i)
|
||||||
if (FLAGS_SET(l->mode, DNS_STUB_LISTENER_UDP))
|
if (l->mode == DNS_STUB_LISTENER_UDP)
|
||||||
(void) manager_dns_stub_udp_fd_extra(m, l);
|
(void) manager_dns_stub_udp_fd_extra(m, l);
|
||||||
if (FLAGS_SET(l->mode, DNS_STUB_LISTENER_TCP))
|
else
|
||||||
(void) manager_dns_stub_tcp_fd_extra(m, l);
|
(void) manager_dns_stub_tcp_fd_extra(m, l);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -794,4 +730,19 @@ 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_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_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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,8 +3,8 @@
|
||||||
|
|
||||||
#include "resolved-manager.h"
|
#include "resolved-manager.h"
|
||||||
|
|
||||||
int dns_stub_listener_extra_new(DNSStubListenerExtra **ret);
|
int dns_stub_extra_new(DNSStubListenerExtra **ret);
|
||||||
DNSStubListenerExtra *dns_stub_listener_extra_free(DNSStubListenerExtra *p);
|
|
||||||
|
|
||||||
void manager_dns_stub_stop(Manager *m);
|
void manager_dns_stub_stop(Manager *m);
|
||||||
|
void manager_dns_stub_stop_extra(Manager *m);
|
||||||
int manager_dns_stub_start(Manager *m);
|
int manager_dns_stub_start(Manager *m);
|
||||||
|
|
|
@ -578,6 +578,8 @@ int manager_new(Manager **ret) {
|
||||||
.llmnr_ipv6_tcp_fd = -1,
|
.llmnr_ipv6_tcp_fd = -1,
|
||||||
.mdns_ipv4_fd = -1,
|
.mdns_ipv4_fd = -1,
|
||||||
.mdns_ipv6_fd = -1,
|
.mdns_ipv6_fd = -1,
|
||||||
|
.dns_stub_udp_fd = -1,
|
||||||
|
.dns_stub_tcp_fd = -1,
|
||||||
.hostname_fd = -1,
|
.hostname_fd = -1,
|
||||||
|
|
||||||
.llmnr_support = DEFAULT_LLMNR_MODE,
|
.llmnr_support = DEFAULT_LLMNR_MODE,
|
||||||
|
@ -699,6 +701,7 @@ Manager *manager_free(Manager *m) {
|
||||||
|
|
||||||
hashmap_free(m->links);
|
hashmap_free(m->links);
|
||||||
hashmap_free(m->dns_transactions);
|
hashmap_free(m->dns_transactions);
|
||||||
|
ordered_set_free(m->dns_extra_stub_listeners);
|
||||||
|
|
||||||
sd_event_source_unref(m->network_event_source);
|
sd_event_source_unref(m->network_event_source);
|
||||||
sd_network_monitor_unref(m->network_monitor);
|
sd_network_monitor_unref(m->network_monitor);
|
||||||
|
@ -711,7 +714,7 @@ Manager *manager_free(Manager *m) {
|
||||||
manager_dns_stub_stop(m);
|
manager_dns_stub_stop(m);
|
||||||
manager_varlink_done(m);
|
manager_varlink_done(m);
|
||||||
|
|
||||||
ordered_set_free(m->dns_extra_stub_listeners);
|
manager_dns_stub_stop_extra(m);
|
||||||
|
|
||||||
bus_verify_polkit_async_registry_free(m->polkit_registry);
|
bus_verify_polkit_async_registry_free(m->polkit_registry);
|
||||||
|
|
||||||
|
@ -790,7 +793,6 @@ int manager_recv(Manager *m, int fd, DnsProtocol protocol, DnsPacket **ret) {
|
||||||
|
|
||||||
p->size = (size_t) l;
|
p->size = (size_t) l;
|
||||||
|
|
||||||
p->fd = fd;
|
|
||||||
p->family = sa.sa.sa_family;
|
p->family = sa.sa.sa_family;
|
||||||
p->ipproto = IPPROTO_UDP;
|
p->ipproto = IPPROTO_UDP;
|
||||||
if (p->family == AF_INET) {
|
if (p->family == AF_INET) {
|
||||||
|
|
|
@ -32,14 +32,11 @@ typedef struct EtcHosts {
|
||||||
} EtcHosts;
|
} EtcHosts;
|
||||||
|
|
||||||
typedef struct DNSStubListenerExtra {
|
typedef struct DNSStubListenerExtra {
|
||||||
|
int fd;
|
||||||
|
|
||||||
DnsStubListenerMode mode;
|
DnsStubListenerMode mode;
|
||||||
|
SocketAddress address;
|
||||||
int family;
|
sd_event_source *dns_stub_extra_event_source;
|
||||||
union in_addr_union address;
|
|
||||||
uint16_t port;
|
|
||||||
|
|
||||||
sd_event_source *udp_event_source;
|
|
||||||
sd_event_source *tcp_event_source;
|
|
||||||
} DNSStubListenerExtra;
|
} DNSStubListenerExtra;
|
||||||
|
|
||||||
struct Manager {
|
struct Manager {
|
||||||
|
@ -144,9 +141,12 @@ struct Manager {
|
||||||
dev_t etc_hosts_dev;
|
dev_t etc_hosts_dev;
|
||||||
bool read_etc_hosts;
|
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;
|
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_udp_event_source;
|
||||||
sd_event_source *dns_stub_tcp_event_source;
|
sd_event_source *dns_stub_tcp_event_source;
|
||||||
|
|
||||||
|
|
|
@ -572,11 +572,9 @@ int pty_forward_set_priority(PTYForward *f, int64_t priority) {
|
||||||
int r;
|
int r;
|
||||||
assert(f);
|
assert(f);
|
||||||
|
|
||||||
if (f->stdin_event_source) {
|
r = sd_event_source_set_priority(f->stdin_event_source, priority);
|
||||||
r = sd_event_source_set_priority(f->stdin_event_source, priority);
|
if (r < 0)
|
||||||
if (r < 0)
|
return r;
|
||||||
return r;
|
|
||||||
}
|
|
||||||
|
|
||||||
r = sd_event_source_set_priority(f->stdout_event_source, priority);
|
r = sd_event_source_set_priority(f->stdout_event_source, priority);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
|
|
|
@ -235,6 +235,33 @@ int socket_address_parse_and_warn(SocketAddress *a, const char *s) {
|
||||||
return 0;
|
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) {
|
int socket_address_parse_netlink(SocketAddress *a, const char *s) {
|
||||||
_cleanup_free_ char *word = NULL;
|
_cleanup_free_ char *word = NULL;
|
||||||
unsigned group = 0;
|
unsigned group = 0;
|
||||||
|
@ -455,36 +482,6 @@ int in_addr_port_ifindex_name_from_string_auto(
|
||||||
return r;
|
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) {
|
struct in_addr_full *in_addr_full_free(struct in_addr_full *a) {
|
||||||
if (!a)
|
if (!a)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
|
@ -16,6 +16,7 @@ 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(SocketAddress *a, const char *s);
|
||||||
int socket_address_parse_and_warn(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_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(const SocketAddress *a, const char *s, int type);
|
||||||
bool socket_address_is_netlink(const SocketAddress *a, const char *s);
|
bool socket_address_is_netlink(const SocketAddress *a, const char *s);
|
||||||
|
@ -33,7 +34,6 @@ 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) {
|
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);
|
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 {
|
struct in_addr_full {
|
||||||
int family;
|
int family;
|
||||||
|
|
|
@ -2212,7 +2212,9 @@ int varlink_server_listen_fd(VarlinkServer *s, int fd) {
|
||||||
};
|
};
|
||||||
|
|
||||||
if (s->event) {
|
if (s->event) {
|
||||||
r = sd_event_add_io(s->event, &ss->event_source, fd, EPOLLIN, connect_callback, ss);
|
_cleanup_(sd_event_source_unrefp) sd_event_source *es = NULL;
|
||||||
|
|
||||||
|
r = sd_event_add_io(s->event, &es, fd, EPOLLIN, connect_callback, ss);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
|
|
|
@ -94,12 +94,6 @@ enum {
|
||||||
#define SD_BUS_ERROR_INTERACTIVE_AUTHORIZATION_REQUIRED \
|
#define SD_BUS_ERROR_INTERACTIVE_AUTHORIZATION_REQUIRED \
|
||||||
"org.freedesktop.DBus.Error.InteractiveAuthorizationRequired"
|
"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;
|
_SD_END_DECLARATIONS;
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -34,6 +34,12 @@ _SD_BEGIN_DECLARATIONS;
|
||||||
#define SD_BUS_DEFAULT_USER ((sd_bus *) 2)
|
#define SD_BUS_DEFAULT_USER ((sd_bus *) 2)
|
||||||
#define SD_BUS_DEFAULT_SYSTEM ((sd_bus *) 3)
|
#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 */
|
/* Types */
|
||||||
|
|
||||||
typedef struct sd_bus sd_bus;
|
typedef struct sd_bus sd_bus;
|
||||||
|
|
|
@ -177,163 +177,10 @@ static void test_in_addr_random_prefix(void) {
|
||||||
str = mfree(str);
|
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[]) {
|
int main(int argc, char *argv[]) {
|
||||||
test_in_addr_prefix_from_string();
|
test_in_addr_prefix_from_string();
|
||||||
test_in_addr_random_prefix();
|
test_in_addr_random_prefix();
|
||||||
test_in_addr_prefix_to_string();
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
/* SPDX-License-Identifier: LGPL-2.1+ */
|
/* SPDX-License-Identifier: LGPL-2.1+ */
|
||||||
|
|
||||||
#include "alloc-util.h"
|
#include "alloc-util.h"
|
||||||
#include "missing_network.h"
|
|
||||||
#include "tests.h"
|
#include "tests.h"
|
||||||
#include "socket-netlink.h"
|
#include "socket-netlink.h"
|
||||||
#include "string-util.h"
|
#include "string-util.h"
|
||||||
|
@ -214,136 +213,39 @@ static void test_socket_address_is_netlink(void) {
|
||||||
assert_se(!socket_address_is_netlink(&a, "route 1"));
|
assert_se(!socket_address_is_netlink(&a, "route 1"));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void test_in_addr_ifindex_to_string_one(int f, const char *a, int ifindex, const char *b) {
|
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 *r = NULL;
|
_cleanup_free_ char *out = NULL;
|
||||||
union in_addr_union ua, uuaa;
|
SocketAddress a;
|
||||||
int ff, ifindex2;
|
int r;
|
||||||
|
|
||||||
assert_se(in_addr_from_string(f, a, &ua) >= 0);
|
r = socket_addr_port_from_string_auto(in, port, &a);
|
||||||
assert_se(in_addr_ifindex_to_string(f, &ua, ifindex, &r) >= 0);
|
if (r >= 0)
|
||||||
printf("test_in_addr_ifindex_to_string_one: %s == %s\n", b, r);
|
assert_se(sockaddr_pretty(&a.sockaddr.sa, a.size, false, true, &out) >= 0);
|
||||||
assert_se(streq(b, r));
|
|
||||||
|
|
||||||
assert_se(in_addr_ifindex_from_string_auto(b, &ff, &uuaa, &ifindex2) >= 0);
|
log_info("\"%s\" → %s → \"%s\" (expect \"%s\")", in,
|
||||||
assert_se(ff == f);
|
r >= 0 ? "✓" : "✗", empty_to_dash(out), r >= 0 ? expected ?: in : "-");
|
||||||
assert_se(in_addr_equal(f, &ua, &uuaa));
|
assert_se(r == ret);
|
||||||
assert_se(ifindex2 == ifindex || ifindex2 == 0);
|
if (r >= 0) {
|
||||||
|
assert_se(a.sockaddr.sa.sa_family == family);
|
||||||
|
assert_se(streq(out, expected ?: in));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void test_in_addr_ifindex_to_string(void) {
|
static void test_socket_addr_port_from_string_auto(void) {
|
||||||
log_info("/* %s */", __func__);
|
log_info("/* %s */", __func__);
|
||||||
|
|
||||||
test_in_addr_ifindex_to_string_one(AF_INET, "192.168.0.1", 7, "192.168.0.1");
|
test_socket_addr_port_from_string_auto_one("junk", 51, -EINVAL, 0, NULL);
|
||||||
test_in_addr_ifindex_to_string_one(AF_INET, "10.11.12.13", 9, "10.11.12.13");
|
test_socket_addr_port_from_string_auto_one("192.168.1.1", 53, 0, AF_INET, "192.168.1.1:53");
|
||||||
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_socket_addr_port_from_string_auto_one(".168.1.1", 53, -EINVAL, 0, NULL);
|
||||||
test_in_addr_ifindex_to_string_one(AF_INET6, "::1", 11, "::1");
|
test_socket_addr_port_from_string_auto_one("989.168.1.1", 53, -EINVAL, 0, NULL);
|
||||||
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) {
|
test_socket_addr_port_from_string_auto_one("[::1]", 53, -EINVAL, 0, NULL);
|
||||||
int family, ifindex;
|
test_socket_addr_port_from_string_auto_one("[::1]8888", 53, -EINVAL, 0, NULL);
|
||||||
union in_addr_union ua;
|
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");
|
||||||
log_info("/* %s */", __func__);
|
test_socket_addr_port_from_string_auto_one("[::1]:0", 53, -EINVAL, 0, NULL);
|
||||||
/* Most in_addr_ifindex_from_string_auto() invocations have already been tested above, but let's test some more */
|
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);
|
||||||
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[]) {
|
int main(int argc, char *argv[]) {
|
||||||
|
@ -355,12 +257,7 @@ int main(int argc, char *argv[]) {
|
||||||
test_socket_address_get_path();
|
test_socket_address_get_path();
|
||||||
test_socket_address_is();
|
test_socket_address_is();
|
||||||
test_socket_address_is_netlink();
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,7 +15,9 @@
|
||||||
#include "io-util.h"
|
#include "io-util.h"
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
#include "macro.h"
|
#include "macro.h"
|
||||||
|
#include "missing_network.h"
|
||||||
#include "process-util.h"
|
#include "process-util.h"
|
||||||
|
#include "socket-netlink.h"
|
||||||
#include "socket-util.h"
|
#include "socket-util.h"
|
||||||
#include "string-util.h"
|
#include "string-util.h"
|
||||||
#include "tests.h"
|
#include "tests.h"
|
||||||
|
@ -82,6 +84,256 @@ static void test_socket_print_unix(void) {
|
||||||
test_socket_print_unix_one("\0\a\b\n\255", 6, "@\\a\\b\\n\\255\\000");
|
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) {
|
static void test_sockaddr_equal(void) {
|
||||||
union sockaddr_union a = {
|
union sockaddr_union a = {
|
||||||
.in.sin_family = AF_INET,
|
.in.sin_family = AF_INET,
|
||||||
|
@ -507,6 +759,16 @@ int main(int argc, char *argv[]) {
|
||||||
|
|
||||||
test_socket_print_unix();
|
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_equal();
|
||||||
|
|
||||||
test_sockaddr_un_len();
|
test_sockaddr_un_len();
|
||||||
|
|
Loading…
Reference in New Issue