]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
Merge pull request #1641 from poettering/btrfs-quota
authorDaniel Mack <github@zonque.org>
Fri, 23 Oct 2015 08:50:53 +0000 (10:50 +0200)
committerDaniel Mack <github@zonque.org>
Fri, 23 Oct 2015 08:50:53 +0000 (10:50 +0200)
btrfs quota beef up and various other unrelated changes

20 files changed:
.gitignore
Makefile.am
man/systemd-nspawn.xml
src/basic/util.c
src/libsystemd-network/dhcp6-internal.h
src/libsystemd-network/dhcp6-network.c
src/libsystemd-network/icmp6-util.c [new file with mode: 0644]
src/libsystemd-network/icmp6-util.h [new file with mode: 0644]
src/libsystemd-network/network-internal.c
src/libsystemd-network/sd-ndisc.c [moved from src/libsystemd-network/sd-icmp6-nd.c with 50% similarity]
src/libsystemd-network/test-icmp6-rs.c [deleted file]
src/libsystemd-network/test-ndisc-rs.c [new file with mode: 0644]
src/network/networkd-dhcp6.c
src/network/networkd-link.c
src/network/networkd-link.h
src/network/networkd-manager.c
src/network/networkd-ndisc.c [new file with mode: 0644]
src/systemd/sd-icmp6-nd.h [deleted file]
src/systemd/sd-ndisc.h [new file with mode: 0644]
src/test/test-util.c

index 709c8b53d08e84c31f1f57f358024d379301ea9a..b47bd1b2f2ec8d1154eaacbd3dc0dfe29e6b2d5e 100644 (file)
 /test-hashmap
 /test-hostname
 /test-hostname-util
-/test-icmp6-rs
+/test-ndisc-rs
 /test-id128
 /test-inhibit
 /test-install
index e210d8a2dae49a5cfcecc5b54d61fac3ed01ac57..fa25485b7363b8b62aa5886022da60c48040ab16 100644 (file)
@@ -3214,7 +3214,7 @@ libsystemd_network_la_SOURCES = \
        src/systemd/sd-dhcp-lease.h \
        src/systemd/sd-ipv4ll.h \
        src/systemd/sd-ipv4acd.h \
-       src/systemd/sd-icmp6-nd.h \
+       src/systemd/sd-ndisc.h \
        src/systemd/sd-dhcp6-client.h \
        src/systemd/sd-dhcp6-lease.h \
        src/systemd/sd-pppoe.h \
@@ -3236,7 +3236,9 @@ libsystemd_network_la_SOURCES = \
        src/libsystemd-network/sd-pppoe.c \
        src/libsystemd-network/network-internal.c \
        src/libsystemd-network/network-internal.h \
-       src/libsystemd-network/sd-icmp6-nd.c \
+       src/libsystemd-network/sd-ndisc.c \
+       src/libsystemd-network/icmp6-util.h \
+       src/libsystemd-network/icmp6-util.c \
        src/libsystemd-network/sd-dhcp6-client.c \
        src/libsystemd-network/dhcp6-internal.h \
        src/libsystemd-network/dhcp6-protocol.h \
@@ -3320,15 +3322,15 @@ test_pppoe_LDADD = \
        libsystemd-network.la \
        libshared.la
 
-test_icmp6_rs_SOURCES = \
+test_ndisc_rs_SOURCES = \
        src/systemd/sd-dhcp6-client.h \
-       src/systemd/sd-icmp6-nd.h \
-       src/libsystemd-network/dhcp6-internal.h \
-       src/libsystemd-network/test-icmp6-rs.c \
+       src/systemd/sd-ndisc.h \
+       src/libsystemd-network/icmp6-util.h \
+       src/libsystemd-network/test-ndisc-rs.c \
        src/libsystemd-network/dhcp-identifier.h \
        src/libsystemd-network/dhcp-identifier.c
 
-test_icmp6_rs_LDADD = \
+test_ndisc_rs_LDADD = \
        libsystemd-network.la \
        libudev.la \
        libshared.la
@@ -3360,7 +3362,7 @@ tests += \
        test-dhcp-client \
        test-dhcp-server \
        test-ipv4ll \
-       test-icmp6-rs \
+       test-ndisc-rs \
        test-dhcp6-client \
        test-lldp
 
@@ -5230,6 +5232,7 @@ libnetworkd_core_la_SOURCES = \
        src/network/networkd-ipv4ll.c \
        src/network/networkd-dhcp4.c \
        src/network/networkd-dhcp6.c \
+       src/network/networkd-ndisc.c \
        src/network/networkd-network.h \
        src/network/networkd-network.c \
        src/network/networkd-network-bus.c \
index 4b0e72113e78db4d8c2579ca7e22c70708ad3567..ddad762653ca9ed7e954fe22b8d6fe6b56099b6f 100644 (file)
     <example>
       <title>Build and boot a minimal Fedora distribution in a container</title>
 
-      <programlisting># dnf -y --releasever=21 --nogpg --installroot=/srv/mycontainer --disablerepo='*' --enablerepo=fedora install systemd passwd dnf fedora-release vim-minimal
+      <programlisting># dnf -y --releasever=23 --installroot=/srv/mycontainer --disablerepo=* --enablerepo=fedora --enablerepo=updates install systemd passwd dnf fedora-release vim-minimal
 # systemd-nspawn -bD /srv/mycontainer</programlisting>
 
       <para>This installs a minimal Fedora distribution into the
