resolved-manager.c revision f0e1546763304aedc90e91d70dab9eeb7c966cf8
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt This file is part of systemd.
7bd8e95d44977833d0de3fc4e893eb3bc84351d6Patrik Flykt Copyright 2014 Tom Gundersen <teg@jklm.no>
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt systemd is free software; you can redistribute it and/or modify it
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt under the terms of the GNU Lesser General Public License as published by
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt the Free Software Foundation; either version 2.1 of the License, or
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt (at your option) any later version.
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt systemd is distributed in the hope that it will be useful, but
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt WITHOUT ANY WARRANTY; without even the implied warranty of
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt Lesser General Public License for more details.
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt You should have received a copy of the GNU Lesser General Public License
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt along with systemd; If not, see <http://www.gnu.org/licenses/>.
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flyktstatic int manager_process_link(sd_rtnl *rtnl, sd_rtnl_message *mm, void *userdata) {
da6fe470e17fa02f3adedc779585caf8669252bdPatrik Flykt r = sd_rtnl_message_link_get_ifindex(mm, &ifindex);
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt l = hashmap_get(m->links, INT_TO_PTR(ifindex));
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt log_debug("Found new link %i/%s", ifindex, l->name);
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt log_debug("Removing link %i/%s", l->ifindex, l->name);
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt log_warning("Failed to process RTNL link message: %s", strerror(-r));
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flyktstatic int manager_process_address(sd_rtnl *rtnl, sd_rtnl_message *mm, void *userdata) {
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt r = sd_rtnl_message_addr_get_ifindex(mm, &ifindex);
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt l = hashmap_get(m->links, INT_TO_PTR(ifindex));
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt r = sd_rtnl_message_addr_get_family(mm, &family);
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt r = sd_rtnl_message_read_in_addr(mm, IFA_LOCAL, &address.in);
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt if (r < 0) {
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt r = sd_rtnl_message_read_in_addr(mm, IFA_ADDRESS, &address.in);
76253e73f9c9c24fec755e485516f3b55d0707b4Dan Williams r = sd_rtnl_message_read_in6_addr(mm, IFA_LOCAL, &address.in6);
76253e73f9c9c24fec755e485516f3b55d0707b4Dan Williams if (r < 0) {
76253e73f9c9c24fec755e485516f3b55d0707b4Dan Williams r = sd_rtnl_message_read_in6_addr(mm, IFA_ADDRESS, &address.in6);
cc22955cfefb4bd6e7a135f1ec95fb5a07ba9ce3Thomas Haller r = link_address_new(l, &a, family, &address);
764aad6258eec3bd4ae62ea341ea507bd69ce628Tom Gundersen log_warning("Failed to process RTNL address message: %s", strerror(-r));
fe4b2156256c5bdf52341576571ce9f095d9f085Tom Gundersen _cleanup_rtnl_message_unref_ sd_rtnl_message *req = NULL, *reply = NULL;
fe4b2156256c5bdf52341576571ce9f095d9f085Tom Gundersen /* First, subscibe to interfaces coming and going */
fe4b2156256c5bdf52341576571ce9f095d9f085Tom Gundersen r = sd_rtnl_open(&m->rtnl, 3, RTNLGRP_LINK, RTNLGRP_IPV4_IFADDR, RTNLGRP_IPV6_IFADDR);
764aad6258eec3bd4ae62ea341ea507bd69ce628Tom Gundersen r = sd_rtnl_attach_event(m->rtnl, m->event, 0);
66eac1201a9c1596f5901f8dbbf24bda7e350878Dan Williams r = sd_rtnl_add_match(m->rtnl, RTM_NEWLINK, manager_process_link, m);
bbfa43ca37df0718287c25a8e39ee7477ebf33f6Patrik Flykt r = sd_rtnl_add_match(m->rtnl, RTM_DELLINK, manager_process_link, m);
bbfa43ca37df0718287c25a8e39ee7477ebf33f6Patrik Flykt r = sd_rtnl_add_match(m->rtnl, RTM_NEWADDR, manager_process_address, m);
bbfa43ca37df0718287c25a8e39ee7477ebf33f6Patrik Flykt r = sd_rtnl_add_match(m->rtnl, RTM_DELADDR, manager_process_address, m);
bbfa43ca37df0718287c25a8e39ee7477ebf33f6Patrik Flykt /* Then, enumerate all links */
bbfa43ca37df0718287c25a8e39ee7477ebf33f6Patrik Flykt r = sd_rtnl_message_new_link(m->rtnl, &req, RTM_GETLINK, 0);
da6fe470e17fa02f3adedc779585caf8669252bdPatrik Flykt for (i = reply; i; i = sd_rtnl_message_next(i)) {
da6fe470e17fa02f3adedc779585caf8669252bdPatrik Flykt /* Finally, enumerate all addresses, too */
da6fe470e17fa02f3adedc779585caf8669252bdPatrik Flykt r = sd_rtnl_message_new_addr(m->rtnl, &req, RTM_GETADDR, 0, AF_UNSPEC);
da6fe470e17fa02f3adedc779585caf8669252bdPatrik Flykt for (i = reply; i; i = sd_rtnl_message_next(i)) {
ea3b3a75abb3f8b853f7da454b9b8e258a120eeaPatrik Flyktstatic int on_network_event(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
c806ffb9592fa9a2b13a1f9f9be4c77cd5b211aaZbigniew Jędrzejewski-Szmek HASHMAP_FOREACH(l, m->links, i) {
4e3e6679e8f73b83d38e4b20d8b025e12991d1cbPatrik Flykt log_warning("Failed to update monitor information for %i: %s", l->ifindex, strerror(-r));
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt log_warning("Could not update resolv.conf: %s", strerror(-r));
c3e2adeaba8e043caed0ef139eeaea016bd152d0Patrik Flyktstatic int manager_network_monitor_listen(Manager *m) {
f12abb48fc510b8b349c05e35ba048134debaf25Patrik Flykt r = sd_network_monitor_new(&m->network_monitor, NULL);
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt fd = sd_network_monitor_get_fd(m->network_monitor);
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt events = sd_network_monitor_get_events(m->network_monitor);
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt r = sd_event_add_io(m->event, &m->network_event_source, fd, events, &on_network_event, m);
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt log_error("System hostname is not UTF-8 clean.");
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt if (r < 0) {
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt log_error("System hostname '%s' cannot be normalized.", h);
bbfa43ca37df0718287c25a8e39ee7477ebf33f6Patrik Flyktstatic int on_hostname_change(sd_event_source *es, int fd, uint32_t revents, void *userdata) {
926695f1b5f9395eeb416cc2f478a9cf75fdbeb4Thomas Hindoe Paaboel Andersen return 0; /* ignore invalid hostnames */
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt log_info("System hostname changed to '%s'.", h);
7246333cb803b03440d3bd0bdaa233564d09b5aePatrik Flykt m->hostname_fd = open("/proc/sys/kernel/hostname", O_RDONLY|O_CLOEXEC|O_NDELAY|O_NOCTTY);
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt r = sd_event_add_io(m->event, &m->hostname_event_source, m->hostname_fd, 0, on_hostname_change, m);
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt if (r < 0) {
3dc34fcc97b41f8b7b019027225b121dfbb9871dPatrik Flykt /* kernels prior to 3.2 don't support polling this file. Ignore the failure. */
3dc34fcc97b41f8b7b019027225b121dfbb9871dPatrik Flykt log_error("Failed to add hostname event source: %s", strerror(-r));
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt if (r < 0) {
da6fe470e17fa02f3adedc779585caf8669252bdPatrik Flykt log_info("Using system hostname '%s'.", m->hostname);
7246333cb803b03440d3bd0bdaa233564d09b5aePatrik Flykt m->llmnr_ipv4_udp_event_source = sd_event_source_unref(m->llmnr_ipv4_udp_event_source);
7246333cb803b03440d3bd0bdaa233564d09b5aePatrik Flykt m->llmnr_ipv4_udp_fd = safe_close(m->llmnr_ipv4_udp_fd);
346e13a25dc6f76d3bc9d8decd40dc4782b02d2aPatrik Flykt m->llmnr_ipv6_udp_event_source = sd_event_source_unref(m->llmnr_ipv6_udp_event_source);
346e13a25dc6f76d3bc9d8decd40dc4782b02d2aPatrik Flykt m->llmnr_ipv6_udp_fd = safe_close(m->llmnr_ipv6_udp_fd);
346e13a25dc6f76d3bc9d8decd40dc4782b02d2aPatrik Flykt m->llmnr_ipv4_tcp_event_source = sd_event_source_unref(m->llmnr_ipv4_tcp_event_source);
346e13a25dc6f76d3bc9d8decd40dc4782b02d2aPatrik Flykt m->llmnr_ipv4_tcp_fd = safe_close(m->llmnr_ipv4_tcp_fd);
346e13a25dc6f76d3bc9d8decd40dc4782b02d2aPatrik Flykt m->llmnr_ipv6_tcp_event_source = sd_event_source_unref(m->llmnr_ipv6_tcp_event_source);
346e13a25dc6f76d3bc9d8decd40dc4782b02d2aPatrik Flykt m->llmnr_ipv6_tcp_fd = safe_close(m->llmnr_ipv6_tcp_fd);
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt log_warning("There appears to be another LLMNR respondering running. Turning off LLMNR support.");
3dc34fcc97b41f8b7b019027225b121dfbb9871dPatrik Flykt m->llmnr_ipv4_udp_fd = m->llmnr_ipv6_udp_fd = -1;
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt m->llmnr_ipv4_tcp_fd = m->llmnr_ipv6_tcp_fd = -1;
3dc34fcc97b41f8b7b019027225b121dfbb9871dPatrik Flykt r = manager_parse_dns_server(m, DNS_SERVER_FALLBACK, DNS_SERVERS);
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt sd_event_add_signal(m->event, NULL, SIGTERM, NULL, NULL);
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt sd_event_add_signal(m->event, NULL, SIGINT, NULL, NULL);
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt r = dns_scope_new(m, &m->unicast_scope, NULL, DNS_PROTOCOL_DNS, AF_UNSPEC);
3dc34fcc97b41f8b7b019027225b121dfbb9871dPatrik Flykt sd_event_source_unref(m->network_event_source);
3dc34fcc97b41f8b7b019027225b121dfbb9871dPatrik Flykt sd_event_source_unref(m->dns_ipv4_event_source);
3dc34fcc97b41f8b7b019027225b121dfbb9871dPatrik Flykt sd_event_source_unref(m->dns_ipv6_event_source);
3dc34fcc97b41f8b7b019027225b121dfbb9871dPatrik Flykt sd_event_source_unref(m->bus_retry_event_source);
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt sd_event_source_unref(m->hostname_event_source);
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt /* Reads the system /etc/resolv.conf, if it exists and is not
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt * symlinked to our own resolv.conf instance */
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt if (r < 0) {
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt log_warning("Failed to open /etc/resolv.conf: %m");
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt /* Have we already seen the file? */
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt /* Is it symlinked to our own file? */
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt if (stat("/run/systemd/resolve/resolv.conf", &own) >= 0 &&
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt log_warning("Failed to open /etc/resolv.conf: %m");
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt FOREACH_LINE(line, f, r = -errno; goto clear) {
9021bb9f935c93b516b10c88db2a212a9e3a8140Tom Gundersen const char *a;
f12abb48fc510b8b349c05e35ba048134debaf25Patrik Flykt r = in_addr_from_string_auto(a, &family, &address);
f12abb48fc510b8b349c05e35ba048134debaf25Patrik Flykt if (r < 0) {
f12abb48fc510b8b349c05e35ba048134debaf25Patrik Flykt log_warning("Failed to parse name server %s.", a);
cfb5b3805759e63dc5e0cae6e92e1df885b5c5b6Tom Gundersen if (s->family == family && in_addr_equal(family, &s->address, &address) > 0)
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt r = dns_server_new(m, NULL, DNS_SERVER_SYSTEM, NULL, family, &address);
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt LIST_FOREACH_SAFE(servers, s, nx, m->dns_servers)
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flyktstatic void write_resolve_conf_server(DnsServer *s, FILE *f, unsigned *count) {
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt r = in_addr_to_string(s->family, &s->address, &t);
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt if (r < 0) {
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt log_warning("Invalid DNS address. Ignoring: %s", strerror(-r));
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt fputs("# Too many DNS servers configured, the following entries may be ignored\n", f);
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt static const char path[] = "/run/systemd/resolve/resolv.conf";
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt unsigned count = 0;
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt /* Read the system /etc/resolv.conf first */
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt fputs("# This file is managed by systemd-resolved(8). Do not edit.\n#\n"
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt "# Third party programs must not access this file directly, but\n"
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt "# only through the symlink at /etc/resolv.conf. To manage\n"
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt "# resolv.conf(5) in a different way, replace the symlink by a\n"
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt "# static file or a different symlink.\n\n", f);
bbfa43ca37df0718287c25a8e39ee7477ebf33f6Patrik Flykt LIST_FOREACH(servers, s, m->fallback_dns_servers)
ed6ee21953dac9c78383da00bc4514ece6b75ab5Patrik Flyktint manager_recv(Manager *m, int fd, DnsProtocol protocol, DnsPacket **ret) {
ed6ee21953dac9c78383da00bc4514ece6b75ab5Patrik Flykt _cleanup_(dns_packet_unrefp) DnsPacket *p = NULL;
ed6ee21953dac9c78383da00bc4514ece6b75ab5Patrik Flykt uint8_t buffer[CMSG_SPACE(MAX(sizeof(struct in_pktinfo), sizeof(struct in6_pktinfo)))
7bd8e95d44977833d0de3fc4e893eb3bc84351d6Patrik Flykt + EXTRA_CMSG_SPACE /* kernel appears to require extra buffer space */];
c47e8936a43ce546e8a74fa569e9fbfae6c64be7Patrik Flykt if (l < 0) {
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt for (cmsg = CMSG_FIRSTHDR(&mh); cmsg; cmsg = CMSG_NXTHDR(&mh, cmsg)) {
ed6ee21953dac9c78383da00bc4514ece6b75ab5Patrik Flykt struct in6_pktinfo *i = (struct in6_pktinfo*) CMSG_DATA(cmsg);
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt struct in_pktinfo *i = (struct in_pktinfo*) CMSG_DATA(cmsg);
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt /* The Linux kernel sets the interface index to the loopback
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt * device if the packet came from the local host since it
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt * avoids the routing table in such a case. Let's unset the
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt * interface index in such a case. */
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt if (p->ifindex > 0 && manager_ifindex_is_loopback(m, p->ifindex) != 0)
bbfa43ca37df0718287c25a8e39ee7477ebf33f6Patrik Flykt /* If we don't know the interface index still, we look for the
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt * first local interface with a matching address. Yuck! */
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt p->ifindex = manager_find_ifindex(m, p->family, &p->destination);
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flyktstatic int on_dns_packet(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt _cleanup_(dns_packet_unrefp) DnsPacket *p = NULL;
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt t = hashmap_get(m->dns_transactions, UINT_TO_PTR(DNS_PACKET_ID(p)));
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt m->dns_ipv4_fd = socket(AF_INET, SOCK_DGRAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0);
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt r = setsockopt(m->dns_ipv4_fd, IPPROTO_IP, IP_PKTINFO, &one, sizeof(one));
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt if (r < 0) {
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt r = sd_event_add_io(m->event, &m->dns_ipv4_event_source, m->dns_ipv4_fd, EPOLLIN, on_dns_packet, m);
bbfa43ca37df0718287c25a8e39ee7477ebf33f6Patrik Flykt m->dns_ipv6_fd = socket(AF_INET6, SOCK_DGRAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0);
bbfa43ca37df0718287c25a8e39ee7477ebf33f6Patrik Flykt r = setsockopt(m->dns_ipv6_fd, IPPROTO_IPV6, IPV6_RECVPKTINFO, &one, sizeof(one));
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt if (r < 0) {
7246333cb803b03440d3bd0bdaa233564d09b5aePatrik Flykt r = sd_event_add_io(m->event, &m->dns_ipv6_event_source, m->dns_ipv6_fd, EPOLLIN, on_dns_packet, m);
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flyktstatic int sendmsg_loop(int fd, struct msghdr *mh, int flags) {
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt r = fd_wait_for_event(fd, POLLOUT, SEND_TIMEOUT_USEC);
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flyktstatic int manager_ipv4_send(Manager *m, int fd, int ifindex, const struct in_addr *addr, uint16_t port, DnsPacket *p) {
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt uint8_t buffer[CMSG_SPACE(sizeof(struct in_pktinfo))];
9021bb9f935c93b516b10c88db2a212a9e3a8140Tom Gundersen mh.msg_controllen = CMSG_LEN(sizeof(struct in_pktinfo));
c3e2adeaba8e043caed0ef139eeaea016bd152d0Patrik Flyktstatic int manager_ipv6_send(Manager *m, int fd, int ifindex, const struct in6_addr *addr, uint16_t port, DnsPacket *p) {
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt uint8_t buffer[CMSG_SPACE(sizeof(struct in6_pktinfo))];
9021bb9f935c93b516b10c88db2a212a9e3a8140Tom Gundersen mh.msg_controllen = CMSG_LEN(sizeof(struct in6_pktinfo));
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flyktint manager_send(Manager *m, int fd, int ifindex, int family, const union in_addr_union *addr, uint16_t port, DnsPacket *p) {
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt log_debug("Sending %s packet with id %u on interface %i/%s", DNS_PACKET_QR(p) ? "response" : "query", DNS_PACKET_ID(p), ifindex, af_to_name(family));
9021bb9f935c93b516b10c88db2a212a9e3a8140Tom Gundersen return manager_ipv4_send(m, fd, ifindex, &addr->in, port, p);
3dc34fcc97b41f8b7b019027225b121dfbb9871dPatrik Flykt return manager_ipv6_send(m, fd, ifindex, &addr->in6, port, p);
c3e2adeaba8e043caed0ef139eeaea016bd152d0Patrik FlyktDnsServer* manager_find_dns_server(Manager *m, int family, const union in_addr_union *in_addr) {
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt if (s->family == family && in_addr_equal(family, &s->address, in_addr) > 0)
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt LIST_FOREACH(servers, s, m->fallback_dns_servers)
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt if (s->family == family && in_addr_equal(family, &s->address, in_addr) > 0)
9021bb9f935c93b516b10c88db2a212a9e3a8140Tom GundersenDnsServer *manager_set_dns_server(Manager *m, DnsServer *s) {
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt in_addr_to_string(s->family, &s->address, &ip);
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt log_info("Switching to system DNS server %s.", strna(ip));
bbfa43ca37df0718287c25a8e39ee7477ebf33f6Patrik Flykt /* Try to read updates resolv.conf */
bbfa43ca37df0718287c25a8e39ee7477ebf33f6Patrik Flykt bool found = false;
bbfa43ca37df0718287c25a8e39ee7477ebf33f6Patrik Flykt /* No DNS servers configured, let's see if there are
bbfa43ca37df0718287c25a8e39ee7477ebf33f6Patrik Flykt * any on any links. If not, we use the fallback
bbfa43ca37df0718287c25a8e39ee7477ebf33f6Patrik Flykt * servers */
bbfa43ca37df0718287c25a8e39ee7477ebf33f6Patrik Flykt manager_set_dns_server(m, m->fallback_dns_servers);
bbfa43ca37df0718287c25a8e39ee7477ebf33f6Patrik Flykt /* If there's currently no DNS server set, then the next
bbfa43ca37df0718287c25a8e39ee7477ebf33f6Patrik Flykt * manager_get_dns_server() will find one */
bbfa43ca37df0718287c25a8e39ee7477ebf33f6Patrik Flykt /* Change to the next one */
bbfa43ca37df0718287c25a8e39ee7477ebf33f6Patrik Flykt manager_set_dns_server(m, m->current_dns_server->servers_next);
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt /* If there was no next one, then start from the beginning of
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt * the list */
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt if (m->current_dns_server->type == DNS_SERVER_FALLBACK)
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt manager_set_dns_server(m, m->fallback_dns_servers);
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt /* If we don't know on which link a DNS packet would be
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt * delivered, let's find the largest MTU that works on all
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt * interfaces we know of */
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt if (l->mtu <= 0)
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flyktstatic int on_llmnr_packet(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt _cleanup_(dns_packet_unrefp) DnsPacket *p = NULL;
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt r = manager_recv(m, fd, DNS_PROTOCOL_LLMNR, &p);
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt log_debug("Got reply packet for id %u", DNS_PACKET_ID(p));
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt t = hashmap_get(m->dns_transactions, UINT_TO_PTR(DNS_PACKET_ID(p)));
c806ffb9592fa9a2b13a1f9f9be4c77cd5b211aaZbigniew Jędrzejewski-Szmek } else if (dns_packet_validate_query(p) > 0) {
62e3d1aed512d68cab1fc9b509e813a1fa2b3790Lennart Poettering l = hashmap_get(m->links, INT_TO_PTR(p->ifindex));
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt static const int one = 1, pmtu = IP_PMTUDISC_DONT, ttl = 255;
da6fe470e17fa02f3adedc779585caf8669252bdPatrik Flykt m->llmnr_ipv4_udp_fd = socket(AF_INET, SOCK_DGRAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0);
da6fe470e17fa02f3adedc779585caf8669252bdPatrik Flykt /* RFC 4795, section 2.5 recommends setting the TTL of UDP packets to 255. */
da6fe470e17fa02f3adedc779585caf8669252bdPatrik Flykt r = setsockopt(m->llmnr_ipv4_udp_fd, IPPROTO_IP, IP_TTL, &ttl, sizeof(ttl));
da6fe470e17fa02f3adedc779585caf8669252bdPatrik Flykt if (r < 0) {
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt r = setsockopt(m->llmnr_ipv4_udp_fd, IPPROTO_IP, IP_MULTICAST_TTL, &ttl, sizeof(ttl));
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt if (r < 0) {
r = -errno;
goto fail;
r = -errno;
goto fail;
r = -errno;
goto fail;
r = -errno;
goto fail;
r = -errno;
goto fail;
r = -errno;
goto fail;
r = -errno;
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);
goto fail;
return m->llmnr_ipv4_udp_fd;
fail:
assert(m);
if (m->llmnr_ipv6_udp_fd >= 0)
return m->llmnr_ipv6_udp_fd;
if (m->llmnr_ipv6_udp_fd < 0)
return -errno;
r = -errno;
goto fail;
r = -errno;
goto fail;
r = -errno;
goto fail;
r = -errno;
goto fail;
r = -errno;
goto fail;
r = -errno;
goto fail;
r = -errno;
goto fail;
r = -errno;
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 = -errno;
goto fail;
return m->llmnr_ipv6_udp_fd;
fail:
assert(s);
Link *l;
if (scope) {
if (s->write_packet)
dns_stream_free(s);
int cfd, r;
if (cfd < 0) {
return -errno;
assert(m);
if (m->llmnr_ipv4_tcp_fd >= 0)
return m->llmnr_ipv4_tcp_fd;
if (m->llmnr_ipv4_tcp_fd < 0)
return -errno;
r = -errno;
goto fail;
r = -errno;
goto fail;
r = -errno;
goto fail;
r = -errno;
goto fail;
r = -errno;
goto fail;
r = -errno;
goto fail;
r = -errno;
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);
goto fail;
return m->llmnr_ipv4_tcp_fd;
fail:
assert(m);
if (m->llmnr_ipv6_tcp_fd >= 0)
return m->llmnr_ipv6_tcp_fd;
if (m->llmnr_ipv6_tcp_fd < 0)
return -errno;
r = -errno;
goto fail;
r = -errno;
goto fail;
r = -errno;
goto fail;
r = -errno;
goto fail;
r = -errno;
goto fail;
r = -errno;
goto fail;
r = -errno;
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);
r = -errno;
goto fail;
return m->llmnr_ipv6_tcp_fd;
fail:
Link *l;
assert(m);
if (ifindex <= 0)
return -EINVAL;
LinkAddress *a;
assert(m);
Iterator i;
Link *l;
assert(m);
link_add_rrs(l, true);
link_add_rrs(l, false);
uint64_t u;
assert(m);
assert(p);
while (p > m->hostname) {
if (*p == 0 || safe_atou64(p, &u) < 0 || u <= 0)
return -ENOMEM;
m->hostname = h;
LinkAddress* manager_find_link_address(Manager *m, int family, const union in_addr_union *in_addr) {
Iterator i;
Link *l;
assert(m);
LinkAddress *a;
return NULL;
assert(m);
assert(p);