Merge pull request #10460 from yuwata/setsockopt_int-more

tree-wide: use setsockopt_int() more
This commit is contained in:
Lennart Poettering 2018-10-19 10:12:00 +02:00 committed by GitHub
commit 6ab1853953
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 281 additions and 412 deletions

View file

@ -839,10 +839,11 @@ int fd_inc_sndbuf(int fd, size_t n) {
/* If we have the privileges we will ignore the kernel limit. */ /* If we have the privileges we will ignore the kernel limit. */
value = (int) n; if (setsockopt_int(fd, SOL_SOCKET, SO_SNDBUF, n) < 0) {
if (setsockopt(fd, SOL_SOCKET, SO_SNDBUF, &value, sizeof(value)) < 0) r = setsockopt_int(fd, SOL_SOCKET, SO_SNDBUFFORCE, n);
if (setsockopt(fd, SOL_SOCKET, SO_SNDBUFFORCE, &value, sizeof(value)) < 0) if (r < 0)
return -errno; return r;
}
return 1; return 1;
} }
@ -857,10 +858,12 @@ int fd_inc_rcvbuf(int fd, size_t n) {
/* If we have the privileges we will ignore the kernel limit. */ /* If we have the privileges we will ignore the kernel limit. */
value = (int) n; if (setsockopt_int(fd, SOL_SOCKET, SO_RCVBUF, n) < 0) {
if (setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &value, sizeof(value)) < 0) r = setsockopt_int(fd, SOL_SOCKET, SO_RCVBUFFORCE, n);
if (setsockopt(fd, SOL_SOCKET, SO_RCVBUFFORCE, &value, sizeof(value)) < 0) if (r < 0)
return -errno; return r;
}
return 1; return 1;
} }

View file

@ -1020,27 +1020,27 @@ static void socket_apply_socket_options(Socket *s, int fd) {
} }
if (s->keep_alive_time > 0) { if (s->keep_alive_time > 0) {
int value = s->keep_alive_time / USEC_PER_SEC; r = setsockopt_int(fd, SOL_TCP, TCP_KEEPIDLE, s->keep_alive_time / USEC_PER_SEC);
if (setsockopt(fd, SOL_TCP, TCP_KEEPIDLE, &value, sizeof(value)) < 0) if (r < 0)
log_unit_warning_errno(UNIT(s), errno, "TCP_KEEPIDLE failed: %m"); log_unit_warning_errno(UNIT(s), r, "TCP_KEEPIDLE failed: %m");
} }
if (s->keep_alive_interval > 0) { if (s->keep_alive_interval > 0) {
int value = s->keep_alive_interval / USEC_PER_SEC; r = setsockopt_int(fd, SOL_TCP, TCP_KEEPINTVL, s->keep_alive_interval / USEC_PER_SEC);
if (setsockopt(fd, SOL_TCP, TCP_KEEPINTVL, &value, sizeof(value)) < 0) if (r < 0)
log_unit_warning_errno(UNIT(s), errno, "TCP_KEEPINTVL failed: %m"); log_unit_warning_errno(UNIT(s), r, "TCP_KEEPINTVL failed: %m");
} }
if (s->keep_alive_cnt > 0) { if (s->keep_alive_cnt > 0) {
int value = s->keep_alive_cnt; r = setsockopt_int(fd, SOL_TCP, TCP_KEEPCNT, s->keep_alive_cnt);
if (setsockopt(fd, SOL_TCP, TCP_KEEPCNT, &value, sizeof(value)) < 0) if (r < 0)
log_unit_warning_errno(UNIT(s), errno, "TCP_KEEPCNT failed: %m"); log_unit_warning_errno(UNIT(s), r, "TCP_KEEPCNT failed: %m");
} }
if (s->defer_accept > 0) { if (s->defer_accept > 0) {
int value = s->defer_accept / USEC_PER_SEC; r = setsockopt_int(fd, SOL_TCP, TCP_DEFER_ACCEPT, s->defer_accept / USEC_PER_SEC);
if (setsockopt(fd, SOL_TCP, TCP_DEFER_ACCEPT, &value, sizeof(value)) < 0) if (r < 0)
log_unit_warning_errno(UNIT(s), errno, "TCP_DEFER_ACCEPT failed: %m"); log_unit_warning_errno(UNIT(s), r, "TCP_DEFER_ACCEPT failed: %m");
} }
if (s->no_delay) { if (s->no_delay) {
@ -1073,48 +1073,53 @@ static void socket_apply_socket_options(Socket *s, int fd) {
log_unit_warning_errno(UNIT(s), r, "SO_PASSSEC failed: %m"); log_unit_warning_errno(UNIT(s), r, "SO_PASSSEC failed: %m");
} }
if (s->priority >= 0) if (s->priority >= 0) {
if (setsockopt(fd, SOL_SOCKET, SO_PRIORITY, &s->priority, sizeof(s->priority)) < 0) r = setsockopt_int(fd, SOL_SOCKET, SO_PRIORITY, s->priority);
log_unit_warning_errno(UNIT(s), errno, "SO_PRIORITY failed: %m"); if (r < 0)
log_unit_warning_errno(UNIT(s), r, "SO_PRIORITY failed: %m");
}
if (s->receive_buffer > 0) { if (s->receive_buffer > 0) {
int value = (int) s->receive_buffer;
/* We first try with SO_RCVBUFFORCE, in case we have the perms for that */ /* We first try with SO_RCVBUFFORCE, in case we have the perms for that */
if (setsockopt(fd, SOL_SOCKET, SO_RCVBUFFORCE, &value, sizeof(value)) < 0) if (setsockopt_int(fd, SOL_SOCKET, SO_RCVBUFFORCE, s->receive_buffer) < 0) {
if (setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &value, sizeof(value)) < 0) r = setsockopt_int(fd, SOL_SOCKET, SO_RCVBUF, s->receive_buffer);
log_unit_warning_errno(UNIT(s), errno, "SO_RCVBUF failed: %m"); if (r < 0)
log_unit_warning_errno(UNIT(s), r, "SO_RCVBUF failed: %m");
}
} }
if (s->send_buffer > 0) { if (s->send_buffer > 0) {
int value = (int) s->send_buffer; if (setsockopt_int(fd, SOL_SOCKET, SO_SNDBUFFORCE, s->send_buffer) < 0) {
if (setsockopt(fd, SOL_SOCKET, SO_SNDBUFFORCE, &value, sizeof(value)) < 0) r = setsockopt_int(fd, SOL_SOCKET, SO_SNDBUF, s->send_buffer);
if (setsockopt(fd, SOL_SOCKET, SO_SNDBUF, &value, sizeof(value)) < 0) if (r < 0)
log_unit_warning_errno(UNIT(s), errno, "SO_SNDBUF failed: %m"); log_unit_warning_errno(UNIT(s), r, "SO_SNDBUF failed: %m");
}
} }
if (s->mark >= 0) if (s->mark >= 0) {
if (setsockopt(fd, SOL_SOCKET, SO_MARK, &s->mark, sizeof(s->mark)) < 0) r = setsockopt_int(fd, SOL_SOCKET, SO_MARK, s->mark);
log_unit_warning_errno(UNIT(s), errno, "SO_MARK failed: %m"); if (r < 0)
log_unit_warning_errno(UNIT(s), r, "SO_MARK failed: %m");
}
if (s->ip_tos >= 0) if (s->ip_tos >= 0) {
if (setsockopt(fd, IPPROTO_IP, IP_TOS, &s->ip_tos, sizeof(s->ip_tos)) < 0) r = setsockopt_int(fd, IPPROTO_IP, IP_TOS, s->ip_tos);
log_unit_warning_errno(UNIT(s), errno, "IP_TOS failed: %m"); if (r < 0)
log_unit_warning_errno(UNIT(s), r, "IP_TOS failed: %m");
}
if (s->ip_ttl >= 0) { if (s->ip_ttl >= 0) {
int x; int x;
r = setsockopt(fd, IPPROTO_IP, IP_TTL, &s->ip_ttl, sizeof(s->ip_ttl)); r = setsockopt_int(fd, IPPROTO_IP, IP_TTL, s->ip_ttl);
if (socket_ipv6_is_supported()) if (socket_ipv6_is_supported())
x = setsockopt(fd, IPPROTO_IPV6, IPV6_UNICAST_HOPS, &s->ip_ttl, sizeof(s->ip_ttl)); x = setsockopt_int(fd, IPPROTO_IPV6, IPV6_UNICAST_HOPS, s->ip_ttl);
else { else
x = -1; x = -EAFNOSUPPORT;
errno = EAFNOSUPPORT;
}
if (r < 0 && x < 0) if (r < 0 && x < 0)
log_unit_warning_errno(UNIT(s), errno, "IP_TTL/IPV6_UNICAST_HOPS failed: %m"); log_unit_warning_errno(UNIT(s), r, "IP_TTL/IPV6_UNICAST_HOPS failed: %m");
} }
if (s->tcp_congestion) if (s->tcp_congestion)