index c2a2f8dc5cdfc76ca139f05588bd1397ec6939c9..ec3b360ffeefda917f50457b3cfe257e5dec08fe 100644 (file)
@@ -5904,9 +5904,11 @@ int extract_first_word(const char **p, char **ret, const char *separators, Extra
                         break;
 
                 case DOUBLE_QUOTE:
-                        if (c == 0)
+                        if (c == 0) {
+                                if (flags & EXTRACT_RELAX)
+                                        goto finish_force_terminate;
                                 return -EINVAL;
-                        else if (c == '\"')
+                        else if (c == '\"')
                                 state = VALUE;
                         else if (c == '\\')
                                 state = DOUBLE_QUOTE_ESCAPE;
index 83e8192f58494bd196db70561d353ad4f3ca6cf8..eeff74fbb9894d850657a19076768e6483ca3ac8 100644 (file)
@@ -58,9 +58,6 @@ typedef struct DHCP6IA DHCP6IA;
 
 #define log_dhcp6_client(p, fmt, ...) log_internal(LOG_DEBUG, 0, __FILE__, __LINE__, __func__, "DHCPv6 CLIENT: " fmt, ##__VA_ARGS__)
 
-int dhcp_network_icmp6_bind_router_solicitation(int index);
-int dhcp_network_icmp6_send_router_solicitation(int s, const struct ether_addr *ether_addr);
-
 int dhcp6_option_append(uint8_t **buf, size_t *buflen, uint16_t code,
                         size_t optlen, const void *optval);
 int dhcp6_option_append_ia(uint8_t **buf, size_t *buflen, DHCP6IA *ia);
index 187975364b5aefe19c675cd0f241e71e3634420e..ccb8363e77581e83c3fdaaacb2ba39af02dbb239 100644 (file)
@@ -25,7 +25,6 @@
 #include <stdio.h>
 #include <unistd.h>
 #include <netinet/ip6.h>
-#include <netinet/icmp6.h>
 #include <netinet/in.h>
 
 #include "socket-util.h"
 #include "dhcp6-internal.h"
 #include "dhcp6-protocol.h"
 
-#define IN6ADDR_ALL_ROUTERS_MULTICAST_INIT \
-        { { { 0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
-              0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02 } } }
-
-#define IN6ADDR_ALL_NODES_MULTICAST_INIT \
-        { { { 0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
-              0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 } } }
-
-int dhcp_network_icmp6_bind_router_solicitation(int index) {
-        struct icmp6_filter filter = { };
-        struct ipv6_mreq mreq = {
-                .ipv6mr_multiaddr = IN6ADDR_ALL_NODES_MULTICAST_INIT,
-                .ipv6mr_interface = index,
-        };
-        _cleanup_close_ int s = -1;
-        int r, zero = 0, hops = 255;
-
-        s = socket(AF_INET6, SOCK_RAW | SOCK_CLOEXEC | SOCK_NONBLOCK,
-                   IPPROTO_ICMPV6);
-        if (s < 0)
-                return -errno;
-
-        ICMP6_FILTER_SETBLOCKALL(&filter);
-        ICMP6_FILTER_SETPASS(ND_ROUTER_ADVERT, &filter);
-        r = setsockopt(s, IPPROTO_ICMPV6, ICMP6_FILTER, &filter,
-                       sizeof(filter));
-        if (r < 0)
-                return -errno;
-
-        /* RFC 3315, section 6.7, bullet point 2 may indicate that an
-           IPV6_PKTINFO socket option also applies for ICMPv6 multicast.
-           Empirical experiments indicates otherwise and therefore an
-           IPV6_MULTICAST_IF socket option is used here instead */
-        r = setsockopt(s, IPPROTO_IPV6, IPV6_MULTICAST_IF, &index,
-                       sizeof(index));
-        if (r < 0)
-                return -errno;
-
-        r = setsockopt(s, IPPROTO_IPV6, IPV6_MULTICAST_LOOP, &zero,
-                       sizeof(zero));
-        if (r < 0)
-                return -errno;
-
-        r = setsockopt(s, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, &hops,
-                       sizeof(hops));
-        if (r < 0)
-                return -errno;
-
-        r = setsockopt(s, IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP, &mreq,
-                       sizeof(mreq));
-        if (r < 0)
-                return -errno;
-
-        r = s;
-        s = -1;
-        return r;
-}
-
-int dhcp_network_icmp6_send_router_solicitation(int s, const struct ether_addr *ether_addr) {
-        struct sockaddr_in6 dst = {
-                .sin6_family = AF_INET6,
-                .sin6_addr = IN6ADDR_ALL_ROUTERS_MULTICAST_INIT,
-        };
-        struct {
-                struct nd_router_solicit rs;
-                struct nd_opt_hdr rs_opt;
-                struct ether_addr rs_opt_mac;
-        } _packed_ rs = {
-                .rs.nd_rs_type = ND_ROUTER_SOLICIT,
-        };
-        struct iovec iov[1] = {
-                { &rs, },
-        };
-        struct msghdr msg = {
-                .msg_name = &dst,
-                .msg_namelen = sizeof(dst),
-                .msg_iov = iov,
-                .msg_iovlen = 1,
-        };
-        int r;
-
-        if (ether_addr) {
-                memcpy(&rs.rs_opt_mac, ether_addr, ETH_ALEN);
-                rs.rs_opt.nd_opt_type = ND_OPT_SOURCE_LINKADDR;
-                rs.rs_opt.nd_opt_len = 1;
-                iov[0].iov_len = sizeof(rs);
-        } else
-                iov[0].iov_len = sizeof(rs.rs);
-
-        r = sendmsg(s, &msg, 0);
-        if (r < 0)
-                return -errno;
-
-        return 0;
-}
-
 int dhcp6_network_bind_udp_socket(int index, struct in6_addr *local_address) {
         struct in6_pktinfo pktinfo = {
                 .ipi6_ifindex = index,
diff --git a/src/libsystemd-network/icmp6-util.c b/src/libsystemd-network/icmp6-util.c
new file mode 100644 (file)
index 0000000..140429b
--- /dev/null
@@ -0,0 +1,129 @@
+/***
+  This file is part of systemd.
+
+  Copyright (C) 2014 Intel Corporation. All rights reserved.
+
+  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/>.
+***/
+
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <string.h>
+#include <linux/if_packet.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <netinet/ip6.h>
+#include <netinet/icmp6.h>
+#include <netinet/in.h>
+
+#include "socket-util.h"
+
+#include "icmp6-util.h"
+
+#define IN6ADDR_ALL_ROUTERS_MULTICAST_INIT \
+        { { { 0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
+              0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02 } } }
+
+#define IN6ADDR_ALL_NODES_MULTICAST_INIT \
+        { { { 0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
+              0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 } } }
+
+int icmp6_bind_router_solicitation(int index) {
+        struct icmp6_filter filter = { };
+        struct ipv6_mreq mreq = {
+                .ipv6mr_multiaddr = IN6ADDR_ALL_NODES_MULTICAST_INIT,
+                .ipv6mr_interface = index,
+        };
+        _cleanup_close_ int s = -1;
+        int r, zero = 0, hops = 255;
+
+        s = socket(AF_INET6, SOCK_RAW | SOCK_CLOEXEC | SOCK_NONBLOCK,
+                   IPPROTO_ICMPV6);
+        if (s < 0)
+                return -errno;
+
+        ICMP6_FILTER_SETBLOCKALL(&filter);
+        ICMP6_FILTER_SETPASS(ND_ROUTER_ADVERT, &filter);
+        r = setsockopt(s, IPPROTO_ICMPV6, ICMP6_FILTER, &filter,
+                       sizeof(filter));
+        if (r < 0)
+                return -errno;
+
+        /* RFC 3315, section 6.7, bullet point 2 may indicate that an
+           IPV6_PKTINFO socket option also applies for ICMPv6 multicast.
+           Empirical experiments indicates otherwise and therefore an
+           IPV6_MULTICAST_IF socket option is used here instead */
+        r = setsockopt(s, IPPROTO_IPV6, IPV6_MULTICAST_IF, &index,
+                       sizeof(index));
+        if (r < 0)
+                return -errno;
+
+        r = setsockopt(s, IPPROTO_IPV6, IPV6_MULTICAST_LOOP, &zero,
+                       sizeof(zero));
+        if (r < 0)
+                return -errno;
+
+        r = setsockopt(s, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, &hops,
+                       sizeof(hops));
+        if (r < 0)
+                return -errno;
+
+        r = setsockopt(s, IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP, &mreq,
+                       sizeof(mreq));
+        if (r < 0)
+                return -errno;
+
+        r = s;
+        s = -1;
+        return r;
+}
+
+int icmp6_send_router_solicitation(int s, const struct ether_addr *ether_addr) {
+        struct sockaddr_in6 dst = {
+                .sin6_family = AF_INET6,
+                .sin6_addr = IN6ADDR_ALL_ROUTERS_MULTICAST_INIT,
+        };
+        struct {
+                struct nd_router_solicit rs;
+                struct nd_opt_hdr rs_opt;
+                struct ether_addr rs_opt_mac;
+        } _packed_ rs = {
+                .rs.nd_rs_type = ND_ROUTER_SOLICIT,
+        };
+        struct iovec iov[1] = {
+                { &rs, },
+        };
+        struct msghdr msg = {
+                .msg_name = &dst,
+                .msg_namelen = sizeof(dst),
+                .msg_iov = iov,
+                .msg_iovlen = 1,
+        };
+        int r;
+
+        if (ether_addr) {
+                memcpy(&rs.rs_opt_mac, ether_addr, ETH_ALEN);
+                rs.rs_opt.nd_opt_type = ND_OPT_SOURCE_LINKADDR;
+                rs.rs_opt.nd_opt_len = 1;
+                iov[0].iov_len = sizeof(rs);
+        } else
+                iov[0].iov_len = sizeof(rs.rs);
+
+        r = sendmsg(s, &msg, 0);
+        if (r < 0)
+                return -errno;
+
+        return 0;
+}
diff --git a/src/libsystemd-network/icmp6-util.h b/src/libsystemd-network/icmp6-util.h
new file mode 100644 (file)
index 0000000..4eb17e1
--- /dev/null
@@ -0,0 +1,27 @@
+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
+
+#pragma once
+
+/***
+  This file is part of systemd.
+
+  Copyright (C) 2014-2015 Intel Corporation. All rights reserved.
+
+  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/>.
+***/
+
+#include <net/ethernet.h>
+
+int icmp6_bind_router_solicitation(int index);
+int icmp6_send_router_solicitation(int s, const struct ether_addr *ether_addr);
index 2a62af2fd47936058f4311dd53cec9412377176e..faf14fe6a222431360bcb64730a35a91070e29f1 100644 (file)
@@ -32,7 +32,7 @@
 #include "conf-parser.h"
 #include "condition.h"
 #include "network-internal.h"
-#include "sd-icmp6-nd.h"
+#include "sd-ndisc.h"
 
 const char *net_get_name(struct udev_device *device) {
         const char *name, *field;
@@ -390,8 +390,8 @@ void serialize_in6_addrs(FILE *f, const struct in6_addr *addresses,
         assert(size);
 
         for (i = 0; i < size; i++)
-                fprintf(f, SD_ICMP6_ND_ADDRESS_FORMAT_STR"%s",
-                        SD_ICMP6_ND_ADDRESS_FORMAT_VAL(addresses[i]),
+                fprintf(f, SD_NDISC_ADDRESS_FORMAT_STR"%s",
+                        SD_NDISC_ADDRESS_FORMAT_VAL(addresses[i]),
                         (i < (size - 1)) ? " ": "");
 }
 
similarity index 50%
rename from src/libsystemd-network/sd-icmp6-nd.c
rename to src/libsystemd-network/sd-ndisc.c
index f014cac628529fef01e207590f94ab966c2ed80e..a36166207285efe34d95186bc49ef629fb3af96d 100644 (file)
 #include <netinet/in.h>
 #include <sys/ioctl.h>
 
-#include "socket-util.h"
 #include "async.h"
+#include "list.h"
+#include "socket-util.h"
 
-#include "dhcp6-internal.h"
-#include "sd-icmp6-nd.h"
+#include "icmp6-util.h"
+#include "sd-ndisc.h"
 
-#define ICMP6_ROUTER_SOLICITATION_INTERVAL      4 * USEC_PER_SEC
-#define ICMP6_MAX_ROUTER_SOLICITATIONS          3
+#define NDISC_ROUTER_SOLICITATION_INTERVAL      4 * USEC_PER_SEC
+#define NDISC_MAX_ROUTER_SOLICITATIONS          3
 
-enum icmp6_nd_state {
-        ICMP6_NEIGHBOR_DISCOVERY_IDLE           = 0,
-        ICMP6_ROUTER_SOLICITATION_SENT          = 10,
-        ICMP6_ROUTER_ADVERTISMENT_LISTEN        = 11,
+enum NDiscState {
+        NDISC_STATE_IDLE,
+        NDISC_STATE_SOLICITATION_SENT,
+        NDISC_STATE_ADVERTISMENT_LISTEN,
+        _NDISC_STATE_MAX,
+        _NDISC_STATE_INVALID = -1,
 };
 
 #define IP6_MIN_MTU (unsigned)1280
-#define ICMP6_ND_RECV_SIZE (IP6_MIN_MTU - sizeof(struct ip6_hdr))
-#define ICMP6_OPT_LEN_UNITS 8
+#define ICMP6_RECV_SIZE (IP6_MIN_MTU - sizeof(struct ip6_hdr))
+#define NDISC_OPT_LEN_UNITS 8
 
-typedef struct ICMP6Prefix ICMP6Prefix;
+typedef struct NDiscPrefix NDiscPrefix;
 
-struct ICMP6Prefix {
+struct NDiscPrefix {
         unsigned n_ref;
 
-        LIST_FIELDS(ICMP6Prefix, prefixes);
+        sd_ndisc *nd;
+
+        LIST_FIELDS(NDiscPrefix, prefixes);
 
         uint8_t len;
-        sd_event_source *timeout_valid;
+        usec_t valid_until;
         struct in6_addr addr;
 };
 
-struct sd_icmp6_nd {
+struct sd_ndisc {
         unsigned n_ref;
 
-        enum icmp6_nd_state state;
+        enum NDiscState state;
         sd_event *event;
         int event_priority;
         int index;
         struct ether_addr mac_addr;
         uint32_t mtu;
-        ICMP6Prefix *expired_prefix;
-        LIST_HEAD(ICMP6Prefix, prefixes);
+        LIST_HEAD(NDiscPrefix, prefixes);
         int fd;
         sd_event_source *recv;
         sd_event_source *timeout;
         int nd_sent;
-        sd_icmp6_nd_callback_t callback;
+        sd_ndisc_callback_t callback;
         void *userdata;
 };
 
-#define log_icmp6_nd(p, fmt, ...) log_internal(LOG_DEBUG, 0, __FILE__, __LINE__, __func__, "ICMPv6 CLIENT: " fmt, ##__VA_ARGS__)
+#define log_ndisc(p, fmt, ...) log_internal(LOG_DEBUG, 0, __FILE__, __LINE__, __func__, "NDisc CLIENT: " fmt, ##__VA_ARGS__)
 
-static ICMP6Prefix *icmp6_prefix_unref(ICMP6Prefix *prefix) {
+static NDiscPrefix *ndisc_prefix_unref(NDiscPrefix *prefix) {
 
         if (!prefix)
                 return NULL;
@@ -87,22 +91,26 @@ static ICMP6Prefix *icmp6_prefix_unref(ICMP6Prefix *prefix) {
         if (prefix->n_ref > 0)
                 return NULL;
 
-        prefix->timeout_valid = sd_event_source_unref(prefix->timeout_valid);
+        if (prefix->nd)
+                LIST_REMOVE(prefixes, prefix->nd->prefixes, prefix);
+
         free(prefix);
+
         return NULL;
 }
 
-static int icmp6_prefix_new(ICMP6Prefix **ret) {
-        _cleanup_free_ ICMP6Prefix *prefix = NULL;
+static int ndisc_prefix_new(sd_ndisc *nd, NDiscPrefix **ret) {
+        _cleanup_free_ NDiscPrefix *prefix = NULL;
 
         assert(ret);
 
-        prefix = new0(ICMP6Prefix, 1);
+        prefix = new0(NDiscPrefix, 1);
         if (!prefix)
                 return -ENOMEM;
 
         prefix->n_ref = 1;
         LIST_INIT(prefixes, prefix);
+        prefix->nd = nd;
 
         *ret = prefix;
         prefix = NULL;
@@ -110,12 +118,12 @@ static int icmp6_prefix_new(ICMP6Prefix **ret) {
         return 0;
 }
 
-static void icmp6_nd_notify(sd_icmp6_nd *nd, int event) {
+static void ndisc_notify(sd_ndisc *nd, int event) {
         if (nd->callback)
                 nd->callback(nd, event, nd->userdata);
 }
 
-int sd_icmp6_nd_set_callback(sd_icmp6_nd *nd, sd_icmp6_nd_callback_t callback,
+int sd_ndisc_set_callback(sd_ndisc *nd, sd_ndisc_callback_t callback,
                              void *userdata) {
         assert(nd);
 
@@ -125,7 +133,7 @@ int sd_icmp6_nd_set_callback(sd_icmp6_nd *nd, sd_icmp6_nd_callback_t callback,
         return 0;
 }
 
-int sd_icmp6_nd_set_index(sd_icmp6_nd *nd, int interface_index) {
+int sd_ndisc_set_index(sd_ndisc *nd, int interface_index) {
         assert(nd);
         assert(interface_index >= -1);
 
@@ -134,7 +142,7 @@ int sd_icmp6_nd_set_index(sd_icmp6_nd *nd, int interface_index) {
         return 0;
 }
 
-int sd_icmp6_nd_set_mac(sd_icmp6_nd *nd, const struct ether_addr *mac_addr) {
+int sd_ndisc_set_mac(sd_ndisc *nd, const struct ether_addr *mac_addr) {
         assert(nd);
 
         if (mac_addr)
@@ -146,7 +154,7 @@ int sd_icmp6_nd_set_mac(sd_icmp6_nd *nd, const struct ether_addr *mac_addr) {
 
 }
 
-int sd_icmp6_nd_attach_event(sd_icmp6_nd *nd, sd_event *event, int priority) {
+int sd_ndisc_attach_event(sd_ndisc *nd, sd_event *event, int priority) {
         int r;
 
         assert_return(nd, -EINVAL);
@@ -165,7 +173,7 @@ int sd_icmp6_nd_attach_event(sd_icmp6_nd *nd, sd_event *event, int priority) {
         return 0;
 }
 
-int sd_icmp6_nd_detach_event(sd_icmp6_nd *nd) {
+int sd_ndisc_detach_event(sd_ndisc *nd) {
         assert_return(nd, -EINVAL);
 
         nd->event = sd_event_unref(nd->event);
@@ -173,13 +181,13 @@ int sd_icmp6_nd_detach_event(sd_icmp6_nd *nd) {
         return 0;
 }
 
-sd_event *sd_icmp6_nd_get_event(sd_icmp6_nd *nd) {
+sd_event *sd_ndisc_get_event(sd_ndisc *nd) {
         assert(nd);
 
         return nd->event;
 }
 
-sd_icmp6_nd *sd_icmp6_nd_ref(sd_icmp6_nd *nd) {
+sd_ndisc *sd_ndisc_ref(sd_ndisc *nd) {
 
         if (!nd)
                 return NULL;
@@ -190,7 +198,7 @@ sd_icmp6_nd *sd_icmp6_nd_ref(sd_icmp6_nd *nd) {
         return nd;
 }
 
-static int icmp6_nd_init(sd_icmp6_nd *nd) {
+static int ndisc_init(sd_ndisc *nd) {
         assert(nd);
 
         nd->recv = sd_event_source_unref(nd->recv);
@@ -200,8 +208,8 @@ static int icmp6_nd_init(sd_icmp6_nd *nd) {
         return 0;
 }
 
-sd_icmp6_nd *sd_icmp6_nd_unref(sd_icmp6_nd *nd) {
-        ICMP6Prefix *prefix, *p;
+sd_ndisc *sd_ndisc_unref(sd_ndisc *nd) {
+        NDiscPrefix *prefix, *p;
 
         if (!nd)
                 return NULL;
@@ -212,29 +220,26 @@ sd_icmp6_nd *sd_icmp6_nd_unref(sd_icmp6_nd *nd) {
         if (nd->n_ref > 0)
                 return NULL;
 
-        icmp6_nd_init(nd);
-        sd_icmp6_nd_detach_event(nd);
-
-        LIST_FOREACH_SAFE(prefixes, prefix, p, nd->prefixes) {
-                LIST_REMOVE(prefixes, nd->prefixes, prefix);
+        ndisc_init(nd);
+        sd_ndisc_detach_event(nd);
 
-                prefix = icmp6_prefix_unref(prefix);
-        }
+        LIST_FOREACH_SAFE(prefixes, prefix, p, nd->prefixes)
+                prefix = ndisc_prefix_unref(prefix);
 
         free(nd);
 
         return NULL;
 }
 
-DEFINE_TRIVIAL_CLEANUP_FUNC(sd_icmp6_nd*, sd_icmp6_nd_unref);
-#define _cleanup_sd_icmp6_nd_free_ _cleanup_(sd_icmp6_nd_unrefp)
+DEFINE_TRIVIAL_CLEANUP_FUNC(sd_ndisc*, sd_ndisc_unref);
+#define _cleanup_sd_ndisc_free_ _cleanup_(sd_ndisc_unrefp)
 
-int sd_icmp6_nd_new(sd_icmp6_nd **ret) {
-        _cleanup_sd_icmp6_nd_free_ sd_icmp6_nd *nd = NULL;
+int sd_ndisc_new(sd_ndisc **ret) {
+        _cleanup_sd_ndisc_free_ sd_ndisc *nd = NULL;
 
         assert(ret);
 
-        nd = new0(sd_icmp6_nd, 1);
+        nd = new0(sd_ndisc, 1);
         if (!nd)
                 return -ENOMEM;
 
@@ -251,7 +256,7 @@ int sd_icmp6_nd_new(sd_icmp6_nd **ret) {
         return 0;
 }
 
-int sd_icmp6_ra_get_mtu(sd_icmp6_nd *nd, uint32_t *mtu) {
+int sd_ndisc_get_mtu(sd_ndisc *nd, uint32_t *mtu) {
         assert_return(nd, -EINVAL);
         assert_return(mtu, -EINVAL);
 
@@ -263,75 +268,9 @@ int sd_icmp6_ra_get_mtu(sd_icmp6_nd *nd, uint32_t *mtu) {
         return 0;
 }
 
-static int icmp6_ra_prefix_timeout(sd_event_source *s, uint64_t usec,
-                                   void *userdata) {
-        sd_icmp6_nd *nd = userdata;
-        ICMP6Prefix *prefix, *p;
-
-        assert(nd);
-
-        LIST_FOREACH_SAFE(prefixes, prefix, p, nd->prefixes) {
-                if (prefix->timeout_valid != s)
-                        continue;
-
-                log_icmp6_nd(nd, "Prefix expired "SD_ICMP6_ND_ADDRESS_FORMAT_STR"/%d",
-                             SD_ICMP6_ND_ADDRESS_FORMAT_VAL(prefix->addr),
-                             prefix->len);
-
-                LIST_REMOVE(prefixes, nd->prefixes, prefix);
-
-                nd->expired_prefix = prefix;
-                icmp6_nd_notify(nd,
-                                SD_ICMP6_ND_EVENT_ROUTER_ADVERTISMENT_PREFIX_EXPIRED);
-                nd->expired_prefix = NULL;
-
-                prefix = icmp6_prefix_unref(prefix);
-
-                break;
-        }
-
-        return 0;
-}
-
-static int icmp6_ra_prefix_set_timeout(sd_icmp6_nd *nd,
-                                       ICMP6Prefix *prefix,
-                                       usec_t valid) {
-        usec_t time_now;
-        int r;
-
-        assert_return(prefix, -EINVAL);
-
-        r = sd_event_now(nd->event, clock_boottime_or_monotonic(), &time_now);
-        if (r < 0)
-                return r;
-
-        prefix->timeout_valid = sd_event_source_unref(prefix->timeout_valid);
-
-        r = sd_event_add_time(nd->event, &prefix->timeout_valid,
-                        clock_boottime_or_monotonic(), time_now + valid,
-                        USEC_PER_SEC, icmp6_ra_prefix_timeout, nd);
-        if (r < 0)
-                goto error;
-
-        r = sd_event_source_set_priority(prefix->timeout_valid,
-                                        nd->event_priority);
-        if (r < 0)
-                goto error;
-
-        r = sd_event_source_set_description(prefix->timeout_valid,
-                                        "icmp6-prefix-timeout");
-
-error:
-        if (r < 0)
-                prefix->timeout_valid =
-                        sd_event_source_unref(prefix->timeout_valid);
-
-        return r;
-}
-
-static int icmp6_prefix_match(const struct in6_addr *prefix, uint8_t prefixlen,
-                              const struct in6_addr *addr,
-                              uint8_t addr_prefixlen) {
+static int prefix_match(const struct in6_addr *prefix, uint8_t prefixlen,
+                        const struct in6_addr *addr,
+                        uint8_t addr_prefixlen) {
         uint8_t bytes, mask, len;
 
         assert_return(prefix, -EINVAL);
@@ -349,69 +288,44 @@ static int icmp6_prefix_match(const struct in6_addr *prefix, uint8_t prefixlen,
         return 0;
 }
 
-static int icmp6_ra_prefix_match(ICMP6Prefix *head, const struct in6_addr *addr,
-                                 uint8_t addr_len, ICMP6Prefix **result) {
-        ICMP6Prefix *prefix;
-
-        LIST_FOREACH(prefixes, prefix, head) {
-                if (icmp6_prefix_match(&prefix->addr, prefix->len, addr,
-                                       addr_len) >= 0) {
-                        *result = prefix;
-                        return 0;
-                }
-        }
-
-        return -EADDRNOTAVAIL;
-}
-
-int sd_icmp6_prefix_match(struct in6_addr *prefix, uint8_t prefixlen,
-                          struct in6_addr *addr) {
-        return icmp6_prefix_match(prefix, prefixlen, addr,
-                                  sizeof(addr->s6_addr) * 8);
-}
-
-int sd_icmp6_ra_get_prefixlen(sd_icmp6_nd *nd, const struct in6_addr *addr,
-                              uint8_t *prefixlen) {
+static int ndisc_prefix_match(sd_ndisc *nd, const struct in6_addr *addr,
+                              uint8_t addr_len, NDiscPrefix **result) {
+        NDiscPrefix *prefix, *p;
+        usec_t time_now;
         int r;
-        ICMP6Prefix *prefix;
 
-        assert_return(nd, -EINVAL);
-        assert_return(addr, -EINVAL);
-        assert_return(prefixlen, -EINVAL);
+        assert(nd);
 
-        r = icmp6_ra_prefix_match(nd->prefixes, addr,
-                                  sizeof(addr->s6_addr) * 8, &prefix);
+        r = sd_event_now(nd->event, clock_boottime_or_monotonic(), &time_now);
         if (r < 0)
                 return r;
 
-        *prefixlen = prefix->len;
-
-        return 0;
-}
-
-int sd_icmp6_ra_get_expired_prefix(sd_icmp6_nd *nd, struct in6_addr **addr, uint8_t *prefixlen) {
-        assert_return(nd, -EINVAL);
-        assert_return(addr, -EINVAL);
-        assert_return(prefixlen, -EINVAL);
+        LIST_FOREACH_SAFE(prefixes, prefix, p, nd->prefixes) {
+                if (prefix->valid_until < time_now) {
+                        prefix = ndisc_prefix_unref(prefix);
 
-        if (!nd->expired_prefix)
-                return -EADDRNOTAVAIL;
+                        continue;
+                }
 
-        *addr = &nd->expired_prefix->addr;
-        *prefixlen = nd->expired_prefix->len;
+                if (prefix_match(&prefix->addr, prefix->len, addr, addr_len) >= 0) {
+                        *result = prefix;
+                        return 0;
+                }
+        }
 
-        return 0;
+        return -EADDRNOTAVAIL;
 }
 
-static int icmp6_ra_prefix_update(sd_icmp6_nd *nd, ssize_t len,
-                                  const struct nd_opt_prefix_info *prefix_opt) {
-        int r;
-        ICMP6Prefix *prefix;
+static int ndisc_prefix_update(sd_ndisc *nd, ssize_t len,
+                               const struct nd_opt_prefix_info *prefix_opt) {
+        NDiscPrefix *prefix;
         uint32_t lifetime;
+        usec_t time_now;
         char time_string[FORMAT_TIMESPAN_MAX];
+        int r;
 
-        assert_return(nd, -EINVAL);
-        assert_return(prefix_opt, -EINVAL);
+        assert(nd);
+        assert(prefix_opt);
 
         if (len < prefix_opt->nd_opt_pi_len)
                 return -ENOMSG;
@@ -421,9 +335,8 @@ static int icmp6_ra_prefix_update(sd_icmp6_nd *nd, ssize_t len,
 
         lifetime = be32toh(prefix_opt->nd_opt_pi_valid_time);
 
-        r = icmp6_ra_prefix_match(nd->prefixes,
-                                  &prefix_opt->nd_opt_pi_prefix,
-                                  prefix_opt->nd_opt_pi_prefix_len, &prefix);
+        r = ndisc_prefix_match(nd, &prefix_opt->nd_opt_pi_prefix,
+                               prefix_opt->nd_opt_pi_prefix_len, &prefix);
 
         if (r < 0 && r != -EADDRNOTAVAIL)
                 return r;
@@ -432,7 +345,7 @@ static int icmp6_ra_prefix_update(sd_icmp6_nd *nd, ssize_t len,
            callback will be called immediately to clean up the prefix */
 
         if (r == -EADDRNOTAVAIL) {
-                r = icmp6_prefix_new(&prefix);
+                r = ndisc_prefix_new(nd, &prefix);
                 if (r < 0)
                         return r;
 
@@ -441,8 +354,8 @@ static int icmp6_ra_prefix_update(sd_icmp6_nd *nd, ssize_t len,
                 memcpy(&prefix->addr, &prefix_opt->nd_opt_pi_prefix,
                         sizeof(prefix->addr));
 
-                log_icmp6_nd(nd, "New prefix "SD_ICMP6_ND_ADDRESS_FORMAT_STR"/%d lifetime %d expires in %s",
-                             SD_ICMP6_ND_ADDRESS_FORMAT_VAL(prefix->addr),
+                log_ndisc(nd, "New prefix "SD_NDISC_ADDRESS_FORMAT_STR"/%d lifetime %d expires in %s",
+                             SD_NDISC_ADDRESS_FORMAT_VAL(prefix->addr),
                              prefix->len, lifetime,
                              format_timespan(time_string, FORMAT_TIMESPAN_MAX, lifetime * USEC_PER_SEC, USEC_PER_SEC));
 
@@ -454,7 +367,7 @@ static int icmp6_ra_prefix_update(sd_icmp6_nd *nd, ssize_t len,
 
                         prefixlen = MIN(prefix->len, prefix_opt->nd_opt_pi_prefix_len);
 
-                        log_icmp6_nd(nd, "Prefix length mismatch %d/%d using %d",
+                        log_ndisc(nd, "Prefix length mismatch %d/%d using %d",
                                      prefix->len,
                                      prefix_opt->nd_opt_pi_prefix_len,
                                      prefixlen);
@@ -462,18 +375,22 @@ static int icmp6_ra_prefix_update(sd_icmp6_nd *nd, ssize_t len,
                         prefix->len = prefixlen;
                 }
 
-                log_icmp6_nd(nd, "Update prefix "SD_ICMP6_ND_ADDRESS_FORMAT_STR"/%d lifetime %d expires in %s",
-                             SD_ICMP6_ND_ADDRESS_FORMAT_VAL(prefix->addr),
+                log_ndisc(nd, "Update prefix "SD_NDISC_ADDRESS_FORMAT_STR"/%d lifetime %d expires in %s",
+                             SD_NDISC_ADDRESS_FORMAT_VAL(prefix->addr),
                              prefix->len, lifetime,
                              format_timespan(time_string, FORMAT_TIMESPAN_MAX, lifetime * USEC_PER_SEC, USEC_PER_SEC));
         }
 
-        r = icmp6_ra_prefix_set_timeout(nd, prefix, lifetime * USEC_PER_SEC);
+        r = sd_event_now(nd->event, clock_boottime_or_monotonic(), &time_now);
+        if (r < 0)
+                return r;
+
+        prefix->valid_until = time_now + lifetime * USEC_PER_SEC;
 
         return r;
 }
 
-static int icmp6_ra_parse(sd_icmp6_nd *nd, struct nd_router_advert *ra,
+static int ndisc_ra_parse(sd_ndisc *nd, struct nd_router_advert *ra,
                           ssize_t len) {
         void *opt;
         struct nd_opt_hdr *opt_hdr;
@@ -482,8 +399,8 @@ static int icmp6_ra_parse(sd_icmp6_nd *nd, struct nd_router_advert *ra,
         assert_return(ra, -EINVAL);
 
         len -= sizeof(*ra);
-        if (len < ICMP6_OPT_LEN_UNITS) {
-                log_icmp6_nd(nd, "Router Advertisement below minimum length");
+        if (len < NDISC_OPT_LEN_UNITS) {
+                log_ndisc(nd, "Router Advertisement below minimum length");
 
                 return -ENOMSG;
         }
@@ -491,7 +408,7 @@ static int icmp6_ra_parse(sd_icmp6_nd *nd, struct nd_router_advert *ra,
         opt = ra + 1;
         opt_hdr = opt;
 
-        while (len != 0 && len >= opt_hdr->nd_opt_len * ICMP6_OPT_LEN_UNITS) {
+        while (len != 0 && len >= opt_hdr->nd_opt_len * NDISC_OPT_LEN_UNITS) {
                 struct nd_opt_mtu *opt_mtu;
                 uint32_t mtu;
                 struct nd_opt_prefix_info *opt_prefix;
@@ -508,7 +425,7 @@ static int icmp6_ra_parse(sd_icmp6_nd *nd, struct nd_router_advert *ra,
                         if (mtu != nd->mtu) {
                                 nd->mtu = MAX(mtu, IP6_MIN_MTU);
 
-                                log_icmp6_nd(nd, "Router Advertisement link MTU %d using %d",
+                                log_ndisc(nd, "Router Advertisement link MTU %d using %d",
                                              mtu, nd->mtu);
                         }
 
@@ -517,29 +434,29 @@ static int icmp6_ra_parse(sd_icmp6_nd *nd, struct nd_router_advert *ra,
                 case ND_OPT_PREFIX_INFORMATION:
                         opt_prefix = opt;
 
-                        icmp6_ra_prefix_update(nd, len, opt_prefix);
+                        ndisc_prefix_update(nd, len, opt_prefix);
 
                         break;
                 }
 
-                len -= opt_hdr->nd_opt_len * ICMP6_OPT_LEN_UNITS;
+                len -= opt_hdr->nd_opt_len * NDISC_OPT_LEN_UNITS;
                 opt = (void *)((char *)opt +
-                        opt_hdr->nd_opt_len * ICMP6_OPT_LEN_UNITS);
+                        opt_hdr->nd_opt_len * NDISC_OPT_LEN_UNITS);
                 opt_hdr = opt;
         }
 
         if (len > 0)
-                log_icmp6_nd(nd, "Router Advertisement contains %zd bytes of trailing garbage", len);
+                log_ndisc(nd, "Router Advertisement contains %zd bytes of trailing garbage", len);
 
         return 0;
 }
 
-static int icmp6_router_advertisment_recv(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
-        sd_icmp6_nd *nd = userdata;
+static int ndisc_router_advertisment_recv(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
+        sd_ndisc *nd = userdata;
         int r, buflen = 0;
         ssize_t len;
         _cleanup_free_ struct nd_router_advert *ra = NULL;
-        int event = SD_ICMP6_ND_EVENT_ROUTER_ADVERTISMENT_NONE;
+        int event = SD_NDISC_EVENT_ROUTER_ADVERTISMENT_NONE;
 
         assert(s);
         assert(nd);
@@ -547,7 +464,7 @@ static int icmp6_router_advertisment_recv(sd_event_source *s, int fd, uint32_t r
 
         r = ioctl(fd, FIONREAD, &buflen);
         if (r < 0 || buflen <= 0)
-                buflen = ICMP6_ND_RECV_SIZE;
+                buflen = ICMP6_RECV_SIZE;
 
         ra = malloc(buflen);
         if (!ra)
@@ -555,7 +472,7 @@ static int icmp6_router_advertisment_recv(sd_event_source *s, int fd, uint32_t r
 
         len = read(fd, ra, buflen);
         if (len < 0) {
-                log_icmp6_nd(nd, "Could not receive message from UDP socket: %m");
+                log_ndisc(nd, "Could not receive message from UDP socket: %m");
                 return 0;
         }
 
@@ -567,34 +484,34 @@ static int icmp6_router_advertisment_recv(sd_event_source *s, int fd, uint32_t r
 
         nd->timeout = sd_event_source_unref(nd->timeout);
 
-        nd->state = ICMP6_ROUTER_ADVERTISMENT_LISTEN;
+        nd->state = NDISC_STATE_ADVERTISMENT_LISTEN;
 
         if (ra->nd_ra_flags_reserved & ND_RA_FLAG_OTHER )
-                event = SD_ICMP6_ND_EVENT_ROUTER_ADVERTISMENT_OTHER;
+                event = SD_NDISC_EVENT_ROUTER_ADVERTISMENT_OTHER;
 
         if (ra->nd_ra_flags_reserved & ND_RA_FLAG_MANAGED)
-                event = SD_ICMP6_ND_EVENT_ROUTER_ADVERTISMENT_MANAGED;
+                event = SD_NDISC_EVENT_ROUTER_ADVERTISMENT_MANAGED;
 
-        log_icmp6_nd(nd, "Received Router Advertisement flags %s/%s",
+        log_ndisc(nd, "Received Router Advertisement flags %s/%s",
                      ra->nd_ra_flags_reserved & ND_RA_FLAG_MANAGED? "MANAGED": "none",
                      ra->nd_ra_flags_reserved & ND_RA_FLAG_OTHER? "OTHER": "none");
 
-        if (event != SD_ICMP6_ND_EVENT_ROUTER_ADVERTISMENT_NONE) {
-                r = icmp6_ra_parse(nd, ra, len);
+        if (event != SD_NDISC_EVENT_ROUTER_ADVERTISMENT_NONE) {
+                r = ndisc_ra_parse(nd, ra, len);
                 if (r < 0) {
-                        log_icmp6_nd(nd, "Could not parse Router Advertisement: %s",
+                        log_ndisc(nd, "Could not parse Router Advertisement: %s",
                                      strerror(-r));
                         return 0;
                 }
         }
 
-        icmp6_nd_notify(nd, event);
+        ndisc_notify(nd, event);
 
         return 0;
 }
 
-static int icmp6_router_solicitation_timeout(sd_event_source *s, uint64_t usec, void *userdata) {
-        sd_icmp6_nd *nd = userdata;
+static int ndisc_router_solicitation_timeout(sd_event_source *s, uint64_t usec, void *userdata) {
+        sd_ndisc *nd = userdata;
         uint64_t time_now, next_timeout;
         struct ether_addr unset = { };
         struct ether_addr *addr = NULL;
@@ -606,89 +523,80 @@ static int icmp6_router_solicitation_timeout(sd_event_source *s, uint64_t usec,
 
         nd->timeout = sd_event_source_unref(nd->timeout);
 
-        if (nd->nd_sent >= ICMP6_MAX_ROUTER_SOLICITATIONS) {
-                icmp6_nd_notify(nd, SD_ICMP6_ND_EVENT_ROUTER_ADVERTISMENT_TIMEOUT);
-                nd->state = ICMP6_ROUTER_ADVERTISMENT_LISTEN;
+        if (nd->nd_sent >= NDISC_MAX_ROUTER_SOLICITATIONS) {
+                ndisc_notify(nd, SD_NDISC_EVENT_ROUTER_ADVERTISMENT_TIMEOUT);
+                nd->state = NDISC_STATE_ADVERTISMENT_LISTEN;
         } else {
                 if (memcmp(&nd->mac_addr, &unset, sizeof(struct ether_addr)))
                         addr = &nd->mac_addr;
 
-                r = dhcp_network_icmp6_send_router_solicitation(nd->fd, addr);
+                r = icmp6_send_router_solicitation(nd->fd, addr);
                 if (r < 0)
-                        log_icmp6_nd(nd, "Error sending Router Solicitation");
+                        log_ndisc(nd, "Error sending Router Solicitation");
                 else {
-                        nd->state = ICMP6_ROUTER_SOLICITATION_SENT;
-                        log_icmp6_nd(nd, "Sent Router Solicitation");
+                        nd->state = NDISC_STATE_SOLICITATION_SENT;
+                        log_ndisc(nd, "Sent Router Solicitation");
                 }
 
                 nd->nd_sent++;
 
-                r = sd_event_now(nd->event, clock_boottime_or_monotonic(), &time_now);
-                if (r < 0) {
-                        icmp6_nd_notify(nd, r);
-                        return 0;
-                }
+                assert_se(sd_event_now(nd->event, clock_boottime_or_monotonic(), &time_now) >= 0);
 
-                next_timeout = time_now + ICMP6_ROUTER_SOLICITATION_INTERVAL;
+                next_timeout = time_now + NDISC_ROUTER_SOLICITATION_INTERVAL;
 
                 r = sd_event_add_time(nd->event, &nd->timeout, clock_boottime_or_monotonic(),
                                       next_timeout, 0,
-                                      icmp6_router_solicitation_timeout, nd);
+                                      ndisc_router_solicitation_timeout, nd);
                 if (r < 0) {
-                        icmp6_nd_notify(nd, r);
+                        ndisc_notify(nd, r);
                         return 0;
                 }
 
-                r = sd_event_source_set_priority(nd->timeout,
-                                                 nd->event_priority);
-                if (r < 0) {
-                        icmp6_nd_notify(nd, r);
+                r = sd_event_source_set_priority(nd->timeout, nd->event_priority);
+                if (r < 0)
                         return 0;
-                }
 
-                r = sd_event_source_set_description(nd->timeout, "icmp6-timeout");
-                if (r < 0) {
-                        icmp6_nd_notify(nd, r);
+                r = sd_event_source_set_description(nd->timeout, "ndisc-timeout");
+                if (r < 0)
                         return 0;
-                }
         }
 
         return 0;
 }
 
-int sd_icmp6_nd_stop(sd_icmp6_nd *nd) {
+int sd_ndisc_stop(sd_ndisc *nd) {
         assert_return(nd, -EINVAL);
         assert_return(nd->event, -EINVAL);
 
-        log_icmp6_nd(client, "Stop ICMPv6");
+        log_ndisc(client, "Stop NDisc");
 
-        icmp6_nd_init(nd);
+        ndisc_init(nd);
 
-        nd->state = ICMP6_NEIGHBOR_DISCOVERY_IDLE;
+        nd->state = NDISC_STATE_IDLE;
 
         return 0;
 }
 
-int sd_icmp6_router_solicitation_start(sd_icmp6_nd *nd) {
+int sd_ndisc_router_discovery_start(sd_ndisc *nd) {
         int r;
 
         assert(nd);
         assert(nd->event);
 
-        if (nd->state != ICMP6_NEIGHBOR_DISCOVERY_IDLE)
+        if (nd->state != NDISC_STATE_IDLE)
                 return -EINVAL;
 
         if (nd->index < 1)
                 return -EINVAL;
 
-        r = dhcp_network_icmp6_bind_router_solicitation(nd->index);
+        r = icmp6_bind_router_solicitation(nd->index);
         if (r < 0)
                 return r;
 
         nd->fd = r;
 
         r = sd_event_add_io(nd->event, &nd->recv, nd->fd, EPOLLIN,
-                            icmp6_router_advertisment_recv, nd);
+                            ndisc_router_advertisment_recv, nd);
         if (r < 0)
                 goto error;
 
@@ -696,12 +604,12 @@ int sd_icmp6_router_solicitation_start(sd_icmp6_nd *nd) {
         if (r < 0)
                 goto error;
 
-        r = sd_event_source_set_description(nd->recv, "icmp6-receive-message");
+        r = sd_event_source_set_description(nd->recv, "ndisc-receive-message");
         if (r < 0)
                 goto error;
 
         r = sd_event_add_time(nd->event, &nd->timeout, clock_boottime_or_monotonic(),
-                              0, 0, icmp6_router_solicitation_timeout, nd);
+                              0, 0, ndisc_router_solicitation_timeout, nd);
         if (r < 0)
                 goto error;
 
@@ -709,12 +617,12 @@ int sd_icmp6_router_solicitation_start(sd_icmp6_nd *nd) {
         if (r < 0)
                 goto error;
 
-        r = sd_event_source_set_description(nd->timeout, "icmp6-timeout");
+        r = sd_event_source_set_description(nd->timeout, "ndisc-timeout");
 error:
         if (r < 0)
-                icmp6_nd_init(nd);
+                ndisc_init(nd);
         else
-                log_icmp6_nd(client, "Start Router Solicitation");
+                log_ndisc(client, "Start Router Solicitation");
 
         return r;
 }
diff --git a/src/libsystemd-network/test-icmp6-rs.c b/src/libsystemd-network/test-icmp6-rs.c
deleted file mode 100644 (file)
index 27b0ef4..0000000
+++ /dev/null
@@ -1,357 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-/***
-  This file is part of systemd.
-
-  Copyright (C) 2014 Intel Corporation. All rights reserved.
-
-  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/>.
-***/
-
-#include <netinet/icmp6.h>
-
-#include "socket-util.h"
-
-#include "dhcp6-internal.h"
-#include "sd-icmp6-nd.h"
-
-static struct ether_addr mac_addr = {
-        .ether_addr_octet = {'A', 'B', 'C', '1', '2', '3'}
-};
-
-static bool verbose = false;
-static sd_event_source *test_hangcheck;
-static int test_fd[2];
-
-typedef int (*send_ra_t)(uint8_t flags);
-static send_ra_t send_ra_function;
-
-static int test_rs_hangcheck(sd_event_source *s, uint64_t usec,
-                             void *userdata) {
-        assert_se(false);
-
-        return 0;
-}
-
-int dhcp_network_icmp6_bind_router_solicitation(int index) {
-        assert_se(index == 42);
-
-        if (socketpair(AF_UNIX, SOCK_DGRAM, 0, test_fd) < 0)
-                return -errno;
-
-        return test_fd[0];
-}
-
-static int send_ra_short_prefix(uint8_t flags) {
-        uint8_t advertisement[] = {
-                0x86, 0x00, 0xbe, 0xd7, 0x40, 0xc0, 0x00, 0xb4,
-                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-
-                0x03, 0x04, 0x34, 0xc0, 0x00, 0x00, 0x01, 0xf4,
-                0x00, 0x00, 0x01, 0xb8, 0x00, 0x00, 0x00, 0x00,
-                0x20, 0x01, 0x0d, 0xb8, 0xde, 0xad, 0xbe, 0xef,
-                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
-        };
-
-        assert_se(write(test_fd[1], advertisement, sizeof(advertisement)) ==
-               sizeof(advertisement));
-
-        return 0;
-}
-
-static void test_short_prefix_cb(sd_icmp6_nd *nd, int event, void *userdata) {
-        sd_event *e = userdata;
-        struct {
-                struct in6_addr addr;
-                uint8_t prefixlen;
-                bool success;
-        } addrs[] = {
-                { { { { 0x20, 0x01, 0x0d, 0xb8, 0xde, 0xad, 0xbe, 0xef,
-                        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } },
-                  52, true },
-                { { { { 0x20, 0x01, 0x0d, 0xb8, 0xde, 0xad, 0x0d, 0xad,
-                        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } },
-                  64, false },
-                { { { { 0x20, 0x01, 0x0d, 0xb8, 0x0b, 0x16, 0xd0, 0x0d,
-                        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } },
-                  60, true },
-                { { { { 0x20, 0x01, 0x0d, 0xb8, 0x00, 0x9d, 0xab, 0xcd,
-                        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } },
-                  64, true },
-                { { { { 0x20, 0x01, 0x0d, 0xb8, 0xde, 0xad, 0xbe, 0xed,
-                        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 } } },
-                  52, true },
-        };
-        uint8_t prefixlen;
-        unsigned int i;
-
-        for (i = 0; i < ELEMENTSOF(addrs); i++) {
-                printf("  %s prefix %02x%02x:%02x%02x:%02x%02x:%02x%02x",
-                        __FUNCTION__,
-                        addrs[i].addr.s6_addr[0], addrs[i].addr.s6_addr[1],
-                        addrs[i].addr.s6_addr[2], addrs[i].addr.s6_addr[3],
-                        addrs[i].addr.s6_addr[4], addrs[i].addr.s6_addr[5],
-                        addrs[i].addr.s6_addr[6], addrs[i].addr.s6_addr[7]);
-
-                if (addrs[i].success) {
-                        assert_se(sd_icmp6_ra_get_prefixlen(nd, &addrs[i].addr,
-                                                                &prefixlen) >= 0);
-                        assert_se(addrs[i].prefixlen == prefixlen);
-                        printf("/%d onlink\n", prefixlen);
-                } else {
-                        assert_se(sd_icmp6_ra_get_prefixlen(nd, &addrs[i].addr,
-                                                                &prefixlen) == -EADDRNOTAVAIL);
-                        printf("/128 offlink\n");
-                }
-        }
-
-        sd_event_exit(e, 0);
-}
-
-static int send_ra_prefixes(uint8_t flags) {
-        uint8_t advertisement[] = {
-                0x86, 0x00, 0xbe, 0xd7, 0x40, 0xc0, 0x00, 0xb4,
-                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-                0x03, 0x04, 0x3f, 0xc0, 0x00, 0x00, 0x01, 0xf4,
-                0x00, 0x00, 0x01, 0xb8, 0x00, 0x00, 0x00, 0x00,
-                0x20, 0x01, 0x0d, 0xb8, 0xde, 0xad, 0xbe, 0xef,
-                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-                0x03, 0x04, 0x40, 0x00, 0x00, 0x00, 0x02, 0x58,
-                0x00, 0x00, 0x02, 0x1c, 0x00, 0x00, 0x00, 0x00,
-                0x20, 0x01, 0x0d, 0xb8, 0xde, 0xad, 0x0d, 0xad,
-                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-                0x03, 0x04, 0x3c, 0x80, 0x00, 0x00, 0x03, 0x84,
-                0x00, 0x00, 0x03, 0x20, 0x00, 0x00, 0x00, 0x00,
-                0x20, 0x01, 0x0d, 0xb8, 0x0b, 0x16, 0xd0, 0x0d,
-                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-                0x03, 0x04, 0x40, 0xc0, 0x00, 0x00, 0x03, 0x84,
-                0x00, 0x00, 0x03, 0x20, 0x00, 0x00, 0x00, 0x00,
-                0x20, 0x01, 0x0d, 0xb8, 0x00, 0x9d, 0xab, 0xcd,
-                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-                0x19, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c,
-                0x20, 0x01, 0x0d, 0xb8, 0xde, 0xad, 0xbe, 0xef,
-                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
-                0x1f, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c,
-                0x03, 0x6c, 0x61, 0x62, 0x05, 0x69, 0x6e, 0x74,
-                0x72, 0x61, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-                0x01, 0x01, 0x78, 0x2b, 0xcb, 0xb3, 0x6d, 0x53
-        };
-
-        assert_se(write(test_fd[1], advertisement, sizeof(advertisement)) ==
-               sizeof(advertisement));
-
-        return 0;
-}
-
-static void test_prefixes_cb(sd_icmp6_nd *nd, int event, void *userdata) {
-        sd_event *e = userdata;
-        struct {
-                struct in6_addr addr;
-                uint8_t prefixlen;
-                bool success;
-        } addrs[] = {
-                { { { { 0x20, 0x01, 0x0d, 0xb8, 0xde, 0xad, 0xbe, 0xef,
-                        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } },
-                  63, true },
-                { { { { 0x20, 0x01, 0x0d, 0xb8, 0xde, 0xad, 0x0d, 0xad,
-                        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } },
-                  64, false },
-                { { { { 0x20, 0x01, 0x0d, 0xb8, 0x0b, 0x16, 0xd0, 0x0d,
-                        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } },
-                  60, true },
-                { { { { 0x20, 0x01, 0x0d, 0xb8, 0x00, 0x9d, 0xab, 0xcd,
-                        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } },
-                  64, true },
-                { { { { 0x20, 0x01, 0x0d, 0xb8, 0xde, 0xad, 0xbe, 0xed,
-                        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 } } },
-                  63, false },
-        };
-        uint8_t prefixlen;
-        unsigned int i;
-
-        for (i = 0; i < ELEMENTSOF(addrs); i++) {
-                printf("  %s prefix %02x%02x:%02x%02x:%02x%02x:%02x%02x",
-                        __FUNCTION__,
-                        addrs[i].addr.s6_addr[0], addrs[i].addr.s6_addr[1],
-                        addrs[i].addr.s6_addr[2], addrs[i].addr.s6_addr[3],
-                        addrs[i].addr.s6_addr[4], addrs[i].addr.s6_addr[5],
-                        addrs[i].addr.s6_addr[6], addrs[i].addr.s6_addr[7]);
-
-                if (addrs[i].success) {
-                        assert_se(sd_icmp6_ra_get_prefixlen(nd, &addrs[i].addr,
-                                                                &prefixlen) >= 0);
-                        assert_se(addrs[i].prefixlen == prefixlen);
-                        printf("/%d onlink\n", prefixlen);
-                } else {
-                        assert_se(sd_icmp6_ra_get_prefixlen(nd, &addrs[i].addr,
-                                                                &prefixlen) == -EADDRNOTAVAIL);
-                        printf("/128 offlink\n");
-                }
-        }
-
-        send_ra_function = send_ra_short_prefix;
-        assert_se(sd_icmp6_nd_set_callback(nd, test_short_prefix_cb, e) >= 0);
-        assert_se(sd_icmp6_nd_stop(nd) >= 0);
-        assert_se(sd_icmp6_router_solicitation_start(nd) >= 0);
-}
-
-static void test_prefixes(void) {
-        sd_event *e;
-        sd_icmp6_nd *nd;
-
-        if (verbose)
-                printf("* %s\n", __FUNCTION__);
-
-        send_ra_function = send_ra_prefixes;
-
-        assert_se(sd_event_new(&e) >= 0);
-
-        assert_se(sd_icmp6_nd_new(&nd) >= 0);
-        assert_se(nd);
-
-        assert_se(sd_icmp6_nd_attach_event(nd, e, 0) >= 0);
-
-        assert_se(sd_icmp6_nd_set_index(nd, 42) >= 0);
-        assert_se(sd_icmp6_nd_set_mac(nd, &mac_addr) >= 0);
-        assert_se(sd_icmp6_nd_set_callback(nd, test_prefixes_cb, e) >= 0);
-
-        assert_se(sd_icmp6_router_solicitation_start(nd) >= 0);
-
-        sd_event_loop(e);
-
-        nd = sd_icmp6_nd_unref(nd);
-        assert_se(!nd);
-
-        close(test_fd[1]);
-
-        sd_event_unref(e);
-}
-
-static int send_ra(uint8_t flags) {
-        uint8_t advertisement[] = {
-                0x86, 0x00, 0xde, 0x83, 0x40, 0xc0, 0x00, 0xb4,
-                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-                0x03, 0x04, 0x40, 0xc0, 0x00, 0x00, 0x01, 0xf4,
-                0x00, 0x00, 0x01, 0xb8, 0x00, 0x00, 0x00, 0x00,
-                0x20, 0x01, 0x0d, 0xb8, 0xde, 0xad, 0xbe, 0xef,
-                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-                0x19, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c,
-                0x20, 0x01, 0x0d, 0xb8, 0xde, 0xad, 0xbe, 0xef,
-                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
-                0x1f, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c,
-                0x03, 0x6c, 0x61, 0x62, 0x05, 0x69, 0x6e, 0x74,
-                0x72, 0x61, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-                0x01, 0x01, 0x78, 0x2b, 0xcb, 0xb3, 0x6d, 0x53,
-        };
-
-        advertisement[5] = flags;
-
-        assert_se(write(test_fd[1], advertisement, sizeof(advertisement)) ==
-               sizeof(advertisement));
-
-        if (verbose)
-                printf("  sent RA with flag 0x%02x\n", flags);
-
-        return 0;
-}
-
-int dhcp_network_icmp6_send_router_solicitation(int s, const struct ether_addr *ether_addr) {
-        return send_ra_function(0);
-}
-
-static void test_rs_done(sd_icmp6_nd *nd, int event, void *userdata) {
-        sd_event *e = userdata;
-        static int idx = 0;
-        struct {
-                uint8_t flag;
-                int event;
-        } flag_event[] = {
-                { 0, SD_ICMP6_ND_EVENT_ROUTER_ADVERTISMENT_NONE },
-                { ND_RA_FLAG_OTHER, SD_ICMP6_ND_EVENT_ROUTER_ADVERTISMENT_OTHER },
-                { ND_RA_FLAG_MANAGED, SD_ICMP6_ND_EVENT_ROUTER_ADVERTISMENT_MANAGED }
-        };
-        uint32_t mtu;
-
-        assert_se(nd);
-
-        assert_se(event == flag_event[idx].event);
-        idx++;
-
-        if (verbose)
-                printf("  got event %d\n", event);
-
-        if (idx < 3) {
-                send_ra(flag_event[idx].flag);
-                return;
-        }
-
-        assert_se(sd_icmp6_ra_get_mtu(nd, &mtu) == -ENOMSG);
-
-        sd_event_exit(e, 0);
-}
-
-static void test_rs(void) {
-        sd_event *e;
-        sd_icmp6_nd *nd;
-        usec_t time_now = now(clock_boottime_or_monotonic());
-
-        if (verbose)
-                printf("* %s\n", __FUNCTION__);
-
-        send_ra_function = send_ra;
-
-        assert_se(sd_event_new(&e) >= 0);
-
-        assert_se(sd_icmp6_nd_new(&nd) >= 0);
-        assert_se(nd);
-
-        assert_se(sd_icmp6_nd_attach_event(nd, e, 0) >= 0);
-
-        assert_se(sd_icmp6_nd_set_index(nd, 42) >= 0);
-        assert_se(sd_icmp6_nd_set_mac(nd, &mac_addr) >= 0);
-        assert_se(sd_icmp6_nd_set_callback(nd, test_rs_done, e) >= 0);
-
-        assert_se(sd_event_add_time(e, &test_hangcheck, clock_boottime_or_monotonic(),
-                                 time_now + 2 *USEC_PER_SEC, 0,
-                                 test_rs_hangcheck, NULL) >= 0);
-
-        assert_se(sd_icmp6_nd_stop(nd) >= 0);
-        assert_se(sd_icmp6_router_solicitation_start(nd) >= 0);
-        assert_se(sd_icmp6_nd_stop(nd) >= 0);
-
-        assert_se(sd_icmp6_router_solicitation_start(nd) >= 0);
-
-        sd_event_loop(e);
-
-        test_hangcheck = sd_event_source_unref(test_hangcheck);
-
-        nd = sd_icmp6_nd_unref(nd);
-        assert_se(!nd);
-
-        close(test_fd[1]);
-
-        sd_event_unref(e);
-}
-
-int main(int argc, char *argv[]) {
-
-        log_set_max_level(LOG_DEBUG);
-        log_parse_environment();
-        log_open();
-
-        test_rs();
-        test_prefixes();
-
-        return 0;
-}
diff --git a/src/libsystemd-network/test-ndisc-rs.c b/src/libsystemd-network/test-ndisc-rs.c
new file mode 100644 (file)
index 0000000..765198e
--- /dev/null
@@ -0,0 +1,171 @@
+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
+
+/***
+  This file is part of systemd.
+
+  Copyright (C) 2014 Intel Corporation. All rights reserved.
+
+  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/>.
+***/
+
+#include <netinet/icmp6.h>
+
+#include "socket-util.h"
+
+#include "icmp6-util.h"
+#include "sd-ndisc.h"
+
+static struct ether_addr mac_addr = {
+        .ether_addr_octet = {'A', 'B', 'C', '1', '2', '3'}
+};
+
+static bool verbose = false;
+static sd_event_source *test_hangcheck;
+static int test_fd[2];
+
+typedef int (*send_ra_t)(uint8_t flags);
+static send_ra_t send_ra_function;
+
+static int test_rs_hangcheck(sd_event_source *s, uint64_t usec,
+                             void *userdata) {
+        assert_se(false);
+
+        return 0;
+}
+
+int icmp6_bind_router_solicitation(int index) {
+        assert_se(index == 42);
+
+        if (socketpair(AF_UNIX, SOCK_DGRAM, 0, test_fd) < 0)
+                return -errno;
+
+        return test_fd[0];
+}
+
+static int send_ra(uint8_t flags) {
+        uint8_t advertisement[] = {
+                0x86, 0x00, 0xde, 0x83, 0x40, 0xc0, 0x00, 0xb4,
+                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                0x03, 0x04, 0x40, 0xc0, 0x00, 0x00, 0x01, 0xf4,
+                0x00, 0x00, 0x01, 0xb8, 0x00, 0x00, 0x00, 0x00,
+                0x20, 0x01, 0x0d, 0xb8, 0xde, 0xad, 0xbe, 0xef,
+                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                0x19, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c,
+                0x20, 0x01, 0x0d, 0xb8, 0xde, 0xad, 0xbe, 0xef,
+                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
+                0x1f, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c,
+                0x03, 0x6c, 0x61, 0x62, 0x05, 0x69, 0x6e, 0x74,
+                0x72, 0x61, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                0x01, 0x01, 0x78, 0x2b, 0xcb, 0xb3, 0x6d, 0x53,
+        };
+
+        advertisement[5] = flags;
+
+        assert_se(write(test_fd[1], advertisement, sizeof(advertisement)) ==
+               sizeof(advertisement));
+
+        if (verbose)
+                printf("  sent RA with flag 0x%02x\n", flags);
+
+        return 0;
+}
+
+int icmp6_send_router_solicitation(int s, const struct ether_addr *ether_addr) {
+        return send_ra_function(0);
+}
+
+static void test_rs_done(sd_ndisc *nd, int event, void *userdata) {
+        sd_event *e = userdata;
+        static int idx = 0;
+        struct {
+                uint8_t flag;
+                int event;
+        } flag_event[] = {
+                { 0, SD_NDISC_EVENT_ROUTER_ADVERTISMENT_NONE },
+                { ND_RA_FLAG_OTHER, SD_NDISC_EVENT_ROUTER_ADVERTISMENT_OTHER },
+                { ND_RA_FLAG_MANAGED, SD_NDISC_EVENT_ROUTER_ADVERTISMENT_MANAGED }
+        };
+        uint32_t mtu;
+
+        assert_se(nd);
+
+        assert_se(event == flag_event[idx].event);
+        idx++;
+
+        if (verbose)
+                printf("  got event %d\n", event);
+
+        if (idx < 3) {
+                send_ra(flag_event[idx].flag);
+                return;
+        }
+
+        assert_se(sd_ndisc_get_mtu(nd, &mtu) == -ENOMSG);
+
+        sd_event_exit(e, 0);
+}
+
+static void test_rs(void) {
+        sd_event *e;
+        sd_ndisc *nd;
+        usec_t time_now = now(clock_boottime_or_monotonic());
+
+        if (verbose)
+                printf("* %s\n", __FUNCTION__);
+
+        send_ra_function = send_ra;
+
+        assert_se(sd_event_new(&e) >= 0);
+
+        assert_se(sd_ndisc_new(&nd) >= 0);
+        assert_se(nd);
+
+        assert_se(sd_ndisc_attach_event(nd, e, 0) >= 0);
+
+        assert_se(sd_ndisc_set_index(nd, 42) >= 0);
+        assert_se(sd_ndisc_set_mac(nd, &mac_addr) >= 0);
+        assert_se(sd_ndisc_set_callback(nd, test_rs_done, e) >= 0);
+
+        assert_se(sd_event_add_time(e, &test_hangcheck, clock_boottime_or_monotonic(),
+                                 time_now + 2 *USEC_PER_SEC, 0,
+                                 test_rs_hangcheck, NULL) >= 0);
+
+        assert_se(sd_ndisc_stop(nd) >= 0);
+        assert_se(sd_ndisc_router_discovery_start(nd) >= 0);
+        assert_se(sd_ndisc_stop(nd) >= 0);
+
+        assert_se(sd_ndisc_router_discovery_start(nd) >= 0);
+
+        sd_event_loop(e);
+
+        test_hangcheck = sd_event_source_unref(test_hangcheck);
+
+        nd = sd_ndisc_unref(nd);
+        assert_se(!nd);
+
+        close(test_fd[1]);
+
+        sd_event_unref(e);
+}
+
+int main(int argc, char *argv[]) {
+
+        log_set_max_level(LOG_DEBUG);
+        log_parse_environment();
+        log_open();
+
+        test_rs();
+
+        return 0;
+}
index fb93e6606ebdac657069b2c12784a537da68096c..57c81cb6467518b00a0345e9df3b2ba08318af70 100644 (file)
@@ -25,7 +25,6 @@
 #include "networkd-link.h"
 #include "network-internal.h"
 
-#include "sd-icmp6-nd.h"
 #include "sd-dhcp6-client.h"
 
 static int dhcp6_lease_address_acquired(sd_dhcp6_client *client, Link *link);
@@ -64,8 +63,7 @@ static int dhcp6_address_handler(sd_netlink *rtnl, sd_netlink_message *m,
 }
 
 static int dhcp6_address_change(Link *link, struct in6_addr *ip6_addr,
-                                uint8_t prefixlen, uint32_t lifetime_preferred,
-                                uint32_t lifetime_valid) {
+                                uint32_t lifetime_preferred, uint32_t lifetime_valid) {
         int r;
         _cleanup_address_free_ Address *addr = NULL;
 
@@ -77,14 +75,14 @@ static int dhcp6_address_change(Link *link, struct in6_addr *ip6_addr,
         memcpy(&addr->in_addr.in6, ip6_addr, sizeof(*ip6_addr));
 
         addr->flags = IFA_F_NOPREFIXROUTE;
-        addr->prefixlen = prefixlen;
+        addr->prefixlen = 128;
 
         addr->cinfo.ifa_prefered = lifetime_preferred;
         addr->cinfo.ifa_valid = lifetime_valid;
 
         log_link_info(link,
-                      "DHCPv6 address "SD_ICMP6_ND_ADDRESS_FORMAT_STR"/%d timeout preferred %d valid %d",
-                      SD_ICMP6_ND_ADDRESS_FORMAT_VAL(addr->in_addr.in6),
+                      "DHCPv6 address "SD_NDISC_ADDRESS_FORMAT_STR"/%d timeout preferred %d valid %d",
+                      SD_NDISC_ADDRESS_FORMAT_VAL(addr->in_addr.in6),
                       addr->prefixlen, lifetime_preferred, lifetime_valid);
 
         r = address_configure(addr, link, dhcp6_address_handler, true);
@@ -99,7 +97,6 @@ static int dhcp6_lease_address_acquired(sd_dhcp6_client *client, Link *link) {
         sd_dhcp6_lease *lease;
         struct in6_addr ip6_addr;
         uint32_t lifetime_preferred, lifetime_valid;
-        uint8_t prefixlen;
 
         r = sd_dhcp6_client_get_lease(client, &lease);
         if (r < 0)
@@ -111,18 +108,7 @@ static int dhcp6_lease_address_acquired(sd_dhcp6_client *client, Link *link) {
                                                 &lifetime_preferred,
                                                 &lifetime_valid) >= 0) {
 
-                r = sd_icmp6_ra_get_prefixlen(link->icmp6_router_discovery,
-                                        &ip6_addr, &prefixlen);
-                if (r < 0 && r != -EADDRNOTAVAIL) {
-                        log_link_warning_errno(link, r, "Could not get prefix information: %m");
-                        return r;
-                }
-
-                if (r == -EADDRNOTAVAIL)
-                        prefixlen = 128;
-
-                r = dhcp6_address_change(link, &ip6_addr, prefixlen,
-                                        lifetime_preferred, lifetime_valid);
+                r = dhcp6_address_change(link, &ip6_addr, lifetime_preferred, lifetime_valid);
                 if (r < 0)
                         return r;
         }
@@ -179,34 +165,29 @@ static void dhcp6_handler(sd_dhcp6_client *client, int event, void *userdata) {
         link_check_ready(link);
 }
 
-static int dhcp6_configure(Link *link, int event) {
+int dhcp6_configure(Link *link, bool inf_req) {
         int r;
         bool information_request;
 
         assert_return(link, -EINVAL);
-        assert_return(IN_SET(event, SD_ICMP6_ND_EVENT_ROUTER_ADVERTISMENT_TIMEOUT,
-                             SD_ICMP6_ND_EVENT_ROUTER_ADVERTISMENT_OTHER,
-                             SD_ICMP6_ND_EVENT_ROUTER_ADVERTISMENT_MANAGED), -EINVAL);
 
         link->dhcp6_configured = false;
 
         if (link->dhcp6_client) {
-                r = sd_dhcp6_client_get_information_request(link->dhcp6_client,
-                                                        &information_request);
+                r = sd_dhcp6_client_get_information_request(link->dhcp6_client, &information_request);
                 if (r < 0) {
                         log_link_warning_errno(link, r, "Could not get DHCPv6 Information request setting: %m");
                         goto error;
                 }
 
-                if (information_request && event != SD_ICMP6_ND_EVENT_ROUTER_ADVERTISMENT_OTHER) {
+                if (information_request && !inf_req) {
                         r = sd_dhcp6_client_stop(link->dhcp6_client);
                         if (r < 0) {
                                 log_link_warning_errno(link, r, "Could not stop DHCPv6 while setting Managed mode: %m");
                                 goto error;
                         }
 
-                        r = sd_dhcp6_client_set_information_request(link->dhcp6_client,
-                                                                    false);
+                        r = sd_dhcp6_client_set_information_request(link->dhcp6_client, false);
                         if (r < 0) {
                                 log_link_warning_errno(link, r, "Could not unset DHCPv6 Information request: %m");
                                 goto error;
@@ -249,9 +230,8 @@ static int dhcp6_configure(Link *link, int event) {
         if (r < 0)
                 goto error;
 
-        if (event == SD_ICMP6_ND_EVENT_ROUTER_ADVERTISMENT_OTHER) {
-                r = sd_dhcp6_client_set_information_request(link->dhcp6_client,
-                                                        true);
+        if (inf_req) {
+                r = sd_dhcp6_client_set_information_request(link->dhcp6_client, true);
                 if (r < 0)
                         goto error;
         }
@@ -266,107 +246,3 @@ static int dhcp6_configure(Link *link, int event) {
         link->dhcp6_client = sd_dhcp6_client_unref(link->dhcp6_client);
         return r;
 }
-
-static int dhcp6_prefix_expired(Link *link) {
-        int r;
-        sd_dhcp6_lease *lease;
-        struct in6_addr *expired_prefix, ip6_addr;
-        uint8_t expired_prefixlen;
-        uint32_t lifetime_preferred, lifetime_valid;
-
-        r = sd_icmp6_ra_get_expired_prefix(link->icmp6_router_discovery,
-                                        &expired_prefix, &expired_prefixlen);
-        if (r < 0)
-                return r;
-
-        r = sd_dhcp6_client_get_lease(link->dhcp6_client, &lease);
-        if (r < 0)
-                return r;
-
-        log_link_info(link, "IPv6 prefix "SD_ICMP6_ND_ADDRESS_FORMAT_STR"/%d expired",
-                      SD_ICMP6_ND_ADDRESS_FORMAT_VAL(*expired_prefix),
-                      expired_prefixlen);
-
-        sd_dhcp6_lease_reset_address_iter(lease);
-
-        while (sd_dhcp6_lease_get_address(lease, &ip6_addr,
-                                                &lifetime_preferred,
-                                                &lifetime_valid) >= 0) {
-
-                r = sd_icmp6_prefix_match(expired_prefix, expired_prefixlen,
-                                        &ip6_addr);
-                if (r < 0)
-                        continue;
-
-                log_link_info(link, "IPv6 prefix length updated "SD_ICMP6_ND_ADDRESS_FORMAT_STR"/%d", SD_ICMP6_ND_ADDRESS_FORMAT_VAL(ip6_addr), 128);
-
-                dhcp6_address_change(link, &ip6_addr, 128, lifetime_preferred, lifetime_valid);
-        }
-
-        return 0;
-}
-
-static void icmp6_router_handler(sd_icmp6_nd *nd, int event, void *userdata) {
-        Link *link = userdata;
-
-        assert(link);
-        assert(link->network);
-        assert(link->manager);
-
-        if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
-                return;
-
-        switch(event) {
-        case SD_ICMP6_ND_EVENT_ROUTER_ADVERTISMENT_NONE:
-                return;
-
-        case SD_ICMP6_ND_EVENT_ROUTER_ADVERTISMENT_TIMEOUT:
-        case SD_ICMP6_ND_EVENT_ROUTER_ADVERTISMENT_OTHER:
-        case SD_ICMP6_ND_EVENT_ROUTER_ADVERTISMENT_MANAGED:
-                dhcp6_configure(link, event);
-
-                break;
-
-        case SD_ICMP6_ND_EVENT_ROUTER_ADVERTISMENT_PREFIX_EXPIRED:
-                if (!link->rtnl_extended_attrs)
-                        dhcp6_prefix_expired(link);
-
-                break;
-
-        default:
-                if (event < 0)
-                        log_link_warning_errno(link, event, "ICMPv6 error: %m");
-                else
-                        log_link_warning(link, "ICMPv6 unknown event: %d", event);
-
-                break;
-        }
-
-}
-
-int icmp6_configure(Link *link) {
-        int r;
-
-        assert_return(link, -EINVAL);
-
-        r = sd_icmp6_nd_new(&link->icmp6_router_discovery);
-        if (r < 0)
-                return r;
-
-        r = sd_icmp6_nd_attach_event(link->icmp6_router_discovery, NULL, 0);
-        if (r < 0)
-                return r;
-
-        r = sd_icmp6_nd_set_mac(link->icmp6_router_discovery, &link->mac);
-        if (r < 0)
-                return r;
-
-        r = sd_icmp6_nd_set_index(link->icmp6_router_discovery, link->ifindex);
-        if (r < 0)
-                return r;
-
-        r = sd_icmp6_nd_set_callback(link->icmp6_router_discovery,
-                                icmp6_router_handler, link);
-
-        return r;
-}
index ec4b082542edcbc41f1040e613deb6cc0a3877a5..09f4bd7029c572cead7e0640125d8bab1a11da5f 100644 (file)
@@ -370,7 +370,7 @@ static void link_free(Link *link) {
 
         sd_ipv4ll_unref(link->ipv4ll);
         sd_dhcp6_client_unref(link->dhcp6_client);
-        sd_icmp6_nd_unref(link->icmp6_router_discovery);
+        sd_ndisc_unref(link->ndisc_router_discovery);
 
         if (link->manager)
                 hashmap_remove(link->manager->links, INT_TO_PTR(link->ifindex));
@@ -481,16 +481,16 @@ static int link_stop_clients(Link *link) {
                         r = log_link_warning_errno(link, r, "Could not stop IPv4 link-local: %m");
         }
 
-        if(link->icmp6_router_discovery) {
+        if(link->ndisc_router_discovery) {
                 if (link->dhcp6_client) {
                         k = sd_dhcp6_client_stop(link->dhcp6_client);
                         if (k < 0)
                                 r = log_link_warning_errno(link, r, "Could not stop DHCPv6 client: %m");
                 }
 
-                k = sd_icmp6_nd_stop(link->icmp6_router_discovery);
+                k = sd_ndisc_stop(link->ndisc_router_discovery);
                 if (k < 0)
-                        r = log_link_warning_errno(link, r, "Could not stop ICMPv6 router discovery: %m");
+                        r = log_link_warning_errno(link, r, "Could not stop IPv6 Router Discovery: %m");
         }
 
         if (link->lldp) {
@@ -1238,13 +1238,13 @@ static int link_acquire_conf(Link *link) {
         }
 
         if (link_dhcp6_enabled(link)) {
-                assert(link->icmp6_router_discovery);
+                assert(link->ndisc_router_discovery);
 
                 log_link_debug(link, "Discovering IPv6 routers");
 
-                r = sd_icmp6_router_solicitation_start(link->icmp6_router_discovery);
+                r = sd_ndisc_router_discovery_start(link->ndisc_router_discovery);
                 if (r < 0)
-                        return log_link_warning_errno(link, r, "Could not start IPv6 router discovery: %m");
+                        return log_link_warning_errno(link, r, "Could not start IPv6 Router Discovery: %m");
         }
 
         if (link_lldp_enabled(link)) {
@@ -2002,7 +2002,7 @@ static int link_configure(Link *link) {
         }
 
         if (link_dhcp6_enabled(link)) {
-                r = icmp6_configure(link);
+                r = ndisc_configure(link);
                 if (r < 0)
                         return r;
         }
index af2ba11701b8a23a49881c7fab51068a5ca85bf6..5c92df4ca8d0221111404e184fb52cf481f01a72 100644 (file)
@@ -26,7 +26,7 @@
 #include "sd-dhcp-client.h"
 #include "sd-dhcp-server.h"
 #include "sd-ipv4ll.h"
-#include "sd-icmp6-nd.h"
+#include "sd-ndisc.h"
 #include "sd-dhcp6-client.h"
 #include "sd-lldp.h"
 
@@ -104,7 +104,7 @@ struct Link {
 
         sd_dhcp_server *dhcp_server;
 
-        sd_icmp6_nd *icmp6_router_discovery;
+        sd_ndisc *ndisc_router_discovery;
         sd_dhcp6_client *dhcp6_client;
         bool rtnl_extended_attrs;
 
@@ -145,7 +145,8 @@ int link_set_timezone(Link *link, const char *timezone);
 
 int ipv4ll_configure(Link *link);
 int dhcp4_configure(Link *link);
-int icmp6_configure(Link *link);
+int dhcp6_configure(Link *link, bool information_request);
+int ndisc_configure(Link *link);
 
 bool link_lldp_enabled(Link *link);
 bool link_ipv4ll_enabled(Link *link);
index 76d5aa5585cb5fdbbee4f55b26085d4eda56009f..e0e1679edeedf0691af34ea54cc88c810f62f3ce 100644 (file)
@@ -409,7 +409,7 @@ int manager_rtnl_process_address(sd_netlink *rtnl, sd_netlink_message *message,
                                 log_link_debug(link, "Adding address: %s/%u (valid for %s)", buf, prefixlen, valid_str);
                 }
 
-                address_update(address, scope, flags, &cinfo);
+                address_update(address, flags, scope, &cinfo);
 
                 break;
 
diff --git a/src/network/networkd-ndisc.c b/src/network/networkd-ndisc.c
new file mode 100644 (file)
index 0000000..637c299
--- /dev/null
@@ -0,0 +1,88 @@
+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
+
+/***
+  This file is part of systemd.
+
+  Copyright (C) 2014 Intel Corporation. All rights reserved.
+
+  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/>.
+***/
+
+#include <netinet/ether.h>
+#include <linux/if.h>
+
+#include "networkd-link.h"
+
+#include "sd-ndisc.h"
+
+static void ndisc_router_handler(sd_ndisc *nd, int event, void *userdata) {
+        Link *link = userdata;
+
+        assert(link);
+        assert(link->network);
+        assert(link->manager);
+
+        if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
+                return;
+
+        switch(event) {
+        case SD_NDISC_EVENT_ROUTER_ADVERTISMENT_NONE:
+                return;
+
+        case SD_NDISC_EVENT_ROUTER_ADVERTISMENT_OTHER:
+                dhcp6_configure(link, true);
+
+                break;
+        case SD_NDISC_EVENT_ROUTER_ADVERTISMENT_TIMEOUT:
+        case SD_NDISC_EVENT_ROUTER_ADVERTISMENT_MANAGED:
+                dhcp6_configure(link, false);
+
+                break;
+
+        default:
+                if (event < 0)
+                        log_link_warning_errno(link, event, "IPv6 Neighbor Discover error: %m");
+                else
+                        log_link_warning(link, "IPv6 Neighbor Discovery unknown event: %d", event);
+
+                break;
+        }
+}
+
+int ndisc_configure(Link *link) {
+        int r;
+
+        assert_return(link, -EINVAL);
+
+        r = sd_ndisc_new(&link->ndisc_router_discovery);
+        if (r < 0)
+                return r;
+
+        r = sd_ndisc_attach_event(link->ndisc_router_discovery, NULL, 0);
+        if (r < 0)
+                return r;
+
+        r = sd_ndisc_set_mac(link->ndisc_router_discovery, &link->mac);
+        if (r < 0)
+                return r;
+
+        r = sd_ndisc_set_index(link->ndisc_router_discovery, link->ifindex);
+        if (r < 0)
+                return r;
+
+        r = sd_ndisc_set_callback(link->ndisc_router_discovery,
+                                  ndisc_router_handler, link);
+
+        return r;
+}
diff --git a/src/systemd/sd-icmp6-nd.h b/src/systemd/sd-icmp6-nd.h
deleted file mode 100644 (file)
index cb6c24a..0000000
+++ /dev/null
@@ -1,79 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-#ifndef foosdicmp6ndfoo
-#define foosdicmp6ndfoo
-
-/***
-  This file is part of systemd.
-
-  Copyright (C) 2014 Intel Corporation. All rights reserved.
-
-  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/>.
-***/
-
-#include <net/ethernet.h>
-
-#include "sd-event.h"
-
-enum {
-        SD_ICMP6_ND_EVENT_ROUTER_ADVERTISMENT_NONE              = 0,
-        SD_ICMP6_ND_EVENT_ROUTER_ADVERTISMENT_TIMEOUT           = 1,
-        SD_ICMP6_ND_EVENT_ROUTER_ADVERTISMENT_OTHER             = 2,
-        SD_ICMP6_ND_EVENT_ROUTER_ADVERTISMENT_MANAGED           = 3,
-        SD_ICMP6_ND_EVENT_ROUTER_ADVERTISMENT_PREFIX_EXPIRED    = 4,
-};
-
-typedef struct sd_icmp6_nd sd_icmp6_nd;
-
-typedef void(*sd_icmp6_nd_callback_t)(sd_icmp6_nd *nd, int event,
-                                      void *userdata);
-
-int sd_icmp6_nd_set_callback(sd_icmp6_nd *nd, sd_icmp6_nd_callback_t cb,
-                             void *userdata);
-int sd_icmp6_nd_set_index(sd_icmp6_nd *nd, int interface_index);
-int sd_icmp6_nd_set_mac(sd_icmp6_nd *nd, const struct ether_addr *mac_addr);
-
-int sd_icmp6_nd_attach_event(sd_icmp6_nd *nd, sd_event *event, int priority);
-int sd_icmp6_nd_detach_event(sd_icmp6_nd *nd);
-sd_event *sd_icmp6_nd_get_event(sd_icmp6_nd *nd);
-
-sd_icmp6_nd *sd_icmp6_nd_ref(sd_icmp6_nd *nd);
-sd_icmp6_nd *sd_icmp6_nd_unref(sd_icmp6_nd *nd);
-int sd_icmp6_nd_new(sd_icmp6_nd **ret);
-
-int sd_icmp6_prefix_match(struct in6_addr *prefix, uint8_t prefixlen,
-                        struct in6_addr *addr);
-
-int sd_icmp6_ra_get_mtu(sd_icmp6_nd *nd, uint32_t *mtu);
-int sd_icmp6_ra_get_prefixlen(sd_icmp6_nd *nd, const struct in6_addr *addr,
-                        uint8_t *prefixlen);
-int sd_icmp6_ra_get_expired_prefix(sd_icmp6_nd *nd, struct in6_addr **addr,
-                                uint8_t *prefixlen);
-
-int sd_icmp6_nd_stop(sd_icmp6_nd *nd);
-int sd_icmp6_router_solicitation_start(sd_icmp6_nd *nd);
-
-#define SD_ICMP6_ND_ADDRESS_FORMAT_STR "%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x"
-
-#define SD_ICMP6_ND_ADDRESS_FORMAT_VAL(address) \
-        be16toh((address).s6_addr16[0]),        \
-        be16toh((address).s6_addr16[1]),        \
-        be16toh((address).s6_addr16[2]),        \
-        be16toh((address).s6_addr16[3]),        \
-        be16toh((address).s6_addr16[4]),        \
-        be16toh((address).s6_addr16[5]),        \
-        be16toh((address).s6_addr16[6]),        \
-        be16toh((address).s6_addr16[7])
-
-#endif
diff --git a/src/systemd/sd-ndisc.h b/src/systemd/sd-ndisc.h
new file mode 100644 (file)
index 0000000..83575c6
--- /dev/null
@@ -0,0 +1,71 @@
+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
+
+#ifndef foosdndiscfoo
+#define foosdndiscfoo
+
+/***
+  This file is part of systemd.
+
+  Copyright (C) 2014 Intel Corporation. All rights reserved.
+
+  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/>.
+***/
+
+#include <net/ethernet.h>
+
+#include "sd-event.h"
+
+enum {
+        SD_NDISC_EVENT_ROUTER_ADVERTISMENT_NONE              = 0,
+        SD_NDISC_EVENT_ROUTER_ADVERTISMENT_TIMEOUT           = 1,
+        SD_NDISC_EVENT_ROUTER_ADVERTISMENT_OTHER             = 2,
+        SD_NDISC_EVENT_ROUTER_ADVERTISMENT_MANAGED           = 3,
+};
+
+typedef struct sd_ndisc sd_ndisc;
+
+typedef void(*sd_ndisc_callback_t)(sd_ndisc *nd, int event,
+                                      void *userdata);
+
+int sd_ndisc_set_callback(sd_ndisc *nd, sd_ndisc_callback_t cb,
+                             void *userdata);
+int sd_ndisc_set_index(sd_ndisc *nd, int interface_index);
+int sd_ndisc_set_mac(sd_ndisc *nd, const struct ether_addr *mac_addr);
+
+int sd_ndisc_attach_event(sd_ndisc *nd, sd_event *event, int priority);
+int sd_ndisc_detach_event(sd_ndisc *nd);
+sd_event *sd_ndisc_get_event(sd_ndisc *nd);
+
+sd_ndisc *sd_ndisc_ref(sd_ndisc *nd);
+sd_ndisc *sd_ndisc_unref(sd_ndisc *nd);
+int sd_ndisc_new(sd_ndisc **ret);
+
+int sd_ndisc_get_mtu(sd_ndisc *nd, uint32_t *mtu);
+
+int sd_ndisc_stop(sd_ndisc *nd);
+int sd_ndisc_router_discovery_start(sd_ndisc *nd);
+
+#define SD_NDISC_ADDRESS_FORMAT_STR "%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x"
+
+#define SD_NDISC_ADDRESS_FORMAT_VAL(address) \
+        be16toh((address).s6_addr16[0]),        \
+        be16toh((address).s6_addr16[1]),        \
+        be16toh((address).s6_addr16[2]),        \
+        be16toh((address).s6_addr16[3]),        \
+        be16toh((address).s6_addr16[4]),        \
+        be16toh((address).s6_addr16[5]),        \
+        be16toh((address).s6_addr16[6]),        \
+        be16toh((address).s6_addr16[7])
+
+#endif
index 503e84080349f4f66c253e66699ee9b64cb133ed..b5d9d01ba0eebd5a25542896c829050eef80f0c0 100644 (file)
@@ -1639,6 +1639,12 @@ static void test_extract_first_word(void) {
         free(t);
         assert_se(isempty(p));
 
+        p = original = "\"fooo";
+        assert_se(extract_first_word(&p, &t, NULL, EXTRACT_QUOTES|EXTRACT_RELAX) > 0);
+        assert_se(streq(t, "fooo"));
+        free(t);
+        assert_se(isempty(p));
+
         p = original = "yay\'foo\'bar";
         assert_se(extract_first_word(&p, &t, NULL, 0) > 0);
         assert_se(streq(t, "yay\'foo\'bar"));