091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen This file is part of systemd.
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen Copyright 2014 Tom Gundersen <teg@jklm.no>
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen systemd is free software; you can redistribute it and/or modify it
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen under the terms of the GNU Lesser General Public License as published by
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen the Free Software Foundation; either version 2.1 of the License, or
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen (at your option) any later version.
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen systemd is distributed in the hope that it will be useful, but
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen WITHOUT ANY WARRANTY; without even the implied warranty of
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen Lesser General Public License for more details.
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen You should have received a copy of the GNU Lesser General Public License
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen along with systemd; If not, see <http://www.gnu.org/licenses/>.
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering#define SEND_TIMEOUT_USEC (200 * USEC_PER_MSEC)
1c4baffc1895809bae9ac36b670af90a4cb9cd7dTom Gundersenstatic int manager_process_link(sd_netlink *rtnl, sd_netlink_message *mm, void *userdata) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering r = sd_rtnl_message_link_get_ifindex(mm, &ifindex);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering l = hashmap_get(m->links, INT_TO_PTR(ifindex));
a2a416f768e2aa7db5b975cd50eb19237cac9cceLennart Poettering log_debug("Found new link %i/%s", ifindex, l->name);
a2a416f768e2aa7db5b975cd50eb19237cac9cceLennart Poettering log_debug("Removing link %i/%s", l->ifindex, l->name);
da927ba997d68401563b927f92e6e40e021a8e5cMichal Schmidt log_warning_errno(r, "Failed to process RTNL link message: %m");
1c4baffc1895809bae9ac36b670af90a4cb9cd7dTom Gundersenstatic int manager_process_address(sd_netlink *rtnl, sd_netlink_message *mm, void *userdata) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering r = sd_rtnl_message_addr_get_ifindex(mm, &ifindex);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering l = hashmap_get(m->links, INT_TO_PTR(ifindex));
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering r = sd_rtnl_message_addr_get_family(mm, &family);
1c4baffc1895809bae9ac36b670af90a4cb9cd7dTom Gundersen r = sd_netlink_message_read_in_addr(mm, IFA_LOCAL, &address.in);
1c4baffc1895809bae9ac36b670af90a4cb9cd7dTom Gundersen r = sd_netlink_message_read_in_addr(mm, IFA_ADDRESS, &address.in);
1c4baffc1895809bae9ac36b670af90a4cb9cd7dTom Gundersen r = sd_netlink_message_read_in6_addr(mm, IFA_LOCAL, &address.in6);
1c4baffc1895809bae9ac36b670af90a4cb9cd7dTom Gundersen r = sd_netlink_message_read_in6_addr(mm, IFA_ADDRESS, &address.in6);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering a = link_find_address(l, family, &address);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering r = link_address_new(l, &a, family, &address);
da927ba997d68401563b927f92e6e40e021a8e5cMichal Schmidt log_warning_errno(r, "Failed to process RTNL address message: %m");
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poetteringstatic int manager_rtnl_listen(Manager *m) {
4afd3348c7506dd1d36305b7bcb9feb8952b9d6bLennart Poettering _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL, *reply = NULL;
cc98b3025eeb89addb76a27390cb2baca4eab8b9Torstein Husebø /* First, subscribe to interfaces coming and going */
2d8950384f3137aafcce22b29912b2b61e6d86fbLennart Poettering r = sd_netlink_attach_event(m->rtnl, m->event, SD_EVENT_PRIORITY_IMPORTANT);
1c4baffc1895809bae9ac36b670af90a4cb9cd7dTom Gundersen r = sd_netlink_add_match(m->rtnl, RTM_NEWLINK, manager_process_link, m);
1c4baffc1895809bae9ac36b670af90a4cb9cd7dTom Gundersen r = sd_netlink_add_match(m->rtnl, RTM_DELLINK, manager_process_link, m);
1c4baffc1895809bae9ac36b670af90a4cb9cd7dTom Gundersen r = sd_netlink_add_match(m->rtnl, RTM_NEWADDR, manager_process_address, m);
1c4baffc1895809bae9ac36b670af90a4cb9cd7dTom Gundersen r = sd_netlink_add_match(m->rtnl, RTM_DELADDR, manager_process_address, m);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering /* Then, enumerate all links */
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering r = sd_rtnl_message_new_link(m->rtnl, &req, RTM_GETLINK, 0);
1c4baffc1895809bae9ac36b670af90a4cb9cd7dTom Gundersen r = sd_netlink_message_request_dump(req, true);
1c4baffc1895809bae9ac36b670af90a4cb9cd7dTom Gundersen for (i = reply; i; i = sd_netlink_message_next(i)) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering /* Finally, enumerate all addresses, too */
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering r = sd_rtnl_message_new_addr(m->rtnl, &req, RTM_GETADDR, 0, AF_UNSPEC);
1c4baffc1895809bae9ac36b670af90a4cb9cd7dTom Gundersen r = sd_netlink_message_request_dump(req, true);
1c4baffc1895809bae9ac36b670af90a4cb9cd7dTom Gundersen for (i = reply; i; i = sd_netlink_message_next(i)) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering r = manager_process_address(m->rtnl, i, m);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poetteringstatic int on_network_event(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering sd_network_monitor_flush(m->network_monitor);
da927ba997d68401563b927f92e6e40e021a8e5cMichal Schmidt log_warning_errno(r, "Failed to update monitor information for %i: %m", l->ifindex);
77abf3c1159a0326d05dba9cc7475d947fde0aa0Zbigniew Jędrzejewski-Szmek log_warning_errno(r, "Could not update "PRIVATE_RESOLV_CONF": %m");
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poetteringstatic int manager_network_monitor_listen(Manager *m) {
0014a4ad505d119c7ac4346d9d774c3f17f663a5Lennart Poettering r = sd_network_monitor_new(&m->network_monitor, NULL);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering fd = sd_network_monitor_get_fd(m->network_monitor);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering events = sd_network_monitor_get_events(m->network_monitor);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering r = sd_event_add_io(m->event, &m->network_event_source, fd, events, &on_network_event, m);
2d8950384f3137aafcce22b29912b2b61e6d86fbLennart Poettering r = sd_event_source_set_priority(m->network_event_source, SD_EVENT_PRIORITY_IMPORTANT+5);
aa4a9deb7d3db95ffb1fd18791be66f58d06a69eLennart Poettering (void) sd_event_source_set_description(m->network_event_source, "network-monitor");
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poetteringstatic int determine_hostname(char **llmnr_hostname, char **mdns_hostname) {
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering _cleanup_free_ char *h = NULL, *n = NULL;
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering const char *p;
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering /* Extract and normalize the first label of the locally
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering * configured hostname, and check it's not "localhost". */
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering r = dns_label_unescape(&p, label, sizeof(label));
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering return log_error_errno(r, "Failed to unescape host name: %m");
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering log_error("Couldn't find a single label in hosntame.");
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering k = dns_label_undo_idna(label, r, label, sizeof(label));
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering return log_error_errno(k, "Failed to undo IDNA: %m");
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering log_error("System hostname is not UTF-8 clean.");
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering return log_error_errno(r, "Failed to escape host name: %m");
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering log_debug("System hostname is 'localhost', ignoring.");
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering r = dns_name_concat(n, "local", mdns_hostname);
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering return log_error_errno(r, "Failed to determine mDNS hostname: %m");
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poetteringstatic int on_hostname_change(sd_event_source *es, int fd, uint32_t revents, void *userdata) {
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering _cleanup_free_ char *llmnr_hostname = NULL, *mdns_hostname = NULL;
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering r = determine_hostname(&llmnr_hostname, &mdns_hostname);
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering return 0; /* ignore invalid hostnames */
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering if (streq(llmnr_hostname, m->llmnr_hostname) && streq(mdns_hostname, m->mdns_hostname))
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering log_info("System hostname changed to '%s'.", llmnr_hostname);
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poetteringstatic int manager_watch_hostname(Manager *m) {
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering m->hostname_fd = open("/proc/sys/kernel/hostname", O_RDONLY|O_CLOEXEC|O_NDELAY|O_NOCTTY);
56f64d95763a799ba4475daf44d8e9f72a1bd474Michal Schmidt log_warning_errno(errno, "Failed to watch hostname: %m");
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering r = sd_event_add_io(m->event, &m->hostname_event_source, m->hostname_fd, 0, on_hostname_change, m);
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering /* kernels prior to 3.2 don't support polling this file. Ignore the failure. */
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering m->hostname_fd = safe_close(m->hostname_fd);
8d3d7072e609ef0e0fb37e1d19a29307d58146c3Michal Schmidt return log_error_errno(r, "Failed to add hostname event source: %m");
aa4a9deb7d3db95ffb1fd18791be66f58d06a69eLennart Poettering (void) sd_event_source_set_description(m->hostname_event_source, "hostname");
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering r = determine_hostname(&m->llmnr_hostname, &m->mdns_hostname);
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering log_info("Defaulting to hostname 'linux'.");
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering m->mdns_hostname = strdup("linux.local");
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering log_info("Using system hostname '%s'.", m->llmnr_hostname);
4d506d6bb757af3b99e0876234c465e6898c5ea4Lennart Poetteringstatic int manager_sigusr1(sd_event_source *s, const struct signalfd_siginfo *si, void *userdata) {
4d506d6bb757af3b99e0876234c465e6898c5ea4Lennart Poettering LIST_FOREACH(scopes, scope, m->dns_scopes)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering _cleanup_(manager_freep) Manager *m = NULL;
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering m->llmnr_ipv4_udp_fd = m->llmnr_ipv6_udp_fd = -1;
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering m->llmnr_ipv4_tcp_fd = m->llmnr_ipv6_tcp_fd = -1;
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering m->etc_hosts_last = m->etc_hosts_mtime = USEC_INFINITY;
0d2cd47617b423f37d7425be7a56ae2fca8ff9f6Lennart Poettering r = dns_trust_anchor_load(&m->trust_anchor);
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen sd_event_add_signal(m->event, NULL, SIGTERM, NULL, NULL);
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen sd_event_add_signal(m->event, NULL, SIGINT, NULL, NULL);
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering r = dns_scope_new(m, &m->unicast_scope, NULL, DNS_PROTOCOL_DNS, AF_UNSPEC);
4d506d6bb757af3b99e0876234c465e6898c5ea4Lennart Poettering (void) sd_event_add_signal(m->event, &m->sigusr1_event_source, SIGUSR1, manager_sigusr1, m);
4b95f1798f22c1bb75295f448188560cb6ec9eceLennart Poettering dns_server_unlink_all(m->fallback_dns_servers);
a51c10485af349eb15faa4d1a63b9818bcf3e589Lennart Poettering dns_search_domain_unlink_all(m->search_domains);
096b6773886bd7a0c8c97aa684b0b67dfae58355Lennart Poettering sd_event_source_unref(m->network_event_source);
096b6773886bd7a0c8c97aa684b0b67dfae58355Lennart Poettering sd_network_monitor_unref(m->network_monitor);
a564ca2fd113b2876e677beab60b38d50591e246Lennart Poettering sd_event_source_unref(m->rtnl_event_source);
902bb5d8abb2a7d258741828d212ca549ab16950Lennart Poettering sd_bus_slot_unref(m->prepare_for_sleep_slot);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering sd_event_source_unref(m->bus_retry_event_source);
4d506d6bb757af3b99e0876234c465e6898c5ea4Lennart Poettering sd_event_source_unref(m->sigusr1_event_source);
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering dns_resource_key_unref(m->llmnr_host_ipv4_key);
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering dns_resource_key_unref(m->llmnr_host_ipv6_key);
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering sd_event_source_unref(m->hostname_event_source);
0d2cd47617b423f37d7425be7a56ae2fca8ff9f6Lennart Poettering dns_trust_anchor_flush(&m->trust_anchor);
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poetteringint manager_recv(Manager *m, int fd, DnsProtocol protocol, DnsPacket **ret) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering _cleanup_(dns_packet_unrefp) DnsPacket *p = NULL;
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering struct cmsghdr header; /* For alignment */
40a1eebde6be7ac3f1885147fc24e06ad1da260cDavid Herrmann uint8_t buffer[CMSG_SPACE(MAXSIZE(struct in_pktinfo, struct in6_pktinfo))
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering + EXTRA_CMSG_SPACE /* kernel appears to require extra buffer space */];
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering p->sender_port = be16toh(sa.in.sin_port);
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering p->sender_port = be16toh(sa.in6.sin6_port);
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering struct in6_pktinfo *i = (struct in6_pktinfo*) CMSG_DATA(cmsg);
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering } else if (cmsg->cmsg_level == IPPROTO_IP) {
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering struct in_pktinfo *i = (struct in_pktinfo*) CMSG_DATA(cmsg);
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering /* The Linux kernel sets the interface index to the loopback
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering * device if the packet came from the local host since it
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering * avoids the routing table in such a case. Let's unset the
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering * interface index in such a case. */
86ad4cd709ced8daf2b75ab564dece1ce82ffed9Tom Gundersen /* If we don't know the interface index still, we look for the
86ad4cd709ced8daf2b75ab564dece1ce82ffed9Tom Gundersen * first local interface with a matching address. Yuck! */
86ad4cd709ced8daf2b75ab564dece1ce82ffed9Tom Gundersen p->ifindex = manager_find_ifindex(m, p->family, &p->destination);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poetteringstatic int sendmsg_loop(int fd, struct msghdr *mh, int flags) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering r = fd_wait_for_event(fd, POLLOUT, SEND_TIMEOUT_USEC);
72290734be81e83e6ef9520c07692f68095eb5b2Tom Gundersenstatic int write_loop(int fd, void *message, size_t length) {
72290734be81e83e6ef9520c07692f68095eb5b2Tom Gundersen r = fd_wait_for_event(fd, POLLOUT, SEND_TIMEOUT_USEC);
72290734be81e83e6ef9520c07692f68095eb5b2Tom Gundersenint manager_write(Manager *m, int fd, DnsPacket *p) {
deb3f3d335d64601bb2d8a7520d8303f99d8a071Lennart Poettering log_debug("Sending %s packet with id %" PRIu16 ".", DNS_PACKET_QR(p) ? "response" : "query", DNS_PACKET_ID(p));
72290734be81e83e6ef9520c07692f68095eb5b2Tom Gundersen r = write_loop(fd, DNS_PACKET_DATA(p), p->size);
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poetteringstatic int manager_ipv4_send(Manager *m, int fd, int ifindex, const struct in_addr *addr, uint16_t port, DnsPacket *p) {
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering struct cmsghdr header; /* For alignment */
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering uint8_t buffer[CMSG_SPACE(sizeof(struct in_pktinfo))];
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering mh.msg_controllen = CMSG_LEN(sizeof(struct in_pktinfo));
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering pi = (struct in_pktinfo*) CMSG_DATA(cmsg);
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poetteringstatic int manager_ipv6_send(Manager *m, int fd, int ifindex, const struct in6_addr *addr, uint16_t port, DnsPacket *p) {
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering struct cmsghdr header; /* For alignment */
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering uint8_t buffer[CMSG_SPACE(sizeof(struct in6_pktinfo))];
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering mh.msg_controllen = CMSG_LEN(sizeof(struct in6_pktinfo));
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering pi = (struct in6_pktinfo*) CMSG_DATA(cmsg);
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poetteringint manager_send(Manager *m, int fd, int ifindex, int family, const union in_addr_union *addr, uint16_t port, DnsPacket *p) {
deb3f3d335d64601bb2d8a7520d8303f99d8a071Lennart Poettering log_debug("Sending %s packet with id %" PRIu16 " on interface %i/%s.", DNS_PACKET_QR(p) ? "response" : "query", DNS_PACKET_ID(p), ifindex, af_to_name(family));
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering return manager_ipv4_send(m, fd, ifindex, &addr->in, port, p);
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering return manager_ipv6_send(m, fd, ifindex, &addr->in6, port, p);
e1c959948c0e31d6997bcdfbabfbd077784b2baeLennart Poettering /* If we don't know on which link a DNS packet would be
e1c959948c0e31d6997bcdfbabfbd077784b2baeLennart Poettering * delivered, let's find the largest MTU that works on all
e1c959948c0e31d6997bcdfbabfbd077784b2baeLennart Poettering * interfaces we know of */
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poetteringint manager_find_ifindex(Manager *m, int family, const union in_addr_union *in_addr) {
4e945a6f7971fd7d1f6b2c62ee3afdaff3c95ce4Lennart Poettering a = manager_find_link_address(m, family, in_addr);
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering m->llmnr_host_ipv4_key = dns_resource_key_unref(m->llmnr_host_ipv4_key);
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering m->llmnr_host_ipv6_key = dns_resource_key_unref(m->llmnr_host_ipv6_key);
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering const char *p;
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering while (p > m->llmnr_hostname) {
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering if (*p == 0 || safe_atou64(p, &u) < 0 || u <= 0)
556a22945fcc88ca27ae7ecc46c9bb2727e37895Lennart Poettering /* Add a random number to the old value. This way we can avoid
556a22945fcc88ca27ae7ecc46c9bb2727e37895Lennart Poettering * that two hosts pick the same hostname, win on IPv4 and lose
556a22945fcc88ca27ae7ecc46c9bb2727e37895Lennart Poettering * on IPv6 (or vice versa), and pick the same hostname
556a22945fcc88ca27ae7ecc46c9bb2727e37895Lennart Poettering * replacement hostname, ad infinitum. We still want the
556a22945fcc88ca27ae7ecc46c9bb2727e37895Lennart Poettering * numbers to go up monotonically, hence we just add a random
556a22945fcc88ca27ae7ecc46c9bb2727e37895Lennart Poettering * value 1..10 */
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering if (asprintf(&h, "%.*s%" PRIu64, (int) (p - m->llmnr_hostname), m->llmnr_hostname, u) < 0)
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering log_info("Hostname conflict, changing published hostname from '%s' to '%s'.", m->llmnr_hostname, h);
4e945a6f7971fd7d1f6b2c62ee3afdaff3c95ce4Lennart PoetteringLinkAddress* manager_find_link_address(Manager *m, int family, const union in_addr_union *in_addr) {
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering a = link_find_address(l, family, in_addr);
a407657425a3e47fd2b559cd3bc800f791303f63Lennart Poetteringbool manager_our_packet(Manager *m, DnsPacket *p) {
4e945a6f7971fd7d1f6b2c62ee3afdaff3c95ce4Lennart Poettering return !!manager_find_link_address(m, p->family, &p->sender);
a407657425a3e47fd2b559cd3bc800f791303f63Lennart PoetteringDnsScope* manager_find_scope(Manager *m, DnsPacket *p) {
a407657425a3e47fd2b559cd3bc800f791303f63Lennart Poettering l = hashmap_get(m->links, INT_TO_PTR(p->ifindex));
b4f1862df2e45aba90386887d685b8bf3c840e10Daniel Mack switch (p->protocol) {
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poetteringint manager_is_own_hostname(Manager *m, const char *name) {
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering r = dns_name_equal(name, m->llmnr_hostname);
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering return dns_name_equal(name, m->mdns_hostname);
9176a57c101d51b4a7fb4141240b5ce03abac57dLennart Poetteringint manager_compile_dns_servers(Manager *m, OrderedSet **dns) {
9176a57c101d51b4a7fb4141240b5ce03abac57dLennart Poettering r = ordered_set_ensure_allocated(dns, &dns_server_hash_ops);
9176a57c101d51b4a7fb4141240b5ce03abac57dLennart Poettering /* First add the system-wide servers and domains */
9176a57c101d51b4a7fb4141240b5ce03abac57dLennart Poettering LIST_FOREACH(servers, s, m->dns_servers) {
9176a57c101d51b4a7fb4141240b5ce03abac57dLennart Poettering /* Then, add the per-link servers */
9176a57c101d51b4a7fb4141240b5ce03abac57dLennart Poettering LIST_FOREACH(servers, s, l->dns_servers) {
9176a57c101d51b4a7fb4141240b5ce03abac57dLennart Poettering /* If we found nothing, add the fallback servers */
9176a57c101d51b4a7fb4141240b5ce03abac57dLennart Poettering LIST_FOREACH(servers, s, m->fallback_dns_servers) {
9176a57c101d51b4a7fb4141240b5ce03abac57dLennart Poetteringint manager_compile_search_domains(Manager *m, OrderedSet **domains) {
9176a57c101d51b4a7fb4141240b5ce03abac57dLennart Poettering r = ordered_set_ensure_allocated(domains, &dns_name_hash_ops);
9176a57c101d51b4a7fb4141240b5ce03abac57dLennart Poettering LIST_FOREACH(domains, d, m->search_domains) {
9176a57c101d51b4a7fb4141240b5ce03abac57dLennart Poettering LIST_FOREACH(domains, d, l->search_domains) {
c69fa7e3c44240bedc0ee1bd89fecf954783ac85Lennart PoetteringDnssecMode manager_get_dnssec_mode(Manager *m) {
c69fa7e3c44240bedc0ee1bd89fecf954783ac85Lennart Poettering if (m->dnssec_mode != _DNSSEC_MODE_INVALID)
c69fa7e3c44240bedc0ee1bd89fecf954783ac85Lennart Poetteringbool manager_dnssec_supported(Manager *m) {
c69fa7e3c44240bedc0ee1bd89fecf954783ac85Lennart Poettering if (manager_get_dnssec_mode(m) == DNSSEC_NO)
c69fa7e3c44240bedc0ee1bd89fecf954783ac85Lennart Poettering if (server && !dns_server_dnssec_supported(server))
59c5b5974d106c5ebad080739b41d0e92ab74d29Lennart Poetteringvoid manager_dnssec_verdict(Manager *m, DnssecVerdict verdict, const DnsResourceKey *key) {
59c5b5974d106c5ebad080739b41d0e92ab74d29Lennart Poettering (void) dns_resource_key_to_string(key, &s);
59c5b5974d106c5ebad080739b41d0e92ab74d29Lennart Poettering log_debug("Found verdict for lookup %s: %s", s ? strstrip(s) : "n/a", dnssec_verdict_to_string(verdict));
011696f76233486bc56c266b18a328924f70269cLennart Poetteringbool manager_routable(Manager *m, int family) {
011696f76233486bc56c266b18a328924f70269cLennart Poettering /* Returns true if the host has at least one interface with a routable address of the specified type */