View file

@ -149,15 +149,15 @@ int dhcp_network_bind_udp_socket(int ifindex, be32_t address, uint16_t port) {
}; };
_cleanup_close_ int s = -1; _cleanup_close_ int s = -1;
char ifname[IF_NAMESIZE] = ""; char ifname[IF_NAMESIZE] = "";
int r, tos = IPTOS_CLASS_CS6; int r;
s = socket(AF_INET, SOCK_DGRAM | SOCK_CLOEXEC | SOCK_NONBLOCK, 0); s = socket(AF_INET, SOCK_DGRAM | SOCK_CLOEXEC | SOCK_NONBLOCK, 0);
if (s < 0) if (s < 0)
return -errno; return -errno;
r = setsockopt(s, IPPROTO_IP, IP_TOS, &tos, sizeof(tos)); r = setsockopt_int(s, IPPROTO_IP, IP_TOS, IPTOS_CLASS_CS6);
if (r < 0) if (r < 0)
return -errno; return r;
r = setsockopt_int(s, SOL_SOCKET, SO_REUSEADDR, true); r = setsockopt_int(s, SOL_SOCKET, SO_REUSEADDR, true);
if (r < 0) if (r < 0)

View file

@ -33,7 +33,6 @@ static int icmp6_bind_router_message(const struct icmp6_filter *filter,
int index = mreq->ipv6mr_interface; int index = mreq->ipv6mr_interface;
_cleanup_close_ int s = -1; _cleanup_close_ int s = -1;
char ifname[IF_NAMESIZE] = ""; char ifname[IF_NAMESIZE] = "";
static const int hops = 255;
int r; int r;
s = socket(AF_INET6, SOCK_RAW | SOCK_CLOEXEC | SOCK_NONBLOCK, IPPROTO_ICMPV6); s = socket(AF_INET6, SOCK_RAW | SOCK_CLOEXEC | SOCK_NONBLOCK, IPPROTO_ICMPV6);
@ -52,21 +51,21 @@ static int icmp6_bind_router_message(const struct icmp6_filter *filter,
IPV6_PKTINFO socket option also applies for ICMPv6 multicast. IPV6_PKTINFO socket option also applies for ICMPv6 multicast.
Empirical experiments indicates otherwise and therefore an Empirical experiments indicates otherwise and therefore an
IPV6_MULTICAST_IF socket option is used here instead */ IPV6_MULTICAST_IF socket option is used here instead */
r = setsockopt(s, IPPROTO_IPV6, IPV6_MULTICAST_IF, &index, sizeof(index)); r = setsockopt_int(s, IPPROTO_IPV6, IPV6_MULTICAST_IF, index);
if (r < 0) if (r < 0)
return -errno; return r;
r = setsockopt_int(s, IPPROTO_IPV6, IPV6_MULTICAST_LOOP, false); r = setsockopt_int(s, IPPROTO_IPV6, IPV6_MULTICAST_LOOP, false);
if (r < 0) if (r < 0)
return r; return r;
r = setsockopt(s, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, &hops, sizeof(hops)); r = setsockopt_int(s, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, 255);
if (r < 0) if (r < 0)
return -errno; return r;
r = setsockopt(s, IPPROTO_IPV6, IPV6_UNICAST_HOPS, &hops, sizeof(hops)); r = setsockopt_int(s, IPPROTO_IPV6, IPV6_UNICAST_HOPS, 255);
if (r < 0) if (r < 0)
return -errno; return r;
r = setsockopt_int(s, SOL_IPV6, IPV6_RECVHOPLIMIT, true); r = setsockopt_int(s, SOL_IPV6, IPV6_RECVHOPLIMIT, true);
if (r < 0) if (r < 0)

View file

@ -88,14 +88,16 @@ int device_monitor_allow_unicast_sender(sd_device_monitor *m, sd_device_monitor
} }
_public_ int sd_device_monitor_set_receive_buffer_size(sd_device_monitor *m, size_t size) { _public_ int sd_device_monitor_set_receive_buffer_size(sd_device_monitor *m, size_t size) {
int n = (int) size; int r, n = (int) size;
assert_return(m, -EINVAL); assert_return(m, -EINVAL);
assert_return((size_t) n != size, -EINVAL); assert_return((size_t) n != size, -EINVAL);
if (setsockopt(m->sock, SOL_SOCKET, SO_RCVBUF, &n, sizeof(n)) < 0 && if (setsockopt_int(m->sock, SOL_SOCKET, SO_RCVBUF, n) < 0) {
setsockopt(m->sock, SOL_SOCKET, SO_RCVBUFFORCE, &n, sizeof(n)) < 0) r = setsockopt_int(m->sock, SOL_SOCKET, SO_RCVBUFFORCE, n);
return -errno; if (r < 0)
return r;
}
return 0; return 0;
} }

View file

@ -115,7 +115,7 @@ int manager_llmnr_ipv4_udp_fd(Manager *m) {
.in.sin_family = AF_INET, .in.sin_family = AF_INET,
.in.sin_port = htobe16(LLMNR_PORT), .in.sin_port = htobe16(LLMNR_PORT),
}; };
static const int pmtu = IP_PMTUDISC_DONT, ttl = 255; _cleanup_close_ int s = -1;
int r; int r;
assert(m); assert(m);
@ -123,90 +123,66 @@ int manager_llmnr_ipv4_udp_fd(Manager *m) {
if (m->llmnr_ipv4_udp_fd >= 0) if (m->llmnr_ipv4_udp_fd >= 0)
return m->llmnr_ipv4_udp_fd; return m->llmnr_ipv4_udp_fd;
m->llmnr_ipv4_udp_fd = socket(AF_INET, SOCK_DGRAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0); s = socket(AF_INET, SOCK_DGRAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0);
if (m->llmnr_ipv4_udp_fd < 0) if (s < 0)
return log_error_errno(errno, "LLMNR-IPv4(UDP): Failed to create socket: %m"); return log_error_errno(errno, "LLMNR-IPv4(UDP): Failed to create socket: %m");
/* RFC 4795, section 2.5 recommends setting the TTL of UDP packets to 255. */ /* RFC 4795, section 2.5 recommends setting the TTL of UDP packets to 255. */
r = setsockopt(m->llmnr_ipv4_udp_fd, IPPROTO_IP, IP_TTL, &ttl, sizeof(ttl)); r = setsockopt_int(s, IPPROTO_IP, IP_TTL, 255);
if (r < 0) { if (r < 0)
r = log_error_errno(errno, "LLMNR-IPv4(UDP): Failed to set IP_TTL: %m"); return log_error_errno(r, "LLMNR-IPv4(UDP): Failed to set IP_TTL: %m");
goto fail;
}
r = setsockopt(m->llmnr_ipv4_udp_fd, IPPROTO_IP, IP_MULTICAST_TTL, &ttl, sizeof(ttl)); r = setsockopt_int(s, IPPROTO_IP, IP_MULTICAST_TTL, 255);
if (r < 0) { if (r < 0)
r = log_error_errno(errno, "LLMNR-IPv4(UDP): Failed to set IP_MULTICAST_TTL: %m"); return log_error_errno(r, "LLMNR-IPv4(UDP): Failed to set IP_MULTICAST_TTL: %m");
goto fail;
}
r = setsockopt_int(m->llmnr_ipv4_udp_fd, IPPROTO_IP, IP_MULTICAST_LOOP, true); r = setsockopt_int(s, IPPROTO_IP, IP_MULTICAST_LOOP, true);
if (r < 0) { if (r < 0)
log_error_errno(r, "LLMNR-IPv4(UDP): Failed to set IP_MULTICAST_LOOP: %m"); return log_error_errno(r, "LLMNR-IPv4(UDP): Failed to set IP_MULTICAST_LOOP: %m");
goto fail;
}
r = setsockopt_int(m->llmnr_ipv4_udp_fd, IPPROTO_IP, IP_PKTINFO, true); r = setsockopt_int(s, IPPROTO_IP, IP_PKTINFO, true);
if (r < 0) { if (r < 0)
log_error_errno(r, "LLMNR-IPv4(UDP): Failed to set IP_PKTINFO: %m"); return log_error_errno(r, "LLMNR-IPv4(UDP): Failed to set IP_PKTINFO: %m");
goto fail;
}
r = setsockopt_int(m->llmnr_ipv4_udp_fd, IPPROTO_IP, IP_RECVTTL, true); r = setsockopt_int(s, IPPROTO_IP, IP_RECVTTL, true);
if (r < 0) { if (r < 0)
log_error_errno(r, "LLMNR-IPv4(UDP): Failed to set IP_RECVTTL: %m"); return log_error_errno(r, "LLMNR-IPv4(UDP): Failed to set IP_RECVTTL: %m");
goto fail;
}
/* Disable Don't-Fragment bit in the IP header */ /* Disable Don't-Fragment bit in the IP header */
r = setsockopt(m->llmnr_ipv4_udp_fd, IPPROTO_IP, IP_MTU_DISCOVER, &pmtu, sizeof(pmtu)); r = setsockopt_int(s, IPPROTO_IP, IP_MTU_DISCOVER, IP_PMTUDISC_DONT);
if (r < 0) { if (r < 0)
r = log_error_errno(errno, "LLMNR-IPv4(UDP): Failed to set IP_MTU_DISCOVER: %m"); return log_error_errno(r, "LLMNR-IPv4(UDP): Failed to set IP_MTU_DISCOVER: %m");
goto fail;
}
/* first try to bind without SO_REUSEADDR to detect another LLMNR responder */ /* first try to bind without SO_REUSEADDR to detect another LLMNR responder */
r = bind(m->llmnr_ipv4_udp_fd, &sa.sa, sizeof(sa.in)); r = bind(s, &sa.sa, sizeof(sa.in));
if (r < 0) { if (r < 0) {
if (errno != EADDRINUSE) { if (errno != EADDRINUSE)
r = log_error_errno(errno, "LLMNR-IPv4(UDP): Failed to bind socket: %m"); return log_error_errno(errno, "LLMNR-IPv4(UDP): Failed to bind socket: %m");
goto fail;
}
log_warning("LLMNR-IPv4(UDP): There appears to be another LLMNR responder running, or previously systemd-resolved crashed with some outstanding transfers."); log_warning("LLMNR-IPv4(UDP): There appears to be another LLMNR responder running, or previously systemd-resolved crashed with some outstanding transfers.");
/* try again with SO_REUSEADDR */ /* try again with SO_REUSEADDR */
r = setsockopt_int(m->llmnr_ipv4_udp_fd, SOL_SOCKET, SO_REUSEADDR, true); r = setsockopt_int(s, SOL_SOCKET, SO_REUSEADDR, true);
if (r < 0) { if (r < 0)
log_error_errno(r, "LLMNR-IPv4(UDP): Failed to set SO_REUSEADDR: %m"); return log_error_errno(r, "LLMNR-IPv4(UDP): Failed to set SO_REUSEADDR: %m");
goto fail;
}
r = bind(m->llmnr_ipv4_udp_fd, &sa.sa, sizeof(sa.in)); r = bind(s, &sa.sa, sizeof(sa.in));
if (r < 0) { if (r < 0)
r = log_error_errno(errno, "LLMNR-IPv4(UDP): Failed to bind socket: %m"); return log_error_errno(errno, "LLMNR-IPv4(UDP): Failed to bind socket: %m");
goto fail;
}
} else { } else {
/* enable SO_REUSEADDR for the case that the user really wants multiple LLMNR responders */ /* enable SO_REUSEADDR for the case that the user really wants multiple LLMNR responders */
r = setsockopt_int(m->llmnr_ipv4_udp_fd, SOL_SOCKET, SO_REUSEADDR, true); r = setsockopt_int(s, SOL_SOCKET, SO_REUSEADDR, true);
if (r < 0) { if (r < 0)
log_error_errno(r, "LLMNR-IPv4(UDP): Failed to set SO_REUSEADDR: %m"); return log_error_errno(r, "LLMNR-IPv4(UDP): Failed to set SO_REUSEADDR: %m");
goto fail;
}
} }
r = sd_event_add_io(m->event, &m->llmnr_ipv4_udp_event_source, m->llmnr_ipv4_udp_fd, EPOLLIN, on_llmnr_packet, m); r = sd_event_add_io(m->event, &m->llmnr_ipv4_udp_event_source, s, EPOLLIN, on_llmnr_packet, m);
if (r < 0) if (r < 0)
goto fail; return log_error_errno(r, "LLMNR-IPv4(UDP): Failed to create event source: %m");
(void) sd_event_source_set_description(m->llmnr_ipv4_udp_event_source, "llmnr-ipv4-udp"); (void) sd_event_source_set_description(m->llmnr_ipv4_udp_event_source, "llmnr-ipv4-udp");
return m->llmnr_ipv4_udp_fd; return m->llmnr_ipv4_udp_fd = TAKE_FD(s);
fail:
m->llmnr_ipv4_udp_fd = safe_close(m->llmnr_ipv4_udp_fd);
return r;
} }
int manager_llmnr_ipv6_udp_fd(Manager *m) { int manager_llmnr_ipv6_udp_fd(Manager *m) {
@ -214,7 +190,7 @@ int manager_llmnr_ipv6_udp_fd(Manager *m) {
.in6.sin6_family = AF_INET6, .in6.sin6_family = AF_INET6,
.in6.sin6_port = htobe16(LLMNR_PORT), .in6.sin6_port = htobe16(LLMNR_PORT),
}; };
static const int ttl = 255; _cleanup_close_ int s = -1;
int r; int r;
assert(m); assert(m);
@ -222,89 +198,65 @@ int manager_llmnr_ipv6_udp_fd(Manager *m) {
if (m->llmnr_ipv6_udp_fd >= 0) if (m->llmnr_ipv6_udp_fd >= 0)
return m->llmnr_ipv6_udp_fd; return m->llmnr_ipv6_udp_fd;
m->llmnr_ipv6_udp_fd = socket(AF_INET6, SOCK_DGRAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0); s = socket(AF_INET6, SOCK_DGRAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0);
if (m->llmnr_ipv6_udp_fd < 0) if (s < 0)
return log_error_errno(errno, "LLMNR-IPv6(UDP): Failed to create socket: %m"); return log_error_errno(errno, "LLMNR-IPv6(UDP): Failed to create socket: %m");
r = setsockopt(m->llmnr_ipv6_udp_fd, IPPROTO_IPV6, IPV6_UNICAST_HOPS, &ttl, sizeof(ttl)); r = setsockopt_int(s, IPPROTO_IPV6, IPV6_UNICAST_HOPS, 255);
if (r < 0) { if (r < 0)
r = log_error_errno(errno, "LLMNR-IPv6(UDP): Failed to set IPV6_UNICAST_HOPS: %m"); return log_error_errno(r, "LLMNR-IPv6(UDP): Failed to set IPV6_UNICAST_HOPS: %m");
goto fail;
}
/* RFC 4795, section 2.5 recommends setting the TTL of UDP packets to 255. */ /* RFC 4795, section 2.5 recommends setting the TTL of UDP packets to 255. */
r = setsockopt(m->llmnr_ipv6_udp_fd, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, &ttl, sizeof(ttl)); r = setsockopt_int(s, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, 255);
if (r < 0) { if (r < 0)
r = log_error_errno(errno, "LLMNR-IPv6(UDP): Failed to set IPV6_MULTICAST_HOPS: %m"); return log_error_errno(r, "LLMNR-IPv6(UDP): Failed to set IPV6_MULTICAST_HOPS: %m");
goto fail;
}
r = setsockopt_int(m->llmnr_ipv6_udp_fd, IPPROTO_IPV6, IPV6_MULTICAST_LOOP, true); r = setsockopt_int(s, IPPROTO_IPV6, IPV6_MULTICAST_LOOP, true);
if (r < 0) { if (r < 0)
log_error_errno(r, "LLMNR-IPv6(UDP): Failed to set IPV6_MULTICAST_LOOP: %m"); return log_error_errno(r, "LLMNR-IPv6(UDP): Failed to set IPV6_MULTICAST_LOOP: %m");
goto fail;
}
r = setsockopt_int(m->llmnr_ipv6_udp_fd, IPPROTO_IPV6, IPV6_V6ONLY, true); r = setsockopt_int(s, IPPROTO_IPV6, IPV6_V6ONLY, true);
if (r < 0) { if (r < 0)
log_error_errno(r, "LLMNR-IPv6(UDP): Failed to set IPV6_V6ONLY: %m"); return log_error_errno(r, "LLMNR-IPv6(UDP): Failed to set IPV6_V6ONLY: %m");
goto fail;
}
r = setsockopt_int(m->llmnr_ipv6_udp_fd, IPPROTO_IPV6, IPV6_RECVPKTINFO, true); r = setsockopt_int(s, IPPROTO_IPV6, IPV6_RECVPKTINFO, true);
if (r < 0) { if (r < 0)
log_error_errno(r, "LLMNR-IPv6(UDP): Failed to set IPV6_RECVPKTINFO: %m"); return log_error_errno(r, "LLMNR-IPv6(UDP): Failed to set IPV6_RECVPKTINFO: %m");
goto fail;
}
r = setsockopt_int(m->llmnr_ipv6_udp_fd, IPPROTO_IPV6, IPV6_RECVHOPLIMIT, true); r = setsockopt_int(s, IPPROTO_IPV6, IPV6_RECVHOPLIMIT, true);
if (r < 0) { if (r < 0)
log_error_errno(r, "LLMNR-IPv6(UDP): Failed to set IPV6_RECVHOPLIMIT: %m"); return log_error_errno(r, "LLMNR-IPv6(UDP): Failed to set IPV6_RECVHOPLIMIT: %m");
goto fail;
}
/* first try to bind without SO_REUSEADDR to detect another LLMNR responder */ /* first try to bind without SO_REUSEADDR to detect another LLMNR responder */
r = bind(m->llmnr_ipv6_udp_fd, &sa.sa, sizeof(sa.in6)); r = bind(s, &sa.sa, sizeof(sa.in6));
if (r < 0) { if (r < 0) {
if (errno != EADDRINUSE) { if (errno != EADDRINUSE)
r = log_error_errno(errno, "LLMNR-IPv6(UDP): Failed to bind socket: %m"); return log_error_errno(errno, "LLMNR-IPv6(UDP): Failed to bind socket: %m");
goto fail;
}
log_warning("LLMNR-IPv6(UDP): There appears to be another LLMNR responder running, or previously systemd-resolved crashed with some outstanding transfers."); log_warning("LLMNR-IPv6(UDP): There appears to be another LLMNR responder running, or previously systemd-resolved crashed with some outstanding transfers.");
/* try again with SO_REUSEADDR */ /* try again with SO_REUSEADDR */
r = setsockopt_int(m->llmnr_ipv6_udp_fd, SOL_SOCKET, SO_REUSEADDR, true); r = setsockopt_int(s, SOL_SOCKET, SO_REUSEADDR, true);
if (r < 0) { if (r < 0)
log_error_errno(r, "LLMNR-IPv6(UDP): Failed to set SO_REUSEADDR: %m"); return log_error_errno(r, "LLMNR-IPv6(UDP): Failed to set SO_REUSEADDR: %m");
goto fail;
}
r = bind(m->llmnr_ipv6_udp_fd, &sa.sa, sizeof(sa.in6)); r = bind(s, &sa.sa, sizeof(sa.in6));
if (r < 0) { if (r < 0)
r = log_error_errno(errno, "LLMNR-IPv6(UDP): Failed to bind socket: %m"); return log_error_errno(errno, "LLMNR-IPv6(UDP): Failed to bind socket: %m");
goto fail;
}
} else { } else {
/* enable SO_REUSEADDR for the case that the user really wants multiple LLMNR responders */ /* enable SO_REUSEADDR for the case that the user really wants multiple LLMNR responders */
r = setsockopt_int(m->llmnr_ipv6_udp_fd, SOL_SOCKET, SO_REUSEADDR, true); r = setsockopt_int(s, SOL_SOCKET, SO_REUSEADDR, true);
if (r < 0) { if (r < 0)
log_error_errno(r, "LLMNR-IPv6(UDP): Failed to set SO_REUSEADDR: %m"); return log_error_errno(r, "LLMNR-IPv6(UDP): Failed to set SO_REUSEADDR: %m");
goto fail;
}
} }
r = sd_event_add_io(m->event, &m->llmnr_ipv6_udp_event_source, m->llmnr_ipv6_udp_fd, EPOLLIN, on_llmnr_packet, m); r = sd_event_add_io(m->event, &m->llmnr_ipv6_udp_event_source, s, EPOLLIN, on_llmnr_packet, m);
if (r < 0) if (r < 0)
goto fail; return log_error_errno(r, "LLMNR-IPv6(UDP): Failed to create event source: %m");
(void) sd_event_source_set_description(m->llmnr_ipv6_udp_event_source, "llmnr-ipv6-udp"); (void) sd_event_source_set_description(m->llmnr_ipv6_udp_event_source, "llmnr-ipv6-udp");
return m->llmnr_ipv6_udp_fd; return m->llmnr_ipv6_udp_fd = TAKE_FD(s);
fail:
m->llmnr_ipv6_udp_fd = safe_close(m->llmnr_ipv6_udp_fd);
return r;
} }
static int on_llmnr_stream_packet(DnsStream *s) { static int on_llmnr_stream_packet(DnsStream *s) {
@ -355,7 +307,7 @@ int manager_llmnr_ipv4_tcp_fd(Manager *m) {
.in.sin_family = AF_INET, .in.sin_family = AF_INET,
.in.sin_port = htobe16(LLMNR_PORT), .in.sin_port = htobe16(LLMNR_PORT),
}; };
static const int pmtu = IP_PMTUDISC_DONT; _cleanup_close_ int s = -1;
int r; int r;
assert(m); assert(m);
@ -363,84 +315,62 @@ int manager_llmnr_ipv4_tcp_fd(Manager *m) {
if (m->llmnr_ipv4_tcp_fd >= 0) if (m->llmnr_ipv4_tcp_fd >= 0)
return m->llmnr_ipv4_tcp_fd; return m->llmnr_ipv4_tcp_fd;
m->llmnr_ipv4_tcp_fd = socket(AF_INET, SOCK_STREAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0); s = socket(AF_INET, SOCK_STREAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0);
if (m->llmnr_ipv4_tcp_fd < 0) if (s < 0)
return log_error_errno(errno, "LLMNR-IPv4(TCP): Failed to create socket: %m"); return log_error_errno(errno, "LLMNR-IPv4(TCP): Failed to create socket: %m");
/* RFC 4795, section 2.5. requires setting the TTL of TCP streams to 1 */ /* RFC 4795, section 2.5. requires setting the TTL of TCP streams to 1 */
r = setsockopt_int(m->llmnr_ipv4_tcp_fd, IPPROTO_IP, IP_TTL, true); r = setsockopt_int(s, IPPROTO_IP, IP_TTL, true);
if (r < 0) { if (r < 0)
log_error_errno(r, "LLMNR-IPv4(TCP): Failed to set IP_TTL: %m"); return log_error_errno(r, "LLMNR-IPv4(TCP): Failed to set IP_TTL: %m");
goto fail;
}
r = setsockopt_int(m->llmnr_ipv4_tcp_fd, IPPROTO_IP, IP_PKTINFO, true); r = setsockopt_int(s, IPPROTO_IP, IP_PKTINFO, true);
if (r < 0) { if (r < 0)
log_error_errno(r, "LLMNR-IPv4(TCP): Failed to set IP_PKTINFO: %m"); return log_error_errno(r, "LLMNR-IPv4(TCP): Failed to set IP_PKTINFO: %m");
goto fail;
}
r = setsockopt_int(m->llmnr_ipv4_tcp_fd, IPPROTO_IP, IP_RECVTTL, true); r = setsockopt_int(s, IPPROTO_IP, IP_RECVTTL, true);
if (r < 0) { if (r < 0)
log_error_errno(r, "LLMNR-IPv4(TCP): Failed to set IP_RECVTTL: %m"); return log_error_errno(r, "LLMNR-IPv4(TCP): Failed to set IP_RECVTTL: %m");
goto fail;
}
/* Disable Don't-Fragment bit in the IP header */ /* Disable Don't-Fragment bit in the IP header */
r = setsockopt(m->llmnr_ipv4_tcp_fd, IPPROTO_IP, IP_MTU_DISCOVER, &pmtu, sizeof(pmtu)); r = setsockopt_int(s, IPPROTO_IP, IP_MTU_DISCOVER, IP_PMTUDISC_DONT);
if (r < 0) { if (r < 0)
r = log_error_errno(errno, "LLMNR-IPv4(TCP): Failed to set IP_MTU_DISCOVER: %m"); return log_error_errno(r, "LLMNR-IPv4(TCP): Failed to set IP_MTU_DISCOVER: %m");
goto fail;
}
/* first try to bind without SO_REUSEADDR to detect another LLMNR responder */ /* first try to bind without SO_REUSEADDR to detect another LLMNR responder */
r = bind(m->llmnr_ipv4_tcp_fd, &sa.sa, sizeof(sa.in)); r = bind(s, &sa.sa, sizeof(sa.in));
if (r < 0) { if (r < 0) {
if (errno != EADDRINUSE) { if (errno != EADDRINUSE)
r = log_error_errno(errno, "LLMNR-IPv4(TCP): Failed to bind socket: %m"); return log_error_errno(errno, "LLMNR-IPv4(TCP): Failed to bind socket: %m");
goto fail;
}
log_warning("LLMNR-IPv4(TCP): There appears to be another LLMNR responder running, or previously systemd-resolved crashed with some outstanding transfers."); log_warning("LLMNR-IPv4(TCP): There appears to be another LLMNR responder running, or previously systemd-resolved crashed with some outstanding transfers.");
/* try again with SO_REUSEADDR */ /* try again with SO_REUSEADDR */
r = setsockopt_int(m->llmnr_ipv4_tcp_fd, SOL_SOCKET, SO_REUSEADDR, true); r = setsockopt_int(s, SOL_SOCKET, SO_REUSEADDR, true);
if (r < 0) { if (r < 0)
log_error_errno(r, "LLMNR-IPv4(TCP): Failed to set SO_REUSEADDR: %m"); return log_error_errno(r, "LLMNR-IPv4(TCP): Failed to set SO_REUSEADDR: %m");
goto fail;
}
r = bind(m->llmnr_ipv4_tcp_fd, &sa.sa, sizeof(sa.in)); r = bind(s, &sa.sa, sizeof(sa.in));
if (r < 0) { if (r < 0)
r = log_error_errno(errno, "LLMNR-IPv4(TCP): Failed to bind socket: %m"); return log_error_errno(errno, "LLMNR-IPv4(TCP): Failed to bind socket: %m");
goto fail;
}
} else { } else {
/* enable SO_REUSEADDR for the case that the user really wants multiple LLMNR responders */ /* enable SO_REUSEADDR for the case that the user really wants multiple LLMNR responders */
r = setsockopt_int(m->llmnr_ipv4_tcp_fd, SOL_SOCKET, SO_REUSEADDR, true); r = setsockopt_int(s, SOL_SOCKET, SO_REUSEADDR, true);
if (r < 0) { if (r < 0)
log_error_errno(r, "LLMNR-IPv4(TCP): Failed to set SO_REUSEADDR: %m"); return log_error_errno(r, "LLMNR-IPv4(TCP): Failed to set SO_REUSEADDR: %m");
goto fail;
}
} }
r = listen(m->llmnr_ipv4_tcp_fd, SOMAXCONN); r = listen(s, SOMAXCONN);
if (r < 0) {
r = log_error_errno(errno, "LLMNR-IPv4(TCP): Failed to listen the stream: %m");
goto fail;
}
r = sd_event_add_io(m->event, &m->llmnr_ipv4_tcp_event_source, m->llmnr_ipv4_tcp_fd, EPOLLIN, on_llmnr_stream, m);
if (r < 0) if (r < 0)
goto fail; return log_error_errno(errno, "LLMNR-IPv4(TCP): Failed to listen the stream: %m");
r = sd_event_add_io(m->event, &m->llmnr_ipv4_tcp_event_source, s, EPOLLIN, on_llmnr_stream, m);
if (r < 0)
return log_error_errno(r, "LLMNR-IPv4(TCP): Failed to create event source: %m");
(void) sd_event_source_set_description(m->llmnr_ipv4_tcp_event_source, "llmnr-ipv4-tcp"); (void) sd_event_source_set_description(m->llmnr_ipv4_tcp_event_source, "llmnr-ipv4-tcp");
return m->llmnr_ipv4_tcp_fd; return m->llmnr_ipv4_tcp_fd = TAKE_FD(s);
fail:
m->llmnr_ipv4_tcp_fd = safe_close(m->llmnr_ipv4_tcp_fd);
return r;
} }
int manager_llmnr_ipv6_tcp_fd(Manager *m) { int manager_llmnr_ipv6_tcp_fd(Manager *m) {
@ -448,6 +378,7 @@ int manager_llmnr_ipv6_tcp_fd(Manager *m) {
.in6.sin6_family = AF_INET6, .in6.sin6_family = AF_INET6,
.in6.sin6_port = htobe16(LLMNR_PORT), .in6.sin6_port = htobe16(LLMNR_PORT),
}; };
_cleanup_close_ int s = -1;
int r; int r;
assert(m); assert(m);
@ -455,81 +386,59 @@ int manager_llmnr_ipv6_tcp_fd(Manager *m) {
if (m->llmnr_ipv6_tcp_fd >= 0) if (m->llmnr_ipv6_tcp_fd >= 0)
return m->llmnr_ipv6_tcp_fd; return m->llmnr_ipv6_tcp_fd;
m->llmnr_ipv6_tcp_fd = socket(AF_INET6, SOCK_STREAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0); s = socket(AF_INET6, SOCK_STREAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0);
if (m->llmnr_ipv6_tcp_fd < 0) if (s < 0)
return log_error_errno(errno, "LLMNR-IPv6(TCP): Failed to create socket: %m"); return log_error_errno(errno, "LLMNR-IPv6(TCP): Failed to create socket: %m");
/* RFC 4795, section 2.5. requires setting the TTL of TCP streams to 1 */ /* RFC 4795, section 2.5. requires setting the TTL of TCP streams to 1 */
r = setsockopt_int(m->llmnr_ipv6_tcp_fd, IPPROTO_IPV6, IPV6_UNICAST_HOPS, true); r = setsockopt_int(s, IPPROTO_IPV6, IPV6_UNICAST_HOPS, true);
if (r < 0) { if (r < 0)
log_error_errno(r, "LLMNR-IPv6(TCP): Failed to set IPV6_UNICAST_HOPS: %m"); return log_error_errno(r, "LLMNR-IPv6(TCP): Failed to set IPV6_UNICAST_HOPS: %m");
goto fail;
}
r = setsockopt_int(m->llmnr_ipv6_tcp_fd, IPPROTO_IPV6, IPV6_V6ONLY, true); r = setsockopt_int(s, IPPROTO_IPV6, IPV6_V6ONLY, true);
if (r < 0) { if (r < 0)
log_error_errno(r, "LLMNR-IPv6(TCP): Failed to set IPV6_V6ONLY: %m"); return log_error_errno(r, "LLMNR-IPv6(TCP): Failed to set IPV6_V6ONLY: %m");
goto fail;
}
r = setsockopt_int(m->llmnr_ipv6_tcp_fd, IPPROTO_IPV6, IPV6_RECVPKTINFO, true); r = setsockopt_int(s, IPPROTO_IPV6, IPV6_RECVPKTINFO, true);
if (r < 0) { if (r < 0)
log_error_errno(r, "LLMNR-IPv6(TCP): Failed to set IPV6_RECVPKTINFO: %m"); return log_error_errno(r, "LLMNR-IPv6(TCP): Failed to set IPV6_RECVPKTINFO: %m");
goto fail;
}
r = setsockopt_int(m->llmnr_ipv6_tcp_fd, IPPROTO_IPV6, IPV6_RECVHOPLIMIT, true); r = setsockopt_int(s, IPPROTO_IPV6, IPV6_RECVHOPLIMIT, true);
if (r < 0) { if (r < 0)
log_error_errno(r, "LLMNR-IPv6(TCP): Failed to set IPV6_RECVHOPLIMIT: %m"); return log_error_errno(r, "LLMNR-IPv6(TCP): Failed to set IPV6_RECVHOPLIMIT: %m");
goto fail;
}
/* first try to bind without SO_REUSEADDR to detect another LLMNR responder */ /* first try to bind without SO_REUSEADDR to detect another LLMNR responder */
r = bind(m->llmnr_ipv6_tcp_fd, &sa.sa, sizeof(sa.in6)); r = bind(s, &sa.sa, sizeof(sa.in6));
if (r < 0) { if (r < 0) {
if (errno != EADDRINUSE) { if (errno != EADDRINUSE)
r = log_error_errno(errno, "LLMNR-IPv6(TCP): Failed to bind socket: %m"); return log_error_errno(errno, "LLMNR-IPv6(TCP): Failed to bind socket: %m");
goto fail;
}
log_warning("LLMNR-IPv6(TCP): There appears to be another LLMNR responder running, or previously systemd-resolved crashed with some outstanding transfers."); log_warning("LLMNR-IPv6(TCP): There appears to be another LLMNR responder running, or previously systemd-resolved crashed with some outstanding transfers.");
/* try again with SO_REUSEADDR */ /* try again with SO_REUSEADDR */
r = setsockopt_int(m->llmnr_ipv6_tcp_fd, SOL_SOCKET, SO_REUSEADDR, true); r = setsockopt_int(s, SOL_SOCKET, SO_REUSEADDR, true);
if (r < 0) { if (r < 0)
log_error_errno(r, "LLMNR-IPv6(TCP): Failed to set SO_REUSEADDR: %m"); return log_error_errno(r, "LLMNR-IPv6(TCP): Failed to set SO_REUSEADDR: %m");
goto fail;
}
r = bind(m->llmnr_ipv6_tcp_fd, &sa.sa, sizeof(sa.in6)); r = bind(s, &sa.sa, sizeof(sa.in6));
if (r < 0) { if (r < 0)
r = log_error_errno(errno, "LLMNR-IPv6(TCP): Failed to bind socket: %m"); return log_error_errno(errno, "LLMNR-IPv6(TCP): Failed to bind socket: %m");
goto fail;
}
} else { } else {
/* enable SO_REUSEADDR for the case that the user really wants multiple LLMNR responders */ /* enable SO_REUSEADDR for the case that the user really wants multiple LLMNR responders */
r = setsockopt_int(m->llmnr_ipv6_tcp_fd, SOL_SOCKET, SO_REUSEADDR, true); r = setsockopt_int(s, SOL_SOCKET, SO_REUSEADDR, true);
if (r < 0) { if (r < 0)
log_error_errno(r, "LLMNR-IPv6(TCP): Failed to set SO_REUSEADDR: %m"); return log_error_errno(r, "LLMNR-IPv6(TCP): Failed to set SO_REUSEADDR: %m");
goto fail;
}
} }
r = listen(m->llmnr_ipv6_tcp_fd, SOMAXCONN); r = listen(s, SOMAXCONN);
if (r < 0) {
r = log_error_errno(errno, "LLMNR-IPv6(TCP): Failed to listen the stream: %m");
goto fail;
}
r = sd_event_add_io(m->event, &m->llmnr_ipv6_tcp_event_source, m->llmnr_ipv6_tcp_fd, EPOLLIN, on_llmnr_stream, m);
if (r < 0) if (r < 0)
goto fail; return log_error_errno(errno, "LLMNR-IPv6(TCP): Failed to listen the stream: %m");
r = sd_event_add_io(m->event, &m->llmnr_ipv6_tcp_event_source, s, EPOLLIN, on_llmnr_stream, m);
if (r < 0)
return log_error_errno(r, "LLMNR-IPv6(TCP): Failed to create event source: %m");
(void) sd_event_source_set_description(m->llmnr_ipv6_tcp_event_source, "llmnr-ipv6-tcp"); (void) sd_event_source_set_description(m->llmnr_ipv6_tcp_event_source, "llmnr-ipv6-tcp");
return m->llmnr_ipv6_tcp_fd; return m->llmnr_ipv6_tcp_fd = TAKE_FD(s);
fail:
m->llmnr_ipv6_tcp_fd = safe_close(m->llmnr_ipv6_tcp_fd);
return r;
} }

