[systemd-commits] 6 commits - Makefile.am configure.ac src/network src/nss-resolve src/resolve src/resolve-host units/ldconfig.service

Lennart Poettering lennart at kemper.freedesktop.org
Wed Aug 13 16:19:24 PDT 2014


 Makefile.am                       |   17 +++-
 configure.ac                      |    5 +
 src/network/networkctl.c          |   96 ++++++++++++++------------
 src/nss-resolve/nss-resolve.c     |   78 +++++++++++++--------
 src/resolve-host/resolve-host.c   |  138 ++++++++++++++++++++++++++------------
 src/resolve/resolved-bus.c        |   97 +++++++++++++++++++-------
 src/resolve/resolved-def.h        |   30 ++++++++
 src/resolve/resolved-dns-packet.h |   14 +++
 src/resolve/resolved-dns-query.c  |   12 ++-
 src/resolve/resolved-dns-query.h  |    7 +
 src/resolve/resolved-dns-scope.c  |    8 +-
 src/resolve/resolved-dns-scope.h  |    2 
 src/resolve/resolved-link.c       |    5 -
 units/ldconfig.service            |    1 
 14 files changed, 357 insertions(+), 153 deletions(-)

New commits:
commit d57c365bf8f09fbcc649e00f7060ff30809f67c2
Author: Lennart Poettering <lennart at poettering.net>
Date:   Thu Aug 14 01:18:37 2014 +0200

    networkctl: add the same color logic to "list" and "status" outputs
    
    And always put operational state first, setup state second.

diff --git a/src/network/networkctl.c b/src/network/networkctl.c
index 3df5e8e..dc0bb4d 100644
--- a/src/network/networkctl.c
+++ b/src/network/networkctl.c
@@ -148,6 +148,37 @@ static int decode_and_sort_links(sd_rtnl_message *m, LinkInfo **ret) {
         return (int) c;
 }
 
