chiark / gitweb /
rtnl: replace message_append by typesafe versions
authorTom Gundersen <teg@jklm.no>
Sun, 15 Dec 2013 13:00:20 +0000 (14:00 +0100)
committerTom Gundersen <teg@jklm.no>
Mon, 16 Dec 2013 16:28:18 +0000 (17:28 +0100)
src/core/loopback-setup.c
src/libsystemd-rtnl/rtnl-message.c
src/libsystemd-rtnl/rtnl-util.c
src/libsystemd-rtnl/test-rtnl.c
src/network/networkd-address.c
src/network/networkd-bridge.c
src/network/networkd-route.c
src/systemd/sd-rtnl.h

index 7bb20ec..1999959 100644 (file)
@@ -47,7 +47,7 @@ static int pipe_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
         return r == -EEXIST ? 0 : r;
 }
 
-static int add_adresses(sd_rtnl *rtnl, int if_loopback, uint32_t ipv4_address, int *counter) {
+static int add_addresses(sd_rtnl *rtnl, int if_loopback, struct in_addr *ipv4_address, int *counter) {
         _cleanup_sd_rtnl_message_unref_ sd_rtnl_message *ipv4 = NULL, *ipv6 = NULL;
         int r;
 
@@ -55,7 +55,7 @@ static int add_adresses(sd_rtnl *rtnl, int if_loopback, uint32_t ipv4_address, i
         if (r < 0)
                 return r;
 
-        r = sd_rtnl_message_append(ipv4, IFA_LOCAL, &ipv4_address);
+        r = sd_rtnl_message_append_in_addr(ipv4, IFA_LOCAL, ipv4_address);
         if (r < 0)
                 return r;
 
@@ -72,7 +72,7 @@ static int add_adresses(sd_rtnl *rtnl, int if_loopback, uint32_t ipv4_address, i
         if (r < 0)
                 return r;
 
-        r = sd_rtnl_message_append(ipv6, IFA_LOCAL, &in6addr_loopback);
+        r = sd_rtnl_message_append_in6_addr(ipv6, IFA_LOCAL, &in6addr_loopback);
         if (r < 0)
                 return r;
 
@@ -85,7 +85,7 @@ static int add_adresses(sd_rtnl *rtnl, int if_loopback, uint32_t ipv4_address, i
         return 0;
 }
 
-static int start_interface(sd_rtnl *rtnl, int if_loopback, uint32_t ipv4_address, int *counter) {
+static int start_interface(sd_rtnl *rtnl, int if_loopback, struct in_addr *ipv4_address, int *counter) {
         _cleanup_sd_rtnl_message_unref_ sd_rtnl_message *req = NULL;
         int r;
 
@@ -97,7 +97,7 @@ static int start_interface(sd_rtnl *rtnl, int if_loopback, uint32_t ipv4_address
         if (r < 0)
                 return r;
 
-        r = sd_rtnl_message_append(req, IFA_LOCAL, &ipv4_address);
+        r = sd_rtnl_message_append_in_addr(req, IFA_LOCAL, ipv4_address);
         if (r < 0)
                 return r;
 
@@ -140,22 +140,24 @@ int loopback_setup(void) {
         _cleanup_sd_rtnl_unref_ sd_rtnl *rtnl = NULL;
         int r, if_loopback, counter = 0;
         bool eperm = false;
-        uint32_t ipv4_address = htonl(INADDR_LOOPBACK);
+        struct in_addr ipv4_address;
 
         errno = 0;
         if_loopback = (int) if_nametoindex("lo");
         if (if_loopback <= 0)
                 return errno ? -errno : -ENODEV;
 
+        ipv4_address.s_addr = htonl(INADDR_LOOPBACK);
+
         r = sd_rtnl_open(0, &rtnl);
         if (r < 0)
                 return r;
 
-        r = add_adresses(rtnl, if_loopback, ipv4_address, &counter);
+        r = add_addresses(rtnl, if_loopback, &ipv4_address, &counter);
         if (r < 0)
                 return r;
 
-        r = start_interface(rtnl, if_loopback, ipv4_address, &counter);
+        r = start_interface(rtnl, if_loopback, &ipv4_address, &counter);
         if (r < 0)
                 return r;
 
index 8940d21..264cca0 100644 (file)
@@ -356,109 +356,256 @@ static int add_rtattr(sd_rtnl_message *m, unsigned short type, const void *data,
         return 0;
 }
 
-int sd_rtnl_message_append(sd_rtnl_message *m, unsigned short type, const void *data) {
+int sd_rtnl_message_append_string(sd_rtnl_message *m, unsigned short type, const char *data) {
         uint16_t rtm_type;
-        struct ifaddrmsg *ifa;
-        struct rtmsg *rtm;
+        int r;
 
         assert_return(m, -EINVAL);
         assert_return(data, -EINVAL);
 
-        sd_rtnl_message_get_type(m, &rtm_type);
+        r = sd_rtnl_message_get_type(m, &rtm_type);
+        if (r < 0)
+                return r;
 
-        if (m->current_container) {
-                switch (rtm_type) {
-                        case RTM_NEWLINK:
-                        case RTM_SETLINK:
-                        case RTM_GETLINK:
-                        case RTM_DELLINK:
-                                switch (m->current_container->rta_type) {
-                                        case IFLA_LINKINFO:
-                                                switch (type) {
-                                                        case IFLA_INFO_KIND:
-                                                                return add_rtattr(m, type, data, strlen(data) + 1);
-                                                        default:
-                                                                return -ENOTSUP;
-                                                }
+        /* check that the type is correct */
+        switch (rtm_type) {
+                case RTM_NEWLINK:
+                case RTM_SETLINK:
+                case RTM_GETLINK:
+                case RTM_DELLINK:
+                        if (m->current_container) {
+                                if (m->current_container->rta_type != IFLA_LINKINFO ||
+                                    type != IFLA_INFO_KIND)
+                                        return -ENOTSUP;
+                        } else {
+                                switch (type) {
+                                        case IFLA_IFNAME:
+                                        case IFLA_IFALIAS:
+                                        case IFLA_QDISC:
+                                                break;
                                         default:
                                                 return -ENOTSUP;
                                 }
-                        default:
+                        }
+                        break;
+                case RTM_NEWADDR:
+                case RTM_GETADDR:
+                case RTM_DELADDR:
+                        if (type != IFA_LABEL)
                                 return -ENOTSUP;
-                }
+                        break;
+                default:
+                        return -ENOTSUP;
         }
 
+        r = add_rtattr(m, type, data, strlen(data) + 1);
+        if (r < 0)
+                return r;
+
+        return 0;
+}
+
+int sd_rtnl_message_append_u32(sd_rtnl_message *m, unsigned short type, uint32_t data) {
+        uint16_t rtm_type;
+        int r;
+
+        assert_return(m, -EINVAL);
+
+        r = sd_rtnl_message_get_type(m, &rtm_type);
+        if (r < 0)
+                return r;
+
+        /* check that the type is correct */
         switch (rtm_type) {
                 case RTM_NEWLINK:
                 case RTM_SETLINK:
-                case RTM_DELLINK:
                 case RTM_GETLINK:
+                case RTM_DELLINK:
                         switch (type) {
-                                case IFLA_IFNAME:
-                                case IFLA_IFALIAS:
-                                case IFLA_QDISC:
-                                        return add_rtattr(m, type, data, strlen(data) + 1);
                                 case IFLA_MASTER:
                                 case IFLA_MTU:
                                 case IFLA_LINK:
-                                        return add_rtattr(m, type, data, sizeof(uint32_t));
-                                case IFLA_STATS:
-                                        return add_rtattr(m, type, data, sizeof(struct rtnl_link_stats));
-                                case IFLA_ADDRESS:
-                                case IFLA_BROADCAST:
-                                        return add_rtattr(m, type, data, ETH_ALEN);
+                                        break;
                                 default:
                                         return -ENOTSUP;
                         }
+                        break;
+                case RTM_NEWROUTE:
+                case RTM_GETROUTE:
+                case RTM_DELROUTE:
+                        switch (type) {
+                                case RTA_TABLE:
+                                case RTA_PRIORITY:
+                                case RTA_IIF:
+                                case RTA_OIF:
+                                        break;
+                                default:
+                                        return -ENOTSUP;
+                        }
+                        break;
+                default:
+                        return -ENOTSUP;
+        }
+
+        r = add_rtattr(m, type, &data, sizeof(&data));
+        if (r < 0)
+                return r;
+
+        return 0;
+}
+
+int sd_rtnl_message_append_in_addr(sd_rtnl_message *m, unsigned short type, const struct in_addr *data) {
+        struct ifaddrmsg *ifa;
+        struct rtmsg *rtm;
+        uint16_t rtm_type;
+        int r;
+
+        assert_return(m, -EINVAL);
+        assert_return(data, -EINVAL);
+
+        r = sd_rtnl_message_get_type(m, &rtm_type);
+        if (r < 0)
+                return r;
+
+        /* check that the type is correct */
+        switch (rtm_type) {
                 case RTM_NEWADDR:
-                case RTM_DELADDR:
                 case RTM_GETADDR:
+                case RTM_DELADDR:
                         switch (type) {
-                                case IFA_LABEL:
-                                        return add_rtattr(m, type, data, strlen(data) + 1);
                                 case IFA_ADDRESS:
                                 case IFA_LOCAL:
                                 case IFA_BROADCAST:
                                 case IFA_ANYCAST:
                                         ifa = NLMSG_DATA(m->hdr);
-                                        switch (ifa->ifa_family) {
-                                                case AF_INET:
-                                                        return add_rtattr(m, type, data, sizeof(struct in_addr));
-                                                case AF_INET6:
-                                                        return add_rtattr(m, type, data, sizeof(struct in6_addr));
-                                                default:
-                                                        return -EINVAL;
-                                        }
+
+                                        if (ifa->ifa_family != AF_INET)
+                                                return -EINVAL;
+
+                                        break;
                                 default:
                                         return -ENOTSUP;
                         }
+                        break;
                 case RTM_NEWROUTE:
+                case RTM_GETROUTE:
                 case RTM_DELROUTE:
+                        switch (type) {
+                                case RTA_DST:
+                                case RTA_SRC:
+                                case RTA_GATEWAY:
+                                        rtm = NLMSG_DATA(m->hdr);
+
+                                        if (rtm->rtm_family != AF_INET)
+                                                return -EINVAL;
+
+                                        break;
+                                default:
+                                        return -ENOTSUP;
+                        }
+                        break;
+                default:
+                        return -ENOTSUP;
+        }
+
+        r = add_rtattr(m, type, data, sizeof(data));
+        if (r < 0)
+                return r;
+
+        return 0;
+}
+
+int sd_rtnl_message_append_in6_addr(sd_rtnl_message *m, unsigned short type, const struct in6_addr *data) {
+        struct ifaddrmsg *ifa;
+        struct rtmsg *rtm;
+        uint16_t rtm_type;
+        int r;
+
+        assert_return(m, -EINVAL);
+        assert_return(data, -EINVAL);
+
+        r = sd_rtnl_message_get_type(m, &rtm_type);
+        if (r < 0)
+                return r;
+
+        /* check that the type is correct */
+        switch (rtm_type) {
+                case RTM_NEWADDR:
+                case RTM_GETADDR:
+                case RTM_DELADDR:
+                        switch (type) {
+                                case IFA_ADDRESS:
+                                case IFA_LOCAL:
+                                case IFA_BROADCAST:
+                                case IFA_ANYCAST:
+                                        ifa = NLMSG_DATA(m->hdr);
+
+                                        if (ifa->ifa_family != AF_INET6)
+                                                return -EINVAL;
+
+                                        break;
+                                default:
+                                        return -ENOTSUP;
+                        }
+                        break;
+                case RTM_NEWROUTE:
                 case RTM_GETROUTE:
+                case RTM_DELROUTE:
                         switch (type) {
                                 case RTA_DST:
                                 case RTA_SRC:
                                 case RTA_GATEWAY:
                                         rtm = NLMSG_DATA(m->hdr);
-                                        switch (rtm->rtm_family) {
-                                                case AF_INET:
-                                                        return add_rtattr(m, type, data, sizeof(struct in_addr));
-                                                case AF_INET6:
-                                                        return add_rtattr(m, type, data, sizeof(struct in6_addr));
-                                                default:
-                                                        return -EINVAL;
-                                        }
-                                case RTA_TABLE:
-                                case RTA_PRIORITY:
-                                case RTA_IIF:
-                                case RTA_OIF:
-                                        return add_rtattr(m, type, data, sizeof(uint32_t));
+
+                                        if (rtm->rtm_family != AF_INET6)
+                                                return -EINVAL;
+
+                                        break;
                                 default:
                                         return -ENOTSUP;
                         }
                 default:
                         return -ENOTSUP;
         }
+
+        r = add_rtattr(m, type, data, sizeof(data));
+        if (r < 0)
+                return r;
+
+        return 0;
+}
+
+int sd_rtnl_message_append_ether_addr(sd_rtnl_message *m, unsigned short type, const struct ether_addr *data) {
+        uint16_t rtm_type;
+        int r;
+
+        assert_return(m, -EINVAL);
+        assert_return(data, -EINVAL);
+
+        sd_rtnl_message_get_type(m, &rtm_type);
+
+        switch (rtm_type) {
+                case RTM_NEWLINK:
+                case RTM_SETLINK:
+                case RTM_DELLINK:
+                case RTM_GETLINK:
+                        switch (type) {
+                                case IFLA_ADDRESS:
+                                case IFLA_BROADCAST:
+                                        break;
+                                default:
+                                        return -ENOTSUP;
+                        }
+                        break;
+                default:
+                        return -ENOTSUP;
+        }
+
+        r = add_rtattr(m, type, data, sizeof(data));
+        if (r < 0)
+                return r;
+
+        return 0;
 }
 
 int sd_rtnl_message_open_container(sd_rtnl_message *m, unsigned short type) {
index 264b72e..dfc0050 100644 (file)
@@ -38,7 +38,7 @@ int rtnl_set_link_name(sd_rtnl *rtnl, int ifindex, const char *name) {
         if (r < 0)
                 return r;
 
-        r = sd_rtnl_message_append(message, IFLA_IFNAME, name);
+        r = sd_rtnl_message_append_string(message, IFLA_IFNAME, name);
         if (r < 0)
                 return r;
 
@@ -66,7 +66,7 @@ int rtnl_set_link_properties(sd_rtnl *rtnl, int ifindex, const char *alias,
                 return r;
 
         if (alias) {
-                r = sd_rtnl_message_append(message, IFLA_IFALIAS, alias);
+                r = sd_rtnl_message_append_string(message, IFLA_IFALIAS, alias);
                 if (r < 0)
                         return r;
 
@@ -75,7 +75,7 @@ int rtnl_set_link_properties(sd_rtnl *rtnl, int ifindex, const char *alias,
         }
 
         if (mac) {
-                r = sd_rtnl_message_append(message, IFLA_ADDRESS, mac);
+                r = sd_rtnl_message_append_ether_addr(message, IFLA_ADDRESS, mac);
                 if (r < 0)
                         return r;
 
@@ -83,7 +83,7 @@ int rtnl_set_link_properties(sd_rtnl *rtnl, int ifindex, const char *alias,
         }
 
         if (mtu > 0) {
-                r = sd_rtnl_message_append(message, IFLA_MTU, &mtu);
+                r = sd_rtnl_message_append_u32(message, IFLA_MTU, mtu);
                 if (r < 0)
                         return r;
 
index d7a243a..58654e9 100644 (file)
@@ -38,9 +38,9 @@ static void test_link_configure(sd_rtnl *rtnl, int ifindex) {
 
         /* we'd really like to test NEWLINK, but let's not mess with the running kernel */
         assert(sd_rtnl_message_link_new(RTM_GETLINK, ifindex, &message) >= 0);
-        assert(sd_rtnl_message_append(message, IFLA_IFNAME, name) >= 0);
-        assert(sd_rtnl_message_append(message, IFLA_ADDRESS, ether_aton(mac)) >= 0);
-        assert(sd_rtnl_message_append(message, IFLA_MTU, &mtu) >= 0);
+        assert(sd_rtnl_message_append_string(message, IFLA_IFNAME, name) >= 0);
+        assert(sd_rtnl_message_append_ether_addr(message, IFLA_ADDRESS, ether_aton(mac)) >= 0);
+        assert(sd_rtnl_message_append_u32(message, IFLA_MTU, mtu) >= 0);
 
         assert(sd_rtnl_message_read(message, &type, &data) > 0);
         assert(type == IFLA_IFNAME);
@@ -59,7 +59,7 @@ static void test_link_configure(sd_rtnl *rtnl, int ifindex) {
 
 static void test_route(void) {
         _cleanup_sd_rtnl_message_unref_ sd_rtnl_message *req;
-        uint32_t addr = htonl(INADDR_LOOPBACK);
+        struct in_addr addr;
         uint32_t index = 2;
         uint16_t type;
         void *data;
@@ -71,13 +71,15 @@ static void test_route(void) {
                 return;
         }
 
-        r = sd_rtnl_message_append(req, RTA_GATEWAY, &addr);
+        addr.s_addr = htonl(INADDR_LOOPBACK);
+
+        r = sd_rtnl_message_append_in_addr(req, RTA_GATEWAY, &addr);
         if (r < 0) {
                 log_error("Could not append RTA_GATEWAY attribute: %s", strerror(-r));
                 return;
         }
 
-        r = sd_rtnl_message_append(req, RTA_OIF, &index);
+        r = sd_rtnl_message_append_u32(req, RTA_OIF, index);
         if (r < 0) {
                 log_error("Could not append RTA_OIF attribute: %s", strerror(-r));
                 return;
@@ -85,7 +87,7 @@ static void test_route(void) {
 
         assert(sd_rtnl_message_read(req, &type, &data) > 0);
         assert(type == RTA_GATEWAY);
-        assert(*(uint32_t *) data == addr);
+        assert(((struct in_addr *)data)->s_addr == addr.s_addr);
 
         assert(sd_rtnl_message_read(req, &type, &data) > 0);
         assert(type == RTA_OIF);
@@ -213,7 +215,7 @@ static void test_container(void) {
 
         assert(sd_rtnl_message_open_container(m, IFLA_LINKINFO) >= 0);
         assert(sd_rtnl_message_open_container(m, IFLA_LINKINFO) == -EINVAL);
-        assert(sd_rtnl_message_append(m, IFLA_INFO_KIND, "kind") >= 0);
+        assert(sd_rtnl_message_append_string(m, IFLA_INFO_KIND, "kind") >= 0);
         assert(sd_rtnl_message_close_container(m) >= 0);
         assert(sd_rtnl_message_close_container(m) == -EINVAL);
 
@@ -295,7 +297,7 @@ int main(void) {
         assert(sd_rtnl_message_link_new(RTM_GETLINK, if_loopback, &m) >= 0);
         assert(m);
 
-        assert(sd_rtnl_message_append(m, IFLA_MTU, &mtu) >= 0);
+        assert(sd_rtnl_message_append_u32(m, IFLA_MTU, mtu) >= 0);
         assert(sd_rtnl_message_read(m, &type, (void **) &mtu_reply) == 1);
 
         assert(type == IFLA_MTU);
index 8f16a8c..63ba33e 100644 (file)
@@ -95,7 +95,10 @@ int address_configure(Address *address, Link *link,
                 return r;
         }
 
-        r = sd_rtnl_message_append(req, IFA_LOCAL, &address->in_addr);
+        if (address->family == AF_INET)
+                r = sd_rtnl_message_append_in_addr(req, IFA_LOCAL, &address->in_addr.in);
+        else if (address->family == AF_INET6)
+                r = sd_rtnl_message_append_in6_addr(req, IFA_LOCAL, &address->in_addr.in6);
         if (r < 0) {
                 log_error("Could not append IFA_LOCAL attribute: %s",
                           strerror(-r));
@@ -107,7 +110,7 @@ int address_configure(Address *address, Link *link,
 
                 broadcast.s_addr = address->in_addr.in.s_addr | address->netmask.s_addr;
 
-                r = sd_rtnl_message_append(req, IFA_BROADCAST, &broadcast);
+                r = sd_rtnl_message_append_in_addr(req, IFA_BROADCAST, &broadcast);
                 if (r < 0) {
                         log_error("Could not append IFA_BROADCAST attribute: %s",
                                   strerror(-r));
@@ -116,7 +119,7 @@ int address_configure(Address *address, Link *link,
         }
 
         if (address->label) {
-                r = sd_rtnl_message_append(req, IFA_LABEL, address->label);
+                r = sd_rtnl_message_append_string(req, IFA_LABEL, address->label);
                 if (r < 0) {
                         log_error("Could not append IFA_LABEL attribute: %s",
                                   strerror(-r));
index b764b7d..2c54146 100644 (file)
@@ -91,7 +91,7 @@ static int bridge_join_ready(Bridge *bridge, Link* link, sd_rtnl_message_handler
                 return r;
         }
 
-        r = sd_rtnl_message_append(req, IFLA_MASTER, &bridge->link->ifindex);
+        r = sd_rtnl_message_append_u32(req, IFLA_MASTER, bridge->link->ifindex);
         if (r < 0) {
                 log_error("Could not append IFLA_MASTER attribute: %s",
                           strerror(-r));
@@ -162,7 +162,7 @@ static int bridge_create(Bridge *bridge) {
                 return r;
         }
 
-        r = sd_rtnl_message_append(req, IFLA_IFNAME, bridge->name);
+        r = sd_rtnl_message_append_string(req, IFLA_IFNAME, bridge->name);
         if (r < 0) {
                 log_error("Could not append IFLA_IFNAME attribute: %s",
                           strerror(-r));
@@ -176,7 +176,7 @@ static int bridge_create(Bridge *bridge) {
                 return r;
         }
 
-        r = sd_rtnl_message_append(req, IFLA_INFO_KIND, "bridge");
+        r = sd_rtnl_message_append_string(req, IFLA_INFO_KIND, "bridge");
         if (r < 0) {
                 log_error("Could not append IFLA_INFO_KIND attribute: %s",
                           strerror(-r));
index f8580e9..22604b3 100644 (file)
@@ -92,16 +92,24 @@ int route_configure(Route *route, Link *link,
                 return r;
         }
 
-        r = sd_rtnl_message_append(req, RTA_GATEWAY, &route->in_addr);
+        if (route->family == AF_INET)
+                r = sd_rtnl_message_append_in_addr(req, RTA_GATEWAY, &route->in_addr.in);
+        else if (route->family == AF_INET6)
+                r = sd_rtnl_message_append_in6_addr(req, RTA_GATEWAY, &route->in_addr.in6);
         if (r < 0) {
                 log_error("Could not append RTA_GATEWAY attribute: %s", strerror(-r));
                 return r;
         }
 
-        r = sd_rtnl_message_append(req, RTA_DST, &route->dst_addr);
-        if (r < 0) {
-                log_error("Could not append RTA_DST attribute: %s", strerror(-r));
-                return r;
+        if (route->dst_prefixlen) {
+                if (route->family == AF_INET)
+                        r = sd_rtnl_message_append_in_addr(req, RTA_DST, &route->dst_addr.in);
+                else if (route->family == AF_INET6)
+                        r = sd_rtnl_message_append_in6_addr(req, RTA_DST, &route->dst_addr.in6);
+                if (r < 0) {
+                        log_error("Could not append RTA_DST attribute: %s", strerror(-r));
+                        return r;
+                }
         }
 
         r = sd_rtnl_message_route_set_dst_prefixlen(req, route->dst_prefixlen);
@@ -110,7 +118,7 @@ int route_configure(Route *route, Link *link,
                 return r;
         }
 
-        r = sd_rtnl_message_append(req, RTA_OIF, &link->ifindex);
+        r = sd_rtnl_message_append_u32(req, RTA_OIF, link->ifindex);
         if (r < 0) {
                 log_error("Could not append RTA_OIF attribute: %s", strerror(-r));
                 return r;
index fcd09a0..7d626b8 100644 (file)
@@ -23,6 +23,8 @@
 ***/
 
 #include <inttypes.h>
+#include <netinet/in.h>
+#include <netinet/ether.h>
 
 #include "sd-event.h"
 #include "_sd-common.h"
@@ -89,7 +91,12 @@ int sd_rtnl_message_link_get_flags(sd_rtnl_message *m, unsigned *flags);
 
 int sd_rtnl_message_route_set_dst_prefixlen(sd_rtnl_message *m, unsigned char prefixlen);
 
-int sd_rtnl_message_append(sd_rtnl_message *m, unsigned short type, const void *data);
+int sd_rtnl_message_append_string(sd_rtnl_message *m, unsigned short type, const char *data);
+int sd_rtnl_message_append_u32(sd_rtnl_message *m, unsigned short type, uint32_t data);
+int sd_rtnl_message_append_in_addr(sd_rtnl_message *m, unsigned short type, const struct in_addr *data);
+int sd_rtnl_message_append_in6_addr(sd_rtnl_message *m, unsigned short type, const struct in6_addr *data);
+int sd_rtnl_message_append_ether_addr(sd_rtnl_message *m, unsigned short type, const struct ether_addr *data);
+
 int sd_rtnl_message_open_container(sd_rtnl_message *m, unsigned short type);
 int sd_rtnl_message_close_container(sd_rtnl_message *m);