View file

@ -339,7 +339,7 @@ int manager_mdns_ipv4_fd(Manager *m) {
.in.sin_family = AF_INET, .in.sin_family = AF_INET,
.in.sin_port = htobe16(MDNS_PORT), .in.sin_port = htobe16(MDNS_PORT),
}; };
static const int pmtu = IP_PMTUDISC_DONT, ttl = 255; _cleanup_close_ int s = -1;
int r; int r;
assert(m); assert(m);
@ -347,88 +347,64 @@ int manager_mdns_ipv4_fd(Manager *m) {
if (m->mdns_ipv4_fd >= 0) if (m->mdns_ipv4_fd >= 0)
return m->mdns_ipv4_fd; return m->mdns_ipv4_fd;
m->mdns_ipv4_fd = socket(AF_INET, SOCK_DGRAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0); s = socket(AF_INET, SOCK_DGRAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0);
if (m->mdns_ipv4_fd < 0) if (s < 0)
return log_error_errno(errno, "mDNS-IPv4: Failed to create socket: %m"); return log_error_errno(errno, "mDNS-IPv4: Failed to create socket: %m");
r = setsockopt(m->mdns_ipv4_fd, IPPROTO_IP, IP_TTL, &ttl, sizeof(ttl)); r = setsockopt_int(s, IPPROTO_IP, IP_TTL, 255);
if (r < 0) { if (r < 0)
r = log_error_errno(errno, "mDNS-IPv4: Failed to set IP_TTL: %m"); return log_error_errno(r, "mDNS-IPv4: Failed to set IP_TTL: %m");
goto fail;
}
r = setsockopt(m->mdns_ipv4_fd, IPPROTO_IP, IP_MULTICAST_TTL, &ttl, sizeof(ttl)); r = setsockopt_int(s, IPPROTO_IP, IP_MULTICAST_TTL, 255);
if (r < 0) { if (r < 0)
r = log_error_errno(errno, "mDNS-IPv4: Failed to set IP_MULTICAST_TTL: %m"); return log_error_errno(r, "mDNS-IPv4: Failed to set IP_MULTICAST_TTL: %m");
goto fail;
}
r = setsockopt_int(m->mdns_ipv4_fd, IPPROTO_IP, IP_MULTICAST_LOOP, true); r = setsockopt_int(s, IPPROTO_IP, IP_MULTICAST_LOOP, true);
if (r < 0) { if (r < 0)
log_error_errno(r, "mDNS-IPv4: Failed to set IP_MULTICAST_LOOP: %m"); return log_error_errno(r, "mDNS-IPv4: Failed to set IP_MULTICAST_LOOP: %m");
goto fail;
}
r = setsockopt_int(m->mdns_ipv4_fd, IPPROTO_IP, IP_PKTINFO, true); r = setsockopt_int(s, IPPROTO_IP, IP_PKTINFO, true);
if (r < 0) { if (r < 0)
log_error_errno(r, "mDNS-IPv4: Failed to set IP_PKTINFO: %m"); return log_error_errno(r, "mDNS-IPv4: Failed to set IP_PKTINFO: %m");
goto fail;
}
r = setsockopt_int(m->mdns_ipv4_fd, IPPROTO_IP, IP_RECVTTL, true); r = setsockopt_int(s, IPPROTO_IP, IP_RECVTTL, true);
if (r < 0) { if (r < 0)
log_error_errno(r, "mDNS-IPv4: Failed to set IP_RECVTTL: %m"); return log_error_errno(r, "mDNS-IPv4: Failed to set IP_RECVTTL: %m");
goto fail;
}
/* Disable Don't-Fragment bit in the IP header */ /* Disable Don't-Fragment bit in the IP header */
r = setsockopt(m->mdns_ipv4_fd, IPPROTO_IP, IP_MTU_DISCOVER, &pmtu, sizeof(pmtu)); r = setsockopt_int(s, IPPROTO_IP, IP_MTU_DISCOVER, IP_PMTUDISC_DONT);
if (r < 0) { if (r < 0)
r = log_error_errno(errno, "mDNS-IPv4: Failed to set IP_MTU_DISCOVER: %m"); return log_error_errno(r, "mDNS-IPv4: Failed to set IP_MTU_DISCOVER: %m");
goto fail;
}
/* See the section 15.1 of RFC6762 */ /* See the section 15.1 of RFC6762 */
/* first try to bind without SO_REUSEADDR to detect another mDNS responder */ /* first try to bind without SO_REUSEADDR to detect another mDNS responder */
r = bind(m->mdns_ipv4_fd, &sa.sa, sizeof(sa.in)); r = bind(s, &sa.sa, sizeof(sa.in));
if (r < 0) { if (r < 0) {
if (errno != EADDRINUSE) { if (errno != EADDRINUSE)
r = log_error_errno(errno, "mDNS-IPv4: Failed to bind socket: %m"); return log_error_errno(errno, "mDNS-IPv4: Failed to bind socket: %m");
goto fail;
}
log_warning("mDNS-IPv4: There appears to be another mDNS responder running, or previously systemd-resolved crashed with some outstanding transfers."); log_warning("mDNS-IPv4: There appears to be another mDNS responder running, or previously systemd-resolved crashed with some outstanding transfers.");
/* try again with SO_REUSEADDR */ /* try again with SO_REUSEADDR */
r = setsockopt_int(m->mdns_ipv4_fd, SOL_SOCKET, SO_REUSEADDR, true); r = setsockopt_int(s, SOL_SOCKET, SO_REUSEADDR, true);
if (r < 0) { if (r < 0)
log_error_errno(r, "mDNS-IPv4: Failed to set SO_REUSEADDR: %m"); return log_error_errno(r, "mDNS-IPv4: Failed to set SO_REUSEADDR: %m");
goto fail;
}
r = bind(m->mdns_ipv4_fd, &sa.sa, sizeof(sa.in)); r = bind(s, &sa.sa, sizeof(sa.in));
if (r < 0) { if (r < 0)
r = log_error_errno(errno, "mDNS-IPv4: Failed to bind socket: %m"); return log_error_errno(errno, "mDNS-IPv4: Failed to bind socket: %m");
goto fail;
}
} else { } else {
/* enable SO_REUSEADDR for the case that the user really wants multiple mDNS responders */ /* enable SO_REUSEADDR for the case that the user really wants multiple mDNS responders */
r = setsockopt_int(m->mdns_ipv4_fd, SOL_SOCKET, SO_REUSEADDR, true); r = setsockopt_int(s, SOL_SOCKET, SO_REUSEADDR, true);
if (r < 0) { if (r < 0)
log_error_errno(r, "mDNS-IPv4: Failed to set SO_REUSEADDR: %m"); return log_error_errno(r, "mDNS-IPv4: Failed to set SO_REUSEADDR: %m");
goto fail;
}
} }
r = sd_event_add_io(m->event, &m->mdns_ipv4_event_source, m->mdns_ipv4_fd, EPOLLIN, on_mdns_packet, m); r = sd_event_add_io(m->event, &m->mdns_ipv4_event_source, s, EPOLLIN, on_mdns_packet, m);
if (r < 0) if (r < 0)
goto fail; return log_error_errno(r, "mDNS-IPv4: Failed to create event source: %m");
return m->mdns_ipv4_fd; return m->mdns_ipv4_fd = TAKE_FD(s);
fail:
m->mdns_ipv4_fd = safe_close(m->mdns_ipv4_fd);
return r;
} }
int manager_mdns_ipv6_fd(Manager *m) { int manager_mdns_ipv6_fd(Manager *m) {
@ -436,7 +412,7 @@ int manager_mdns_ipv6_fd(Manager *m) {
.in6.sin6_family = AF_INET6, .in6.sin6_family = AF_INET6,
.in6.sin6_port = htobe16(MDNS_PORT), .in6.sin6_port = htobe16(MDNS_PORT),
}; };
static const int ttl = 255; _cleanup_close_ int s = -1;
int r; int r;
assert(m); assert(m);
@ -444,86 +420,62 @@ int manager_mdns_ipv6_fd(Manager *m) {
if (m->mdns_ipv6_fd >= 0) if (m->mdns_ipv6_fd >= 0)
return m->mdns_ipv6_fd; return m->mdns_ipv6_fd;
m->mdns_ipv6_fd = socket(AF_INET6, SOCK_DGRAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0); s = socket(AF_INET6, SOCK_DGRAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0);
if (m->mdns_ipv6_fd < 0) if (s < 0)
return log_error_errno(errno, "mDNS-IPv6: Failed to create socket: %m"); return log_error_errno(errno, "mDNS-IPv6: Failed to create socket: %m");
r = setsockopt(m->mdns_ipv6_fd, IPPROTO_IPV6, IPV6_UNICAST_HOPS, &ttl, sizeof(ttl)); r = setsockopt_int(s, IPPROTO_IPV6, IPV6_UNICAST_HOPS, 255);
if (r < 0) { if (r < 0)
r = log_error_errno(errno, "mDNS-IPv6: Failed to set IPV6_UNICAST_HOPS: %m"); return log_error_errno(r, "mDNS-IPv6: Failed to set IPV6_UNICAST_HOPS: %m");
goto fail;
}
/* RFC 4795, section 2.5 recommends setting the TTL of UDP packets to 255. */ /* RFC 4795, section 2.5 recommends setting the TTL of UDP packets to 255. */
r = setsockopt(m->mdns_ipv6_fd, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, &ttl, sizeof(ttl)); r = setsockopt_int(s, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, 255);
if (r < 0) { if (r < 0)
r = log_error_errno(errno, "mDNS-IPv6: Failed to set IPV6_MULTICAST_HOPS: %m"); return log_error_errno(r, "mDNS-IPv6: Failed to set IPV6_MULTICAST_HOPS: %m");
goto fail;
}
r = setsockopt_int(m->mdns_ipv6_fd, IPPROTO_IPV6, IPV6_MULTICAST_LOOP, true); r = setsockopt_int(s, IPPROTO_IPV6, IPV6_MULTICAST_LOOP, true);
if (r < 0) { if (r < 0)
log_error_errno(r, "mDNS-IPv6: Failed to set IPV6_MULTICAST_LOOP: %m"); return log_error_errno(r, "mDNS-IPv6: Failed to set IPV6_MULTICAST_LOOP: %m");
goto fail;
}
r = setsockopt_int(m->mdns_ipv6_fd, IPPROTO_IPV6, IPV6_V6ONLY, true); r = setsockopt_int(s, IPPROTO_IPV6, IPV6_V6ONLY, true);
if (r < 0) { if (r < 0)
log_error_errno(r, "mDNS-IPv6: Failed to set IPV6_V6ONLY: %m"); return log_error_errno(r, "mDNS-IPv6: Failed to set IPV6_V6ONLY: %m");
goto fail;
}
r = setsockopt_int(m->mdns_ipv6_fd, IPPROTO_IPV6, IPV6_RECVPKTINFO, true); r = setsockopt_int(s, IPPROTO_IPV6, IPV6_RECVPKTINFO, true);
if (r < 0) { if (r < 0)
log_error_errno(r, "mDNS-IPv6: Failed to set IPV6_RECVPKTINFO: %m"); return log_error_errno(r, "mDNS-IPv6: Failed to set IPV6_RECVPKTINFO: %m");
goto fail;
}
r = setsockopt_int(m->mdns_ipv6_fd, IPPROTO_IPV6, IPV6_RECVHOPLIMIT, true); r = setsockopt_int(s, IPPROTO_IPV6, IPV6_RECVHOPLIMIT, true);
if (r < 0) { if (r < 0)
log_error_errno(r, "mDNS-IPv6: Failed to set IPV6_RECVHOPLIMIT: %m"); return log_error_errno(r, "mDNS-IPv6: Failed to set IPV6_RECVHOPLIMIT: %m");
goto fail;
}
/* See the section 15.1 of RFC6762 */ /* See the section 15.1 of RFC6762 */
/* first try to bind without SO_REUSEADDR to detect another mDNS responder */ /* first try to bind without SO_REUSEADDR to detect another mDNS responder */
r = bind(m->mdns_ipv6_fd, &sa.sa, sizeof(sa.in6)); r = bind(s, &sa.sa, sizeof(sa.in6));
if (r < 0) { if (r < 0) {
if (errno != EADDRINUSE) { if (errno != EADDRINUSE)
r = log_error_errno(errno, "mDNS-IPv6: Failed to bind socket: %m"); return log_error_errno(errno, "mDNS-IPv6: Failed to bind socket: %m");
goto fail;
}
log_warning("mDNS-IPv6: There appears to be another mDNS responder running, or previously systemd-resolved crashed with some outstanding transfers."); log_warning("mDNS-IPv6: There appears to be another mDNS responder running, or previously systemd-resolved crashed with some outstanding transfers.");
/* try again with SO_REUSEADDR */ /* try again with SO_REUSEADDR */
r = setsockopt_int(m->mdns_ipv6_fd, SOL_SOCKET, SO_REUSEADDR, true); r = setsockopt_int(s, SOL_SOCKET, SO_REUSEADDR, true);
if (r < 0) { if (r < 0)
log_error_errno(r, "mDNS-IPv6: Failed to set SO_REUSEADDR: %m"); return log_error_errno(r, "mDNS-IPv6: Failed to set SO_REUSEADDR: %m");
goto fail;
}
r = bind(m->mdns_ipv6_fd, &sa.sa, sizeof(sa.in6)); r = bind(s, &sa.sa, sizeof(sa.in6));
if (r < 0) { if (r < 0)
r = log_error_errno(errno, "mDNS-IPv6: Failed to bind socket: %m"); return log_error_errno(errno, "mDNS-IPv6: Failed to bind socket: %m");
goto fail;
}
} else { } else {
/* enable SO_REUSEADDR for the case that the user really wants multiple mDNS responders */ /* enable SO_REUSEADDR for the case that the user really wants multiple mDNS responders */
r = setsockopt_int(m->mdns_ipv6_fd, SOL_SOCKET, SO_REUSEADDR, true); r = setsockopt_int(s, SOL_SOCKET, SO_REUSEADDR, true);
if (r < 0) { if (r < 0)
log_error_errno(r, "mDNS-IPv6: Failed to set SO_REUSEADDR: %m"); return log_error_errno(r, "mDNS-IPv6: Failed to set SO_REUSEADDR: %m");
goto fail;
}
} }
r = sd_event_add_io(m->event, &m->mdns_ipv6_event_source, m->mdns_ipv6_fd, EPOLLIN, on_mdns_packet, m); r = sd_event_add_io(m->event, &m->mdns_ipv6_event_source, s, EPOLLIN, on_mdns_packet, m);
if (r < 0) if (r < 0)
goto fail; return log_error_errno(r, "mDNS-IPv6: Failed to create event source: %m");
return m->mdns_ipv6_fd; return m->mdns_ipv6_fd = TAKE_FD(s);
fail:
m->mdns_ipv6_fd = safe_close(m->mdns_ipv6_fd);
return r;
} }

View file

@ -629,7 +629,6 @@ static int manager_receive_response(sd_event_source *source, int fd, uint32_t re
static int manager_listen_setup(Manager *m) { static int manager_listen_setup(Manager *m) {
union sockaddr_union addr = {}; union sockaddr_union addr = {};
static const int tos = IPTOS_LOWDELAY;
int r; int r;
assert(m); assert(m);
@ -654,7 +653,7 @@ static int manager_listen_setup(Manager *m) {
if (r < 0) if (r < 0)
return r; return r;
(void) setsockopt(m->server_socket, IPPROTO_IP, IP_TOS, &tos, sizeof(tos)); (void) setsockopt_int(m->server_socket, IPPROTO_IP, IP_TOS, IPTOS_LOWDELAY);
return sd_event_add_io(m->event, &m->event_receive, m->server_socket, EPOLLIN, manager_receive_response, m); return sd_event_add_io(m->event, &m->event_receive, m->server_socket, EPOLLIN, manager_receive_response, m);
} }