+static void operational_state_to_color(const char *state, const char **on, const char **off) {
+        assert(on);
+        assert(off);
+
+        if (streq_ptr(state, "routable")) {
+                *on = ansi_highlight_green();
+                *off = ansi_highlight_off();
+        } else if (streq_ptr(state, "degraded")) {
+                *on = ansi_highlight_yellow();
+                *off = ansi_highlight_off();
+        } else
+                *on = *off = "";
+}
+
+static void setup_state_to_color(const char *state, const char **on, const char **off) {
+        assert(on);
+        assert(off);
+
+        if (streq_ptr(state, "configured")) {
+                *on = ansi_highlight_green();
+                *off = ansi_highlight_off();
+        } else if (streq_ptr(state, "configuring")) {
+                *on = ansi_highlight_yellow();
+                *off = ansi_highlight_off();
+        } else if (streq_ptr(state, "failed") || streq_ptr(state, "linger")) {
+                *on = ansi_highlight_red();
+                *off = ansi_highlight_off();
+        } else
+                *on = *off = "";
+}
+
 static int list_links(char **args, unsigned n) {
         _cleanup_rtnl_message_unref_ sd_rtnl_message *req = NULL, *reply = NULL;
         _cleanup_udev_unref_ struct udev *udev = NULL;
@@ -184,7 +215,7 @@ static int list_links(char **args, unsigned n) {
         }
 
         if (arg_legend)
-                printf("%3s %-16s %-10s %-11s %-10s\n", "IDX", "LINK", "TYPE", "SETUP", "OPERATIONAL");
+                printf("%3s %-16s %-10s %-11s %-10s\n", "IDX", "LINK", "TYPE", "OPERATIONAL", "SETUP");
 
         c = decode_and_sort_links(reply, &links);
         if (c < 0)
@@ -193,42 +224,26 @@ static int list_links(char **args, unsigned n) {
         for (i = 0; i < c; i++) {
                 _cleanup_free_ char *setup_state = NULL, *operational_state = NULL;
                 _cleanup_udev_device_unref_ struct udev_device *d = NULL;
-                const char *on_color_oper = "", *off_color_oper = "",
-                           *on_color = "", *off_color = "";
+                const char *on_color_operational, *off_color_operational,
+                           *on_color_setup, *off_color_setup;
                  char devid[2 + DECIMAL_STR_MAX(int)];
                 _cleanup_free_ char *t = NULL;
 
-                sd_network_link_get_setup_state(links[i].ifindex, &setup_state);
                 sd_network_link_get_operational_state(links[i].ifindex, &operational_state);
+                operational_state_to_color(operational_state, &on_color_operational, &off_color_operational);
+
+                sd_network_link_get_setup_state(links[i].ifindex, &setup_state);
+                setup_state_to_color(setup_state, &on_color_setup, &off_color_setup);
 
                 sprintf(devid, "n%i", links[i].ifindex);
                 d = udev_device_new_from_device_id(udev, devid);
 
                 link_get_type_string(links[i].iftype, d, &t);
 
-                if (streq_ptr(operational_state, "routable")) {
-                        on_color_oper = ansi_highlight_green();
-                        off_color_oper = ansi_highlight_off();
-                } else if (streq_ptr(operational_state, "degraded")) {
-                        on_color_oper = ansi_highlight_yellow();
-                        off_color_oper = ansi_highlight_off();
-                }
-
-                if (streq_ptr(setup_state, "configured")) {
-                        on_color = ansi_highlight_green();
-                        off_color = ansi_highlight_off();
-                } else if (streq_ptr(setup_state, "configuring")) {
-                        on_color = ansi_highlight_yellow();
-                        off_color = ansi_highlight_off();
-                } else if (streq_ptr(setup_state, "failed") ||
-                           streq_ptr(setup_state, "linger")) {
-                        on_color = ansi_highlight_red();
-                        off_color = ansi_highlight_off();
-                }
-
-                printf("%3i %-16s %-10s %s%-11s%s %s%-10s%s\n", links[i].ifindex,
-                       links[i].name, strna(t), on_color, strna(setup_state), off_color,
-                       on_color_oper, strna(operational_state), off_color_oper);
+                printf("%3i %-16s %-10s %s%-11s%s %s%-10s%s\n",
+                       links[i].ifindex, links[i].name, strna(t),
+                       on_color_operational, strna(operational_state), off_color_operational,
+                       on_color_setup, strna(setup_state), off_color_setup);
         }
 
         if (arg_legend)
@@ -280,7 +295,8 @@ static int link_status_one(sd_rtnl *rtnl, struct udev *udev, const char *name) {
         char devid[2 + DECIMAL_STR_MAX(int)];
         _cleanup_free_ char *t = NULL;
         const char *driver = NULL, *path = NULL, *vendor = NULL, *model = NULL;
-        const char *on_color = "", *off_color = "";
+        const char *on_color_operational, *off_color_operational,
+                   *on_color_setup, *off_color_setup;
         struct ether_addr e;
         unsigned iftype;
         int r, ifindex;
@@ -340,8 +356,11 @@ static int link_status_one(sd_rtnl *rtnl, struct udev *udev, const char *name) {
 
         sd_rtnl_message_read_u32(reply, IFLA_MTU, &mtu);
 
-        sd_network_link_get_setup_state(ifindex, &setup_state);
         sd_network_link_get_operational_state(ifindex, &operational_state);
+        operational_state_to_color(operational_state, &on_color_operational, &off_color_operational);
+
+        sd_network_link_get_setup_state(ifindex, &setup_state);
+        setup_state_to_color(setup_state, &on_color_setup, &off_color_setup);
 
         sd_network_link_get_dns(ifindex, &dns);
         sd_network_link_get_ntp(ifindex, &ntp);
@@ -364,21 +383,14 @@ static int link_status_one(sd_rtnl *rtnl, struct udev *udev, const char *name) {
                         model = udev_device_get_property_value(d, "ID_MODEL");
         }
 
-        if (streq_ptr(operational_state, "routable")) {
-                on_color = ansi_highlight_green();
-                off_color = ansi_highlight_off();
-        } else if (streq_ptr(operational_state, "degraded")) {
-                on_color = ansi_highlight_yellow();
-                off_color = ansi_highlight_off();
-        }
 
-        printf("%s%s%s %i: %s\n", on_color, draw_special_char(DRAW_BLACK_CIRCLE), off_color, ifindex, name);
+        printf("%s%s%s %i: %s\n", on_color_operational, draw_special_char(DRAW_BLACK_CIRCLE), off_color_operational, ifindex, name);
 
         printf("        Type: %s\n"
-               "       State: %s%s%s (%s)\n",
+               "       State: %s%s%s (%s%s%s)\n",
                strna(t),
-               on_color, strna(operational_state), off_color,
-               strna(setup_state));
+               on_color_operational, strna(operational_state), off_color_operational,
+               on_color_setup, strna(setup_state), off_color_setup);
 
         if (path)
                 printf("        Path: %s\n", path);

commit ab1525bc2d92780b4dc64bc5b9cdb52594e2df7d
Author: Lennart Poettering <lennart at poettering.net>
Date:   Thu Aug 14 01:10:08 2014 +0200

    networkctl: name setup state variable setup_state

diff --git a/src/network/networkctl.c b/src/network/networkctl.c
index b022f20..3df5e8e 100644
--- a/src/network/networkctl.c
+++ b/src/network/networkctl.c
@@ -191,14 +191,14 @@ static int list_links(char **args, unsigned n) {
                 return rtnl_log_parse_error(c);
 
         for (i = 0; i < c; i++) {
-                _cleanup_free_ char *state = NULL, *operational_state = NULL;
+                _cleanup_free_ char *setup_state = NULL, *operational_state = NULL;
                 _cleanup_udev_device_unref_ struct udev_device *d = NULL;
                 const char *on_color_oper = "", *off_color_oper = "",
                            *on_color = "", *off_color = "";
                  char devid[2 + DECIMAL_STR_MAX(int)];
                 _cleanup_free_ char *t = NULL;
 
-                sd_network_link_get_setup_state(links[i].ifindex, &state);
+                sd_network_link_get_setup_state(links[i].ifindex, &setup_state);
                 sd_network_link_get_operational_state(links[i].ifindex, &operational_state);
 
                 sprintf(devid, "n%i", links[i].ifindex);
@@ -214,20 +214,20 @@ static int list_links(char **args, unsigned n) {
                         off_color_oper = ansi_highlight_off();
                 }
 
-                if (streq_ptr(state, "configured")) {
+                if (streq_ptr(setup_state, "configured")) {
                         on_color = ansi_highlight_green();
                         off_color = ansi_highlight_off();
-                } else if (streq_ptr(state, "configuring")) {
+                } else if (streq_ptr(setup_state, "configuring")) {
                         on_color = ansi_highlight_yellow();
                         off_color = ansi_highlight_off();
-                } else if (streq_ptr(state, "failed") ||
-                           streq_ptr(state, "linger")) {
+                } else if (streq_ptr(setup_state, "failed") ||
+                           streq_ptr(setup_state, "linger")) {
                         on_color = ansi_highlight_red();
                         off_color = ansi_highlight_off();
                 }
 
                 printf("%3i %-16s %-10s %s%-11s%s %s%-10s%s\n", links[i].ifindex,
-                       links[i].name, strna(t), on_color, strna(state), off_color,
+                       links[i].name, strna(t), on_color, strna(setup_state), off_color,
                        on_color_oper, strna(operational_state), off_color_oper);
         }
 
@@ -274,7 +274,7 @@ static void dump_list(const char *prefix, char **l) {
 
 static int link_status_one(sd_rtnl *rtnl, struct udev *udev, const char *name) {
         _cleanup_strv_free_ char **dns = NULL, **ntp = NULL;
-        _cleanup_free_ char *state = NULL, *operational_state = NULL;
+        _cleanup_free_ char *setup_state = NULL, *operational_state = NULL;
         _cleanup_rtnl_message_unref_ sd_rtnl_message *req = NULL, *reply = NULL;
         _cleanup_udev_device_unref_ struct udev_device *d = NULL;
         char devid[2 + DECIMAL_STR_MAX(int)];
@@ -340,7 +340,7 @@ static int link_status_one(sd_rtnl *rtnl, struct udev *udev, const char *name) {
 
         sd_rtnl_message_read_u32(reply, IFLA_MTU, &mtu);
 
-        sd_network_link_get_setup_state(ifindex, &state);
+        sd_network_link_get_setup_state(ifindex, &setup_state);
         sd_network_link_get_operational_state(ifindex, &operational_state);
 
         sd_network_link_get_dns(ifindex, &dns);
@@ -378,7 +378,7 @@ static int link_status_one(sd_rtnl *rtnl, struct udev *udev, const char *name) {
                "       State: %s%s%s (%s)\n",
                strna(t),
                on_color, strna(operational_state), off_color,
-               strna(state));
+               strna(setup_state));
 
         if (path)
                 printf("        Path: %s\n", path);

commit 2368512a31f55e107f0cfb6e68cd4057648fd2de
Author: Lennart Poettering <lennart at poettering.net>
Date:   Thu Aug 14 01:08:46 2014 +0200

    networkctl: update column header to new 'setup' state naming

diff --git a/src/network/networkctl.c b/src/network/networkctl.c
index f83c1f3..b022f20 100644
--- a/src/network/networkctl.c
+++ b/src/network/networkctl.c
@@ -184,7 +184,7 @@ static int list_links(char **args, unsigned n) {
         }
 
         if (arg_legend)
-                printf("%3s %-16s %-10s %-11s %-10s\n", "IDX", "LINK", "TYPE", "ADMIN", "OPERATIONAL");
+                printf("%3s %-16s %-10s %-11s %-10s\n", "IDX", "LINK", "TYPE", "SETUP", "OPERATIONAL");
 
         c = decode_and_sort_links(reply, &links);
         if (c < 0)

commit db97a66aa69925f7403ba3c433e86320d136567d
Author: Lennart Poettering <lennart at poettering.net>
Date:   Thu Aug 14 01:00:57 2014 +0200

    resolved: enable LLMNR
    
    THis was accidentally broken, as we truned off LLMNR far to frequently,
    where we only wanted to turn off LLMNr on IPV6 on kernels lacking
    support for it.

diff --git a/src/resolve/resolved-link.c b/src/resolve/resolved-link.c
index fea52d9..8ec180d 100644
--- a/src/resolve/resolved-link.c
+++ b/src/resolve/resolved-link.c
@@ -95,8 +95,7 @@ static void link_allocate_scopes(Link *l) {
 
         if (link_relevant(l, AF_INET) &&
             l->llmnr_support != SUPPORT_NO &&
-            l->manager->llmnr_support != SUPPORT_NO &&
-            l->manager->llmnr_ipv4_udp_fd >= 0) {
+            l->manager->llmnr_support != SUPPORT_NO) {
                 if (!l->llmnr_ipv4_scope) {
                         r = dns_scope_new(l->manager, &l->llmnr_ipv4_scope, l, DNS_PROTOCOL_LLMNR, AF_INET);
                         if (r < 0)
@@ -108,7 +107,7 @@ static void link_allocate_scopes(Link *l) {
         if (link_relevant(l, AF_INET6) &&
             l->llmnr_support != SUPPORT_NO &&
             l->manager->llmnr_support != SUPPORT_NO &&
-            l->manager->llmnr_ipv6_udp_fd >= 0) {
+            socket_ipv6_is_supported()) {
                 if (!l->llmnr_ipv6_scope) {
                         r = dns_scope_new(l->manager, &l->llmnr_ipv6_scope, l, DNS_PROTOCOL_LLMNR, AF_INET6);
                         if (r < 0)

commit 51323288fc628a5cac50914df915545d685b793e
Author: Lennart Poettering <lennart at poettering.net>
Date:   Thu Aug 14 01:00:15 2014 +0200

    resolved: allow passing on which protocol, family and interface to look something up
    
    Also, return on which protocol/family/interface we found something.

diff --git a/Makefile.am b/Makefile.am
index 513c852..b95ddf2 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -4781,6 +4781,7 @@ systemd_resolved_SOURCES = \
 	src/resolve/resolved-bus.h \
 	src/resolve/resolved-link.h \
 	src/resolve/resolved-link.c \
+	src/resolve/resolved-def.h \
 	src/resolve/resolved-dns-domain.h \
 	src/resolve/resolved-dns-domain.c \
 	src/resolve/resolved-dns-rr.h \
diff --git a/src/nss-resolve/nss-resolve.c b/src/nss-resolve/nss-resolve.c
index ccbc731..bc55acf 100644
--- a/src/nss-resolve/nss-resolve.c
+++ b/src/nss-resolve/nss-resolve.c
@@ -66,23 +66,27 @@ static bool bus_error_shall_fallback(sd_bus_error *e) {
 }
 
 static int count_addresses(sd_bus_message *m, int af, const char **canonical) {
-        int c = 0, r;
+        int c = 0, r, ifindex;
 
         assert(m);
         assert(canonical);
 
-        r = sd_bus_message_enter_container(m, 'a', "(iayi)");
+        r = sd_bus_message_read(m, "i", &ifindex);
         if (r < 0)
                 return r;
 
-        while ((r = sd_bus_message_enter_container(m, 'r', "iayi")) > 0) {
+        r = sd_bus_message_enter_container(m, 'a', "(iay)");
+        if (r < 0)
+                return r;
+
+        while ((r = sd_bus_message_enter_container(m, 'r', "iay")) > 0) {
                 int family;
 
                 r = sd_bus_message_read(m, "i", &family);
                 if (r < 0)
                         return r;
 
-                r = sd_bus_message_skip(m, "ayi");
+                r = sd_bus_message_skip(m, "ay");
                 if (r < 0)
                         return r;
 
@@ -127,7 +131,7 @@ enum nss_status _nss_resolve_gethostbyname4_r(
         const char *canonical = NULL;
         size_t l, ms, idx;
         char *r_name;
-        int c, r, i = 0;
+        int c, r, i = 0, ifindex;
 
         assert(name);
         assert(pat);
@@ -153,7 +157,7 @@ enum nss_status _nss_resolve_gethostbyname4_r(
         if (r < 0)
                 goto fail;
 
-        r = sd_bus_message_append(req, "si", name, AF_UNSPEC);
+        r = sd_bus_message_append(req, "isit", 0, name, AF_UNSPEC, (uint64_t) 0);
         if (r < 0)
                 goto fail;
 
@@ -219,12 +223,21 @@ enum nss_status _nss_resolve_gethostbyname4_r(
         /* Second, append addresses */
         r_tuple_first = (struct gaih_addrtuple*) (buffer + idx);
 
-        r = sd_bus_message_enter_container(reply, 'a', "(iayi)");
+        r = sd_bus_message_read(reply, "i", &ifindex);
+        if (r < 0)
+                goto fail;
+
+        if (ifindex < 0) {
+                r = -EINVAL;
+                goto fail;
+        }
+
+        r = sd_bus_message_enter_container(reply, 'a', "(iay)");
         if (r < 0)
                 goto fail;
 
-        while ((r = sd_bus_message_enter_container(reply, 'r', "iayi")) > 0) {
-                int family, ifindex;
+        while ((r = sd_bus_message_enter_container(reply, 'r', "iay")) > 0) {
+                int family;
                 const void *a;
                 size_t sz;
 
@@ -236,10 +249,6 @@ enum nss_status _nss_resolve_gethostbyname4_r(
                 if (r < 0)
                         goto fail;
 
-                r = sd_bus_message_read(reply, "i", &ifindex);
-                if (r < 0)
-                        goto fail;
-
                 r = sd_bus_message_exit_container(reply);
                 if (r < 0)
                         goto fail;
@@ -252,11 +261,6 @@ enum nss_status _nss_resolve_gethostbyname4_r(
                         goto fail;
                 }
 
-                if (ifindex < 0) {
-                        r = -EINVAL;
-                        goto fail;
-                }
-
                 r_tuple = (struct gaih_addrtuple*) (buffer + idx);
                 r_tuple->next = i == c-1 ? NULL : (struct gaih_addrtuple*) ((char*) r_tuple + ALIGN(sizeof(struct gaih_addrtuple)));
                 r_tuple->name = r_name;
@@ -309,7 +313,7 @@ enum nss_status _nss_resolve_gethostbyname3_r(
         _cleanup_bus_close_unref_ sd_bus *bus = NULL;
         size_t l, idx, ms, alen;
         const char *canonical;
-        int c, r, i = 0;
+        int c, r, i = 0, ifindex;
 
         assert(name);
         assert(result);
@@ -343,7 +347,7 @@ enum nss_status _nss_resolve_gethostbyname3_r(
         if (r < 0)
                 goto fail;
 
-        r = sd_bus_message_append(req, "si", name, af);
+        r = sd_bus_message_append(req, "isit", 0, name, af, (uint64_t) 0);
         if (r < 0)
                 goto fail;
 
@@ -424,12 +428,21 @@ enum nss_status _nss_resolve_gethostbyname3_r(
         /* Third, append addresses */
         r_addr = buffer + idx;
 
-        r = sd_bus_message_enter_container(reply, 'a', "(iayi)");
+        r = sd_bus_message_read(reply, "i", &ifindex);
         if (r < 0)
                 goto fail;
 
-        while ((r = sd_bus_message_enter_container(reply, 'r', "iayi")) > 0) {
-                int family, ifindex;
+        if (ifindex < 0) {
+                r = -EINVAL;
+                goto fail;
+        }
+
+        r = sd_bus_message_enter_container(reply, 'a', "(iay)");
+        if (r < 0)
+                goto fail;
+
+        while ((r = sd_bus_message_enter_container(reply, 'r', "iay")) > 0) {
+                int family;
                 const void *a;
                 size_t sz;
 
@@ -441,10 +454,6 @@ enum nss_status _nss_resolve_gethostbyname3_r(
                 if (r < 0)
                         goto fail;
 
-                r = sd_bus_message_read(reply, "i", &ifindex);
-                if (r < 0)
-                        goto fail;
-
                 r = sd_bus_message_exit_container(reply);
                 if (r < 0)
                         goto fail;
@@ -521,7 +530,7 @@ enum nss_status _nss_resolve_gethostbyaddr2_r(
         unsigned c = 0, i = 0;
         size_t ms = 0, idx;
         const char *n;
-        int r;
+        int r, ifindex;
 
         assert(addr);
         assert(result);
@@ -559,7 +568,7 @@ enum nss_status _nss_resolve_gethostbyaddr2_r(
         if (r < 0)
                 goto fail;
 
-        r = sd_bus_message_append(req, "i", af);
+        r = sd_bus_message_append(req, "ii", 0, af);
         if (r < 0)
                 goto fail;
 
@@ -567,7 +576,7 @@ enum nss_status _nss_resolve_gethostbyaddr2_r(
         if (r < 0)
                 goto fail;
 
-        r = sd_bus_message_append(req, "i", 0);
+        r = sd_bus_message_append(req, "t", (uint64_t) 0);
         if (r < 0)
                 goto fail;
 
@@ -607,6 +616,15 @@ enum nss_status _nss_resolve_gethostbyaddr2_r(
                 return NSS_STATUS_UNAVAIL;
         }
 
+        r = sd_bus_message_read(reply, "i", &ifindex);
+        if (r < 0)
+                goto fail;
+
+        if (ifindex < 0) {
+                r = -EINVAL;
+                goto fail;
+        }
+
         r = sd_bus_message_enter_container(reply, 'a', "s");
         if (r < 0)
                 goto fail;
diff --git a/src/resolve-host/resolve-host.c b/src/resolve-host/resolve-host.c
index 3709268..c39b582 100644
--- a/src/resolve-host/resolve-host.c
+++ b/src/resolve-host/resolve-host.c
@@ -32,6 +32,7 @@
 #include "build.h"
 
 #include "resolved-dns-packet.h"
+#include "resolved-def.h"
 
 #define DNS_CALL_TIMEOUT_USEC (45*USEC_PER_SEC)
 
@@ -40,6 +41,32 @@ static int arg_ifindex = 0;
 static int arg_type = 0;
 static uint16_t arg_class = 0;
 static bool arg_legend = true;
+static uint64_t arg_flags = 0;
+
+static void print_source(int ifindex, uint64_t flags) {
+
+        if (!arg_legend)
+                return;
+
+        if (ifindex <= 0 && flags == 0)
+                return;
+
+        fputs("\n-- Information acquired via", stdout);
+
+        if (flags != 0)
+                printf(" protocol%s%s%s",
+                       flags & SD_RESOLVED_DNS ? " DNS" :"",
+                       flags & SD_RESOLVED_LLMNR_IPV4 ? " LLMNR/IPv4" : "",
+                       flags & SD_RESOLVED_LLMNR_IPV6 ? " LLMNR/IPv6" : "");
+
+        if (ifindex > 0) {
+                char ifname[IF_NAMESIZE] = "";
+                printf(" interface %s", strna(if_indextoname(ifindex, ifname)));
+        }
+
+        fputc('.', stdout);
+        fputc('\n', stdout);
+}
 
 static int resolve_host(sd_bus *bus, const char *name) {
 
@@ -47,7 +74,8 @@ static int resolve_host(sd_bus *bus, const char *name) {
         _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
         const char *canonical = NULL;
         unsigned c = 0;
-        int r;
+        int r, ifindex;
+        uint64_t flags;
 
         assert(name);
 
@@ -67,7 +95,7 @@ static int resolve_host(sd_bus *bus, const char *name) {
         if (r < 0)
                 return bus_log_create_error(r);
 
-        r = sd_bus_message_append(req, "si", name, arg_family);
+        r = sd_bus_message_append(req, "isit", arg_ifindex, name, arg_family, arg_flags);
         if (r < 0)
                 return bus_log_create_error(r);
 
@@ -77,13 +105,17 @@ static int resolve_host(sd_bus *bus, const char *name) {
                 return r;
         }
 
-        r = sd_bus_message_enter_container(reply, 'a', "(iayi)");
+        r = sd_bus_message_read(reply, "i", &ifindex);
         if (r < 0)
                 return bus_log_parse_error(r);
 
-        while ((r = sd_bus_message_enter_container(reply, 'r', "iayi")) > 0) {
+        r = sd_bus_message_enter_container(reply, 'a', "(iay)");
+        if (r < 0)
+                return bus_log_parse_error(r);
+
+        while ((r = sd_bus_message_enter_container(reply, 'r', "iay")) > 0) {
                 const void *a;
-                int family, ifindex;
+                int family;
                 size_t sz;
                 _cleanup_free_ char *pretty = NULL;
                 char ifname[IF_NAMESIZE] = "";
@@ -96,10 +128,6 @@ static int resolve_host(sd_bus *bus, const char *name) {
                 if (r < 0)
                         return bus_log_parse_error(r);
 
-                r = sd_bus_message_read(reply, "i", &ifindex);
-                if (r < 0)
-                        return bus_log_parse_error(r);
-
                 r = sd_bus_message_exit_container(reply);
                 if (r < 0)
                         return bus_log_parse_error(r);
@@ -115,12 +143,6 @@ static int resolve_host(sd_bus *bus, const char *name) {
                         continue;
                 }
 
-                if (ifindex < 0) {
-                        log_error("%s: systemd-resolved returned invalid interface index %i",
-                                  name, ifindex);
-                        continue;
-                }
-
                 if (ifindex > 0) {
                         char *t;
 
@@ -131,12 +153,6 @@ static int resolve_host(sd_bus *bus, const char *name) {
                         }
                 }
 
-                if (arg_ifindex > 0 && ifindex > 0 && ifindex != arg_ifindex) {
-                        log_debug("%s: skipping entry with ifindex %i (%s)",
-                                  name, ifindex, ifname);
-                        continue;
-                }
-
                 r = in_addr_to_string(family, a, &pretty);
                 if (r < 0) {
                         log_error("%s: failed to print address: %s", name, strerror(-r));
@@ -157,7 +173,7 @@ static int resolve_host(sd_bus *bus, const char *name) {
         if (r < 0)
                 return bus_log_parse_error(r);
 
-        r = sd_bus_message_read(reply, "s", &canonical);
+        r = sd_bus_message_read(reply, "st", &canonical, &flags);
         if (r < 0)
                 return bus_log_parse_error(r);
 
@@ -172,6 +188,8 @@ static int resolve_host(sd_bus *bus, const char *name) {
                 return -ESRCH;
         }
 
+        print_source(ifindex, flags);
+
         return 0;
 }
 
@@ -180,6 +198,7 @@ static int resolve_address(sd_bus *bus, int family, const union in_addr_union *a
         _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
         _cleanup_free_ char *pretty = NULL;
         char ifname[IF_NAMESIZE] = "";
+        uint64_t flags;
         unsigned c = 0;
         const char *n;
         int r;
@@ -218,7 +237,7 @@ static int resolve_address(sd_bus *bus, int family, const union in_addr_union *a
         if (r < 0)
                 return bus_log_create_error(r);
 
-        r = sd_bus_message_append(req, "i", family);
+        r = sd_bus_message_append(req, "ii", ifindex, family);
         if (r < 0)
                 return bus_log_create_error(r);
 
@@ -226,7 +245,7 @@ static int resolve_address(sd_bus *bus, int family, const union in_addr_union *a
         if (r < 0)
                 return bus_log_create_error(r);
 
-        r = sd_bus_message_append(req, "i", ifindex);
+        r = sd_bus_message_append(req, "t", arg_flags);
         if (r < 0)
                 return bus_log_create_error(r);
 
@@ -236,6 +255,10 @@ static int resolve_address(sd_bus *bus, int family, const union in_addr_union *a
                 return r;
         }
 
+        r = sd_bus_message_read(reply, "i", &ifindex);
+        if (r < 0)
+                return bus_log_parse_error(r);
+
         r = sd_bus_message_enter_container(reply, 'a', "s");
         if (r < 0)
                 return bus_log_create_error(r);
@@ -257,11 +280,17 @@ static int resolve_address(sd_bus *bus, int family, const union in_addr_union *a
         if (r < 0)
                 return bus_log_parse_error(r);
 
+        r = sd_bus_message_read(reply, "t", &flags);
+        if (r < 0)
+                return bus_log_parse_error(r);
+
         if (c == 0) {
                 log_error("%s: no names found", pretty);
                 return -ESRCH;
         }
 
+        print_source(ifindex, flags);
+
         return 0;
 }
 
@@ -296,7 +325,8 @@ static int resolve_record(sd_bus *bus, const char *name) {
         _cleanup_bus_message_unref_ sd_bus_message *req = NULL, *reply = NULL;
         _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
         unsigned n = 0;
-        int r;
+        uint64_t flags;
+        int r, ifindex;
 
         assert(name);
 
@@ -317,7 +347,7 @@ static int resolve_record(sd_bus *bus, const char *name) {
                 return bus_log_create_error(r);
 
         assert((uint16_t) arg_type == arg_type);
-        r = sd_bus_message_append(req, "sqq", name, arg_class, arg_type);
+        r = sd_bus_message_append(req, "isqqt", arg_ifindex, name, arg_class, arg_type, arg_flags);
         if (r < 0)
                 return bus_log_create_error(r);
 
@@ -327,6 +357,10 @@ static int resolve_record(sd_bus *bus, const char *name) {
                 return r;
         }
 
+        r = sd_bus_message_read(reply, "i", &ifindex);
+        if (r < 0)
+                return bus_log_parse_error(r);
+
         r = sd_bus_message_enter_container(reply, 'a', "(qqay)");
         if (r < 0)
                 return bus_log_parse_error(r);
@@ -381,11 +415,17 @@ static int resolve_record(sd_bus *bus, const char *name) {
         if (r < 0)
                 return bus_log_parse_error(r);
 
+        r = sd_bus_message_read(reply, "t", &flags);
+        if (r < 0)
+                return bus_log_parse_error(r);
+
         if (n == 0) {
                 log_error("%s: no records found", name);
                 return -ESRCH;
         }
 
+        print_source(ifindex, flags);
+
         return 0;
 }
 
@@ -418,14 +458,15 @@ static void help_dns_classes(void) {
 static void help(void) {
         printf("%s [OPTIONS...]\n\n"
                "Resolve IPv4 or IPv6 addresses.\n\n"
-               "  -h --help             Show this help\n"
-               "     --version          Show package version\n"
-               "  -4                    Resolve IPv4 addresses\n"
-               "  -6                    Resolve IPv6 addresses\n"
-               "  -i INTERFACE          Filter by interface\n"
-               "  -t --type=TYPE        Query RR with DNS type\n"
-               "  -c --class=CLASS      Query RR with DNS class\n"
-               "     --no-legend        Do not print column headers\n"
+               "  -h --help               Show this help\n"
+               "     --version            Show package version\n"
+               "  -4                      Resolve IPv4 addresses\n"
+               "  -6                      Resolve IPv6 addresses\n"
+               "  -i INTERFACE            Look on interface\n"
+               "  -p --protocol=PROTOCOL  Look via protocol\n"
+               "  -t --type=TYPE          Query RR with DNS type\n"
+               "  -c --class=CLASS        Query RR with DNS class\n"
+               "     --no-legend          Do not print column headers\n"
                , program_invocation_short_name);
 }
 
@@ -436,11 +477,12 @@ static int parse_argv(int argc, char *argv[]) {
         };
 
         static const struct option options[] = {
-                { "help",        no_argument,       NULL, 'h'           },
-                { "version",     no_argument,       NULL, ARG_VERSION   },
-                { "type",        no_argument,       NULL, 't'           },
-                { "class",       no_argument,       NULL, 'c'           },
-                { "no-legend",   no_argument,       NULL, ARG_NO_LEGEND },
+                { "help",      no_argument,       NULL, 'h'           },
+                { "version",   no_argument,       NULL, ARG_VERSION   },
+                { "type",      required_argument, NULL, 't'           },
+                { "class",     required_argument, NULL, 'c'           },
+                { "no-legend", no_argument,       NULL, ARG_NO_LEGEND },
+                { "protocol",  required_argument, NULL, 'p'           },
                 {}
         };
 
@@ -449,7 +491,7 @@ static int parse_argv(int argc, char *argv[]) {
         assert(argc >= 0);
         assert(argv);
 
-        while ((c = getopt_long(argc, argv, "h46i:t:c:", options, NULL)) >= 0)
+        while ((c = getopt_long(argc, argv, "h46i:t:c:p:", options, NULL)) >= 0)
                 switch(c) {
 
                 case 'h':
@@ -510,6 +552,22 @@ static int parse_argv(int argc, char *argv[]) {
                         arg_legend = false;
                         break;
 
+                case 'p':
+                        if (streq(optarg, "dns"))
+                                arg_flags |= SD_RESOLVED_DNS;
+                        else if (streq(optarg, "llmnr"))
+                                arg_flags |= SD_RESOLVED_LLMNR;
+                        else if (streq(optarg, "llmnr-ipv4"))
+                                arg_flags |= SD_RESOLVED_LLMNR_IPV4;
+                        else if (streq(optarg, "llmnr-ipv6"))
+                                arg_flags |= SD_RESOLVED_LLMNR_IPV6;
+                        else {
+                                log_error("Unknown protocol specifier: %s", optarg);
+                                return -EINVAL;
+                        }
+
+                        break;
+
                 case '?':
                         return -EINVAL;
 
diff --git a/src/resolve/resolved-bus.c b/src/resolve/resolved-bus.c
index cfe12d3..0029023 100644
--- a/src/resolve/resolved-bus.c
+++ b/src/resolve/resolved-bus.c
@@ -24,6 +24,7 @@
 
 #include "resolved-dns-domain.h"
 #include "resolved-bus.h"
+#include "resolved-def.h"
 
 static int reply_query_state(DnsQuery *q) {
         _cleanup_free_ char *ip = NULL;
@@ -90,13 +91,13 @@ static int reply_query_state(DnsQuery *q) {
         }
 }
 
-static int append_address(sd_bus_message *reply, DnsResourceRecord *rr, int ifindex) {
+static int append_address(sd_bus_message *reply, DnsResourceRecord *rr) {
         int r;
 
         assert(reply);
         assert(rr);
 
-        r = sd_bus_message_open_container(reply, 'r', "iayi");
+        r = sd_bus_message_open_container(reply, 'r', "iay");
         if (r < 0)
                 return r;
 
@@ -119,10 +120,6 @@ static int append_address(sd_bus_message *reply, DnsResourceRecord *rr, int ifin
         if (r < 0)
                 return r;
 
-        r = sd_bus_message_append(reply, "i", ifindex);
-        if (r < 0)
-                return r;
-
         r = sd_bus_message_close_container(reply);
         if (r < 0)
                 return r;
@@ -135,7 +132,7 @@ static void bus_method_resolve_hostname_complete(DnsQuery *q) {
         _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
         _cleanup_(dns_answer_unrefp) DnsAnswer *answer = NULL;
         unsigned added = 0, i;
-        int r, ifindex;
+        int r;
 
         assert(q);
 
@@ -148,11 +145,13 @@ static void bus_method_resolve_hostname_complete(DnsQuery *q) {
         if (r < 0)
                 goto finish;
 
-        r = sd_bus_message_open_container(reply, 'a', "(iayi)");
+        r = sd_bus_message_append(reply, "i", q->answer_ifindex);
         if (r < 0)
                 goto finish;
 
-        ifindex = q->answer_ifindex;
+        r = sd_bus_message_open_container(reply, 'a', "(iay)");
+        if (r < 0)
+                goto finish;
 
         if (q->answer) {
                 answer = dns_answer_ref(q->answer);
@@ -173,7 +172,7 @@ static void bus_method_resolve_hostname_complete(DnsQuery *q) {
                                 continue;
                         }
 
-                        r = append_address(reply, answer->rrs[i], ifindex);
+                        r = append_address(reply, answer->rrs[i]);
                         if (r < 0)
                                 goto finish;
 
@@ -211,7 +210,7 @@ static void bus_method_resolve_hostname_complete(DnsQuery *q) {
                         if (r == 0)
                                 continue;
 
-                        r = append_address(reply, answer->rrs[i], ifindex);
+                        r = append_address(reply, answer->rrs[i]);
                         if (r < 0)
                                 goto finish;
 
@@ -244,7 +243,7 @@ static void bus_method_resolve_hostname_complete(DnsQuery *q) {
 
         /* Return the precise spelling and uppercasing reported by the server */
         assert(canonical);
-        r = sd_bus_message_append(reply, "s", DNS_RESOURCE_KEY_NAME(canonical->key));
+        r = sd_bus_message_append(reply, "st", DNS_RESOURCE_KEY_NAME(canonical->key), SD_RESOLVED_FLAGS_MAKE(q->answer_protocol, q->answer_family));
         if (r < 0)
                 goto finish;
 
@@ -259,11 +258,27 @@ finish:
         dns_query_free(q);
 }
 
+static int check_ifindex_flags(int ifindex, uint64_t *flags, sd_bus_error *error) {
+        assert(flags);
+
+        if (ifindex < 0)
+                return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid interface index");
+
+        if (*flags & ~SD_RESOLVED_FLAGS_ALL)
+                return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid flags parameter");
+
+        if (*flags == 0)
+                *flags = SD_RESOLVED_FLAGS_DEFAULT;
+
+        return 0;
+}
+
 static int bus_method_resolve_hostname(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
         _cleanup_(dns_question_unrefp) DnsQuestion *question = NULL;
         Manager *m = userdata;
         const char *hostname;
-        int family;
+        int family, ifindex;
+        uint64_t flags;
         DnsQuery *q;
         int r;
 
@@ -271,7 +286,7 @@ static int bus_method_resolve_hostname(sd_bus *bus, sd_bus_message *message, voi
         assert(message);
         assert(m);
 
-        r = sd_bus_message_read(message, "si", &hostname, &family);
+        r = sd_bus_message_read(message, "isit", &ifindex, &hostname, &family, &flags);
         if (r < 0)
                 return r;
 
@@ -282,6 +297,10 @@ static int bus_method_resolve_hostname(sd_bus *bus, sd_bus_message *message, voi
         if (r < 0)
                 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid hostname '%s'", hostname);
 
+        r = check_ifindex_flags(ifindex, &flags, error);
+        if (r < 0)
+                return r;
+
         question = dns_question_new(family == AF_UNSPEC ? 2 : 1);
         if (!question)
                 return -ENOMEM;
@@ -310,7 +329,7 @@ static int bus_method_resolve_hostname(sd_bus *bus, sd_bus_message *message, voi
                         return r;
         }
 
-        r = dns_query_new(m, &q, question);
+        r = dns_query_new(m, &q, question, ifindex, flags);
         if (r < 0)
                 return r;
 
@@ -353,6 +372,10 @@ static void bus_method_resolve_address_complete(DnsQuery *q) {
         if (r < 0)
                 goto finish;
 
+        r = sd_bus_message_append(reply, "i", q->answer_ifindex);
+        if (r < 0)
+                goto finish;
+
         r = sd_bus_message_open_container(reply, 'a', "s");
         if (r < 0)
                 goto finish;
@@ -388,6 +411,10 @@ static void bus_method_resolve_address_complete(DnsQuery *q) {
         if (r < 0)
                 goto finish;
 
+        r = sd_bus_message_append(reply, "t", SD_RESOLVED_FLAGS_MAKE(q->answer_protocol, q->answer_family));
+        if (r < 0)
+                goto finish;
+
         r = sd_bus_send(q->manager->bus, reply, NULL);
 
 finish:
@@ -405,6 +432,7 @@ static int bus_method_resolve_address(sd_bus *bus, sd_bus_message *message, void
         _cleanup_free_ char *reverse = NULL;
         Manager *m = userdata;
         int family, ifindex;
+        uint64_t flags;
         const void *d;
         DnsQuery *q;
         size_t sz;
@@ -414,7 +442,7 @@ static int bus_method_resolve_address(sd_bus *bus, sd_bus_message *message, void
         assert(message);
         assert(m);
 
-        r = sd_bus_message_read(message, "i", &family);
+        r = sd_bus_message_read(message, "ii", &ifindex, &family);
         if (r < 0)
                 return r;
 
@@ -428,11 +456,13 @@ static int bus_method_resolve_address(sd_bus *bus, sd_bus_message *message, void
         if (sz != FAMILY_ADDRESS_SIZE(family))
                 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid address size");
 
-        r = sd_bus_message_read(message, "i", &ifindex);
+        r = sd_bus_message_read(message, "t", &flags);
+        if (r < 0)
+                return r;
+
+        r = check_ifindex_flags(ifindex, &flags, error);
         if (r < 0)
                 return r;
-        if (ifindex < 0)
-                return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid interface index");
 
         r = dns_name_reverse(family, d, &reverse);
         if (r < 0)
@@ -452,7 +482,7 @@ static int bus_method_resolve_address(sd_bus *bus, sd_bus_message *message, void
         if (r < 0)
                 return r;
 
-        r = dns_query_new(m, &q, question);
+        r = dns_query_new(m, &q, question, ifindex, flags);
         if (r < 0)
                 return r;
 
@@ -495,6 +525,10 @@ static void bus_method_resolve_record_complete(DnsQuery *q) {
         if (r < 0)
                 goto finish;
 
+        r = sd_bus_message_append(reply, "i", q->answer_ifindex);
+        if (r < 0)
+                goto finish;
+
         r = sd_bus_message_open_container(reply, 'a', "(qqay)");
         if (r < 0)
                 goto finish;
@@ -549,6 +583,10 @@ static void bus_method_resolve_record_complete(DnsQuery *q) {
         if (r < 0)
                 goto finish;
 
+        r = sd_bus_message_append(reply, "t", SD_RESOLVED_FLAGS_MAKE(q->answer_protocol, q->answer_family));
+        if (r < 0)
+                goto finish;
+
         r = sd_bus_send(q->manager->bus, reply, NULL);
 
 finish:
@@ -564,16 +602,17 @@ static int bus_method_resolve_record(sd_bus *bus, sd_bus_message *message, void
         _cleanup_(dns_resource_key_unrefp) DnsResourceKey *key = NULL;
         _cleanup_(dns_question_unrefp) DnsQuestion *question = NULL;
         Manager *m = userdata;
-        DnsQuery *q;
-        int r;
         uint16_t class, type;
         const char *name;
+        int r, ifindex;
+        uint64_t flags;
+        DnsQuery *q;
 
         assert(bus);
         assert(message);
         assert(m);
 
-        r = sd_bus_message_read(message, "sqq", &name, &class, &type);
+        r = sd_bus_message_read(message, "isqqt", &ifindex, &name, &class, &type, &flags);
         if (r < 0)
                 return r;
 
@@ -581,6 +620,10 @@ static int bus_method_resolve_record(sd_bus *bus, sd_bus_message *message, void
         if (r < 0)
                 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid name '%s'", name);
 
+        r = check_ifindex_flags(ifindex, &flags, error);
+        if (r < 0)
+                return r;
+
         question = dns_question_new(1);
         if (!question)
                 return -ENOMEM;
@@ -593,7 +636,7 @@ static int bus_method_resolve_record(sd_bus *bus, sd_bus_message *message, void
         if (r < 0)
                 return r;
 
-        r = dns_query_new(m, &q, question);
+        r = dns_query_new(m, &q, question, ifindex, flags);
         if (r < 0)
                 return r;
 
@@ -620,9 +663,9 @@ static int bus_method_resolve_record(sd_bus *bus, sd_bus_message *message, void
 
 static const sd_bus_vtable resolve_vtable[] = {
         SD_BUS_VTABLE_START(0),
-        SD_BUS_METHOD("ResolveHostname", "si", "a(iayi)s", bus_method_resolve_hostname, SD_BUS_VTABLE_UNPRIVILEGED),
-        SD_BUS_METHOD("ResolveAddress", "iayi", "as", bus_method_resolve_address, SD_BUS_VTABLE_UNPRIVILEGED),
-        SD_BUS_METHOD("ResolveRecord", "sqq", "a(qqay)", bus_method_resolve_record, SD_BUS_VTABLE_UNPRIVILEGED),
+        SD_BUS_METHOD("ResolveHostname", "isit", "ia(iay)st", bus_method_resolve_hostname, SD_BUS_VTABLE_UNPRIVILEGED),
+        SD_BUS_METHOD("ResolveAddress", "iiayt", "iast", bus_method_resolve_address, SD_BUS_VTABLE_UNPRIVILEGED),
+        SD_BUS_METHOD("ResolveRecord", "isqqt", "ia(qqay)t", bus_method_resolve_record, SD_BUS_VTABLE_UNPRIVILEGED),
         SD_BUS_VTABLE_END,
 };
 
diff --git a/src/resolve/resolved-def.h b/src/resolve/resolved-def.h
new file mode 100644
index 0000000..086d111
--- /dev/null
+++ b/src/resolve/resolved-def.h
@@ -0,0 +1,30 @@
+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
+
+#pragma once
+
+/***
+  This file is part of systemd.
+
+  Copyright 2014 Lennart Poettering
+
+  systemd is free software; you can redistribute it and/or modify it
+  under the terms of the GNU Lesser General Public License as published by
+  the Free Software Foundation; either version 2.1 of the License, or
+  (at your option) any later version.
+
+  systemd is distributed in the hope that it will be useful, but
+  WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+  Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public License
+  along with systemd; If not, see <http://www.gnu.org/licenses/>.
+***/
+
+#define SD_RESOLVED_DNS           ((uint64_t) 1)
+#define SD_RESOLVED_LLMNR_IPV4    ((uint64_t) 2)
+#define SD_RESOLVED_LLMNR_IPV6    ((uint64_t) 4)
+#define SD_RESOLVED_LLMNR         (SD_RESOLVED_LLMNR_IPV4|SD_RESOLVED_LLMNR_IPV6)
+
+#define SD_RESOLVED_FLAGS_ALL     (SD_RESOLVED_DNS|SD_RESOLVED_LLMNR_IPV4|SD_RESOLVED_LLMNR_IPV6)
+#define SD_RESOLVED_FLAGS_DEFAULT SD_RESOLVED_FLAGS_ALL
diff --git a/src/resolve/resolved-dns-packet.h b/src/resolve/resolved-dns-packet.h
index 6a865a2..561dd3a 100644
--- a/src/resolve/resolved-dns-packet.h
+++ b/src/resolve/resolved-dns-packet.h
@@ -34,6 +34,7 @@ typedef struct DnsPacket DnsPacket;
 #include "resolved-dns-rr.h"
 #include "resolved-dns-question.h"
 #include "resolved-dns-answer.h"
+#include "resolved-def.h"
 
 typedef enum DnsProtocol {
         DNS_PROTOCOL_DNS,
@@ -220,3 +221,16 @@ enum {
 
 const char* dnssec_algorithm_to_string(int i) _const_;
 int dnssec_algorithm_from_string(const char *s) _pure_;
+
+static inline uint64_t SD_RESOLVED_FLAGS_MAKE(DnsProtocol protocol, int family) {
+
+        /* Converts a protocol + family into a flags field as used in queries */
+
+        if (protocol == DNS_PROTOCOL_DNS)
+                return SD_RESOLVED_DNS;
+
+        if (protocol == DNS_PROTOCOL_LLMNR)
+                return family == AF_INET6 ? SD_RESOLVED_LLMNR_IPV6 : SD_RESOLVED_LLMNR_IPV4;
+
+        return 0;
+}
diff --git a/src/resolve/resolved-dns-query.c b/src/resolve/resolved-dns-query.c
index 6d77c10..669595d 100644
--- a/src/resolve/resolved-dns-query.c
+++ b/src/resolve/resolved-dns-query.c
@@ -66,7 +66,7 @@ DnsQuery *dns_query_free(DnsQuery *q) {
         return NULL;
 }
 
-int dns_query_new(Manager *m, DnsQuery **ret, DnsQuestion *question) {
+int dns_query_new(Manager *m, DnsQuery **ret, DnsQuestion *question, int ifindex, uint64_t flags) {
         _cleanup_(dns_query_freep) DnsQuery *q = NULL;
         unsigned i;
         int r;
@@ -86,6 +86,8 @@ int dns_query_new(Manager *m, DnsQuery **ret, DnsQuestion *question) {
                 return -ENOMEM;
 
         q->question = dns_question_ref(question);
+        q->ifindex = ifindex;
+        q->flags = flags;
 
         for (i = 0; i < question->n_keys; i++) {
                 _cleanup_free_ char *p;
@@ -233,7 +235,7 @@ int dns_query_go(DnsQuery *q) {
         LIST_FOREACH(scopes, s, q->manager->dns_scopes) {
                 DnsScopeMatch match;
 
-                match = dns_scope_good_domain(s, name);
+                match = dns_scope_good_domain(s, q->ifindex, q->flags, name);
                 if (match < 0)
                         return match;
 
@@ -263,7 +265,7 @@ int dns_query_go(DnsQuery *q) {
         LIST_FOREACH(scopes, s, first->scopes_next) {
                 DnsScopeMatch match;
 
-                match = dns_scope_good_domain(s, name);
+                match = dns_scope_good_domain(s, q->ifindex, q->flags, name);
                 if (match < 0)
                         goto fail;
 
@@ -278,6 +280,8 @@ int dns_query_go(DnsQuery *q) {
         q->answer = dns_answer_unref(q->answer);
         q->answer_ifindex = 0;
         q->answer_rcode = 0;
+        q->answer_family = AF_UNSPEC;
+        q->answer_protocol = _DNS_PROTOCOL_INVALID;
 
         r = sd_event_add_time(
                         q->manager->event,
@@ -422,6 +426,8 @@ void dns_query_ready(DnsQuery *q) {
                 q->answer = dns_answer_ref(answer);
                 q->answer_rcode = rcode;
                 q->answer_ifindex = (scope && scope->link) ? scope->link->ifindex : 0;
+                q->answer_protocol = scope ? scope->protocol : _DNS_PROTOCOL_INVALID;
+                q->answer_family = scope ? scope->family : AF_UNSPEC;
         }
 
         dns_query_complete(q, state);
diff --git a/src/resolve/resolved-dns-query.h b/src/resolve/resolved-dns-query.h
index 50fa3a2..13b3ee4 100644
--- a/src/resolve/resolved-dns-query.h
+++ b/src/resolve/resolved-dns-query.h
@@ -41,6 +41,9 @@ struct DnsQuery {
         Manager *manager;
         DnsQuestion *question;
 
+        uint64_t flags;
+        int ifindex;
+
         DnsTransactionState state;
         unsigned n_cname_redirects;
 
@@ -49,6 +52,8 @@ struct DnsQuery {
         /* Discovered data */
         DnsAnswer *answer;
         int answer_ifindex;
+        int answer_family;
+        DnsProtocol answer_protocol;
         int answer_rcode;
 
         /* Bus client information */
@@ -68,7 +73,7 @@ struct DnsQuery {
         LIST_FIELDS(DnsQuery, queries);
 };
 
-int dns_query_new(Manager *m, DnsQuery **q, DnsQuestion *question);
+int dns_query_new(Manager *m, DnsQuery **q, DnsQuestion *question, int family, uint64_t flags);
 DnsQuery *dns_query_free(DnsQuery *q);
 
 int dns_query_go(DnsQuery *q);
diff --git a/src/resolve/resolved-dns-scope.c b/src/resolve/resolved-dns-scope.c
index 174249a..396ae19 100644
--- a/src/resolve/resolved-dns-scope.c
+++ b/src/resolve/resolved-dns-scope.c
@@ -291,12 +291,18 @@ int dns_scope_tcp_socket(DnsScope *s, int family, const union in_addr_union *add
         return ret;
 }
 
-DnsScopeMatch dns_scope_good_domain(DnsScope *s, const char *domain) {
+DnsScopeMatch dns_scope_good_domain(DnsScope *s, int ifindex, uint64_t flags, const char *domain) {
         char **i;
 
         assert(s);
         assert(domain);
 
+        if (ifindex != 0 && (!s->link || s->link->ifindex != ifindex))
+                return DNS_SCOPE_NO;
+
+        if ((SD_RESOLVED_FLAGS_MAKE(s->protocol, s->family) & flags) == 0)
+                return DNS_SCOPE_NO;
+
         STRV_FOREACH(i, s->domains)
                 if (dns_name_endswith(domain, *i) > 0)
                         return DNS_SCOPE_YES;
diff --git a/src/resolve/resolved-dns-scope.h b/src/resolve/resolved-dns-scope.h
index 6ba5ef2..a022309 100644
--- a/src/resolve/resolved-dns-scope.h
+++ b/src/resolve/resolved-dns-scope.h
@@ -71,7 +71,7 @@ DnsScope* dns_scope_free(DnsScope *s);
 int dns_scope_emit(DnsScope *s, DnsPacket *p);
 int dns_scope_tcp_socket(DnsScope *s, int family, const union in_addr_union *address, uint16_t port);
 
-DnsScopeMatch dns_scope_good_domain(DnsScope *s, const char *domain);
+DnsScopeMatch dns_scope_good_domain(DnsScope *s, int ifindex, uint64_t flags, const char *domain);
 int dns_scope_good_key(DnsScope *s, DnsResourceKey *key);
 int dns_scope_good_dns_server(DnsScope *s, int family, const union in_addr_union *address);
 

commit 12e34d9d58ed4d97e7bdf8c23494c51ee5ec388e
Author: Umut Tezduyar Lindskog <umut.tezduyar at axis.com>
Date:   Tue Aug 5 12:17:09 2014 +0200

    ldconfig: add configure option to disable

diff --git a/Makefile.am b/Makefile.am
index fa6fd7d..513c852 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -490,8 +490,7 @@ dist_systemunit_DATA = \
 	units/systemd-udevd-control.socket \
 	units/systemd-udevd-kernel.socket \
 	units/system-update.target \
-	units/initrd-switch-root.target \
-	units/ldconfig.service
+	units/initrd-switch-root.target
 
 nodist_systemunit_DATA = \
 	units/getty at .service \
@@ -919,6 +918,16 @@ libsystemd_label_la_CFLAGS = \
 libsystemd_label_la_LIBADD = \
 	$(SELINUX_LIBS)
 
+# -----------------------------------------------------------------------------
+
+if ENABLE_LDCONFIG
+dist_systemunit_DATA += \
+	units/ldconfig.service
+
+SYSINIT_TARGET_WANTS += \
+	ldconfig.service
+endif
+
 # ------------------------------------------------------------------------------
 
 if HAVE_SECCOMP
@@ -5789,8 +5798,7 @@ endif
 
 SYSINIT_TARGET_WANTS += \
 	systemd-update-utmp.service \
-	systemd-update-done.service \
-	ldconfig.service
+	systemd-update-done.service
 
 LOCAL_FS_TARGET_WANTS += \
 	systemd-remount-fs.service \
diff --git a/configure.ac b/configure.ac
index 6d5536b..d95a348 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1182,7 +1182,12 @@ AS_IF([test "x$enable_manpages" != xno], [have_manpages=yes])
 AM_CONDITIONAL(ENABLE_MANPAGES, [test "x$have_manpages" = "xyes"])
 
 # ------------------------------------------------------------------------------
+AC_ARG_ENABLE(ldconfig,
+       [AC_HELP_STRING([--disable-ldconfig], [disable ldconfig])],
+       enable_ldconfig=$enableval, enable_ldconfig=yes)
+AM_CONDITIONAL(ENABLE_LDCONFIG, [test x$enable_ldconfig = xyes])
 
+# ------------------------------------------------------------------------------
 # Location of the init scripts as mandated by LSB
 SYSTEM_SYSVINIT_PATH=/etc/init.d
 SYSTEM_SYSVRCND_PATH=/etc/rc.d
diff --git a/units/ldconfig.service b/units/ldconfig.service
index 09a2b74..43c145b 100644
--- a/units/ldconfig.service
+++ b/units/ldconfig.service
@@ -13,7 +13,6 @@ Conflicts=shutdown.target
 After=systemd-readahead-collect.service systemd-readahead-replay.service systemd-remount-fs.service
 Before=sysinit.target shutdown.target systemd-update-done.service
 ConditionNeedsUpdate=/etc
-ConditionFileIsExecutable=/sbin/ldconfig
 
 [Service]
 Type=oneshot



More information about the systemd-commits mailing list