LCOV - code coverage report
Current view: top level - libsystemd/sd-netlink - test-netlink.c (source / functions) Hit Total Coverage
Test: systemd_full.info Lines: 360 366 98.4 %
Date: 2019-08-23 13:36:53 Functions: 26 26 100.0 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 256 506 50.6 %

           Branch data     Line data    Source code
       1                 :            : /* SPDX-License-Identifier: LGPL-2.1+ */
       2                 :            : 
       3                 :            : #include <net/if.h>
       4                 :            : #include <netinet/ether.h>
       5                 :            : #include <linux/genetlink.h>
       6                 :            : 
       7                 :            : #include "sd-netlink.h"
       8                 :            : 
       9                 :            : #include "alloc-util.h"
      10                 :            : #include "ether-addr-util.h"
      11                 :            : #include "macro.h"
      12                 :            : #include "missing.h"
      13                 :            : #include "netlink-util.h"
      14                 :            : #include "socket-util.h"
      15                 :            : #include "stdio-util.h"
      16                 :            : #include "string-util.h"
      17                 :            : #include "util.h"
      18                 :            : 
      19                 :          4 : static void test_message_link_bridge(sd_netlink *rtnl) {
      20                 :          4 :         _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *message = NULL;
      21                 :            :         uint32_t cost;
      22                 :            : 
      23         [ -  + ]:          4 :         assert_se(sd_rtnl_message_new_link(rtnl, &message, RTM_NEWLINK, 1) >= 0);
      24         [ -  + ]:          4 :         assert_se(sd_rtnl_message_link_set_family(message, PF_BRIDGE) >= 0);
      25         [ -  + ]:          4 :         assert_se(sd_netlink_message_open_container(message, IFLA_PROTINFO) >= 0);
      26         [ -  + ]:          4 :         assert_se(sd_netlink_message_append_u32(message, IFLA_BRPORT_COST, 10) >= 0);
      27         [ -  + ]:          4 :         assert_se(sd_netlink_message_close_container(message) >= 0);
      28                 :            : 
      29         [ -  + ]:          4 :         assert_se(sd_netlink_message_rewind(message) >= 0);
      30                 :            : 
      31         [ -  + ]:          4 :         assert_se(sd_netlink_message_enter_container(message, IFLA_PROTINFO) >= 0);
      32         [ -  + ]:          4 :         assert_se(sd_netlink_message_read_u32(message, IFLA_BRPORT_COST, &cost) >= 0);
      33         [ -  + ]:          4 :         assert_se(cost == 10);
      34         [ -  + ]:          4 :         assert_se(sd_netlink_message_exit_container(message) >= 0);
      35                 :          4 : }
      36                 :            : 
      37                 :          4 : static void test_link_configure(sd_netlink *rtnl, int ifindex) {
      38                 :          4 :         _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *message = NULL;
      39                 :          4 :         const char *mac = "98:fe:94:3f:c6:18", *name = "test";
      40                 :            :         char buffer[ETHER_ADDR_TO_STRING_MAX];
      41                 :          4 :         uint32_t mtu = 1450, mtu_out;
      42                 :            :         const char *name_out;
      43                 :            :         struct ether_addr mac_out;
      44                 :            : 
      45                 :            :         /* we'd really like to test NEWLINK, but let's not mess with the running kernel */
      46         [ -  + ]:          4 :         assert_se(sd_rtnl_message_new_link(rtnl, &message, RTM_GETLINK, ifindex) >= 0);
      47         [ -  + ]:          4 :         assert_se(sd_netlink_message_append_string(message, IFLA_IFNAME, name) >= 0);
      48         [ -  + ]:          4 :         assert_se(sd_netlink_message_append_ether_addr(message, IFLA_ADDRESS, ether_aton(mac)) >= 0);
      49         [ -  + ]:          4 :         assert_se(sd_netlink_message_append_u32(message, IFLA_MTU, mtu) >= 0);
      50                 :            : 
      51         [ -  + ]:          4 :         assert_se(sd_netlink_call(rtnl, message, 0, NULL) == 1);
      52         [ -  + ]:          4 :         assert_se(sd_netlink_message_rewind(message) >= 0);
      53                 :            : 
      54         [ -  + ]:          4 :         assert_se(sd_netlink_message_read_string(message, IFLA_IFNAME, &name_out) >= 0);
      55         [ -  + ]:          4 :         assert_se(streq(name, name_out));
      56                 :            : 
      57         [ -  + ]:          4 :         assert_se(sd_netlink_message_read_ether_addr(message, IFLA_ADDRESS, &mac_out) >= 0);
      58         [ -  + ]:          4 :         assert_se(streq(mac, ether_addr_to_string(&mac_out, buffer)));
      59                 :            : 
      60         [ -  + ]:          4 :         assert_se(sd_netlink_message_read_u32(message, IFLA_MTU, &mtu_out) >= 0);
      61         [ -  + ]:          4 :         assert_se(mtu == mtu_out);
      62                 :          4 : }
      63                 :            : 
      64                 :          4 : static void test_link_get(sd_netlink *rtnl, int ifindex) {
      65                 :            :         sd_netlink_message *m;
      66                 :            :         sd_netlink_message *r;
      67                 :          4 :         uint32_t mtu = 1500;
      68                 :            :         const char *str_data;
      69                 :            :         uint8_t u8_data;
      70                 :            :         uint32_t u32_data;
      71                 :            :         struct ether_addr eth_data;
      72                 :            : 
      73         [ -  + ]:          4 :         assert_se(sd_rtnl_message_new_link(rtnl, &m, RTM_GETLINK, ifindex) >= 0);
      74         [ -  + ]:          4 :         assert_se(m);
      75                 :            : 
      76                 :            :         /* u8 test cases  */
      77         [ -  + ]:          4 :         assert_se(sd_netlink_message_append_u8(m, IFLA_CARRIER, 0) >= 0);
      78         [ -  + ]:          4 :         assert_se(sd_netlink_message_append_u8(m, IFLA_OPERSTATE, 0) >= 0);
      79         [ -  + ]:          4 :         assert_se(sd_netlink_message_append_u8(m, IFLA_LINKMODE, 0) >= 0);
      80                 :            : 
      81                 :            :         /* u32 test cases */
      82         [ -  + ]:          4 :         assert_se(sd_netlink_message_append_u32(m, IFLA_MTU, mtu) >= 0);
      83         [ -  + ]:          4 :         assert_se(sd_netlink_message_append_u32(m, IFLA_GROUP, 0) >= 0);
      84         [ -  + ]:          4 :         assert_se(sd_netlink_message_append_u32(m, IFLA_TXQLEN, 0) >= 0);
      85         [ -  + ]:          4 :         assert_se(sd_netlink_message_append_u32(m, IFLA_NUM_TX_QUEUES, 0) >= 0);
      86         [ -  + ]:          4 :         assert_se(sd_netlink_message_append_u32(m, IFLA_NUM_RX_QUEUES, 0) >= 0);
      87                 :            : 
      88         [ -  + ]:          4 :         assert_se(sd_netlink_call(rtnl, m, -1, &r) == 1);
      89                 :            : 
      90         [ -  + ]:          4 :         assert_se(sd_netlink_message_read_string(r, IFLA_IFNAME, &str_data) == 0);
      91                 :            : 
      92         [ -  + ]:          4 :         assert_se(sd_netlink_message_read_u8(r, IFLA_CARRIER, &u8_data) == 0);
      93         [ -  + ]:          4 :         assert_se(sd_netlink_message_read_u8(r, IFLA_OPERSTATE, &u8_data) == 0);
      94         [ -  + ]:          4 :         assert_se(sd_netlink_message_read_u8(r, IFLA_LINKMODE, &u8_data) == 0);
      95                 :            : 
      96         [ -  + ]:          4 :         assert_se(sd_netlink_message_read_u32(r, IFLA_MTU, &u32_data) == 0);
      97         [ -  + ]:          4 :         assert_se(sd_netlink_message_read_u32(r, IFLA_GROUP, &u32_data) == 0);
      98         [ -  + ]:          4 :         assert_se(sd_netlink_message_read_u32(r, IFLA_TXQLEN, &u32_data) == 0);
      99         [ -  + ]:          4 :         assert_se(sd_netlink_message_read_u32(r, IFLA_NUM_TX_QUEUES, &u32_data) == 0);
     100         [ -  + ]:          4 :         assert_se(sd_netlink_message_read_u32(r, IFLA_NUM_RX_QUEUES, &u32_data) == 0);
     101                 :            : 
     102         [ -  + ]:          4 :         assert_se(sd_netlink_message_read_ether_addr(r, IFLA_ADDRESS, &eth_data) == 0);
     103                 :            : 
     104         [ -  + ]:          4 :         assert_se((m = sd_netlink_message_unref(m)) == NULL);
     105         [ -  + ]:          4 :         assert_se((r = sd_netlink_message_unref(r)) == NULL);
     106                 :          4 : }
     107                 :            : 
     108                 :          4 : static void test_address_get(sd_netlink *rtnl, int ifindex) {
     109                 :            :         sd_netlink_message *m;
     110                 :            :         sd_netlink_message *r;
     111                 :            :         struct in_addr in_data;
     112                 :            :         struct ifa_cacheinfo cache;
     113                 :            :         const char *label;
     114                 :            : 
     115         [ -  + ]:          4 :         assert_se(sd_rtnl_message_new_addr(rtnl, &m, RTM_GETADDR, ifindex, AF_INET) >= 0);
     116         [ -  + ]:          4 :         assert_se(m);
     117                 :            : 
     118         [ -  + ]:          4 :         assert_se(sd_netlink_call(rtnl, m, -1, &r) == 1);
     119                 :            : 
     120         [ -  + ]:          4 :         assert_se(sd_netlink_message_read_in_addr(r, IFA_LOCAL, &in_data) == 0);
     121         [ -  + ]:          4 :         assert_se(sd_netlink_message_read_in_addr(r, IFA_ADDRESS, &in_data) == 0);
     122         [ -  + ]:          4 :         assert_se(sd_netlink_message_read_string(r, IFA_LABEL, &label) == 0);
     123         [ -  + ]:          4 :         assert_se(sd_netlink_message_read_cache_info(r, IFA_CACHEINFO, &cache) == 0);
     124                 :            : 
     125         [ -  + ]:          4 :         assert_se((m = sd_netlink_message_unref(m)) == NULL);
     126         [ -  + ]:          4 :         assert_se((r = sd_netlink_message_unref(r)) == NULL);
     127                 :            : 
     128                 :          4 : }
     129                 :            : 
     130                 :          4 : static void test_route(sd_netlink *rtnl) {
     131         [ +  - ]:          4 :         _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req;
     132                 :            :         struct in_addr addr, addr_data;
     133                 :          4 :         uint32_t index = 2, u32_data;
     134                 :            :         int r;
     135                 :            : 
     136                 :          4 :         r = sd_rtnl_message_new_route(rtnl, &req, RTM_NEWROUTE, AF_INET, RTPROT_STATIC);
     137         [ -  + ]:          4 :         if (r < 0) {
     138         [ #  # ]:          0 :                 log_error_errno(r, "Could not create RTM_NEWROUTE message: %m");
     139                 :          0 :                 return;
     140                 :            :         }
     141                 :            : 
     142                 :          4 :         addr.s_addr = htonl(INADDR_LOOPBACK);
     143                 :            : 
     144                 :          4 :         r = sd_netlink_message_append_in_addr(req, RTA_GATEWAY, &addr);
     145         [ -  + ]:          4 :         if (r < 0) {
     146         [ #  # ]:          0 :                 log_error_errno(r, "Could not append RTA_GATEWAY attribute: %m");
     147                 :          0 :                 return;
     148                 :            :         }
     149                 :            : 
     150                 :          4 :         r = sd_netlink_message_append_u32(req, RTA_OIF, index);
     151         [ -  + ]:          4 :         if (r < 0) {
     152         [ #  # ]:          0 :                 log_error_errno(r, "Could not append RTA_OIF attribute: %m");
     153                 :          0 :                 return;
     154                 :            :         }
     155                 :            : 
     156         [ -  + ]:          4 :         assert_se(sd_netlink_message_rewind(req) >= 0);
     157                 :            : 
     158         [ -  + ]:          4 :         assert_se(sd_netlink_message_read_in_addr(req, RTA_GATEWAY, &addr_data) >= 0);
     159         [ -  + ]:          4 :         assert_se(addr_data.s_addr == addr.s_addr);
     160                 :            : 
     161         [ -  + ]:          4 :         assert_se(sd_netlink_message_read_u32(req, RTA_OIF, &u32_data) >= 0);
     162         [ -  + ]:          4 :         assert_se(u32_data == index);
     163                 :            : 
     164         [ -  + ]:          4 :         assert_se((req = sd_netlink_message_unref(req)) == NULL);
     165                 :            : }
     166                 :            : 
     167                 :          4 : static void test_multiple(void) {
     168                 :            :         sd_netlink *rtnl1, *rtnl2;
     169                 :            : 
     170         [ -  + ]:          4 :         assert_se(sd_netlink_open(&rtnl1) >= 0);
     171         [ -  + ]:          4 :         assert_se(sd_netlink_open(&rtnl2) >= 0);
     172                 :            : 
     173                 :          4 :         rtnl1 = sd_netlink_unref(rtnl1);
     174                 :          4 :         rtnl2 = sd_netlink_unref(rtnl2);
     175                 :          4 : }
     176                 :            : 
     177                 :         12 : static int link_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userdata) {
     178                 :         12 :         char *ifname = userdata;
     179                 :            :         const char *data;
     180                 :            : 
     181         [ -  + ]:         12 :         assert_se(rtnl);
     182         [ -  + ]:         12 :         assert_se(m);
     183         [ -  + ]:         12 :         assert_se(userdata);
     184                 :            : 
     185         [ +  - ]:         12 :         log_info("%s: got link info about %s", __func__, ifname);
     186                 :         12 :         free(ifname);
     187                 :            : 
     188         [ -  + ]:         12 :         assert_se(sd_netlink_message_read_string(m, IFLA_IFNAME, &data) >= 0);
     189         [ -  + ]:         12 :         assert_se(streq(data, "lo"));
     190                 :            : 
     191                 :         12 :         return 1;
     192                 :            : }
     193                 :            : 
     194                 :          4 : static void test_event_loop(int ifindex) {
     195                 :          4 :         _cleanup_(sd_event_unrefp) sd_event *event = NULL;
     196                 :          4 :         _cleanup_(sd_netlink_unrefp) sd_netlink *rtnl = NULL;
     197                 :          4 :         _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL;
     198                 :            :         char *ifname;
     199                 :            : 
     200                 :          4 :         ifname = strdup("lo2");
     201         [ -  + ]:          4 :         assert_se(ifname);
     202                 :            : 
     203         [ -  + ]:          4 :         assert_se(sd_netlink_open(&rtnl) >= 0);
     204         [ -  + ]:          4 :         assert_se(sd_rtnl_message_new_link(rtnl, &m, RTM_GETLINK, ifindex) >= 0);
     205                 :            : 
     206         [ -  + ]:          4 :         assert_se(sd_netlink_call_async(rtnl, NULL, m, link_handler, NULL, ifname, 0, NULL) >= 0);
     207                 :            : 
     208         [ -  + ]:          4 :         assert_se(sd_event_default(&event) >= 0);
     209                 :            : 
     210         [ -  + ]:          4 :         assert_se(sd_netlink_attach_event(rtnl, event, 0) >= 0);
     211                 :            : 
     212         [ -  + ]:          4 :         assert_se(sd_event_run(event, 0) >= 0);
     213                 :            : 
     214         [ -  + ]:          4 :         assert_se(sd_netlink_detach_event(rtnl) >= 0);
     215                 :            : 
     216         [ -  + ]:          4 :         assert_se((rtnl = sd_netlink_unref(rtnl)) == NULL);
     217                 :          4 : }
     218                 :            : 
     219                 :          8 : static void test_async_destroy(void *userdata) {
     220                 :          8 : }
     221                 :            : 
     222                 :          4 : static void test_async(int ifindex) {
     223                 :          4 :         _cleanup_(sd_netlink_unrefp) sd_netlink *rtnl = NULL;
     224                 :          4 :         _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL, *r = NULL;
     225                 :          4 :         _cleanup_(sd_netlink_slot_unrefp) sd_netlink_slot *slot = NULL;
     226                 :            :         sd_netlink_destroy_t destroy_callback;
     227                 :            :         const char *description;
     228                 :            :         char *ifname;
     229                 :            : 
     230                 :          4 :         ifname = strdup("lo");
     231         [ -  + ]:          4 :         assert_se(ifname);
     232                 :            : 
     233         [ -  + ]:          4 :         assert_se(sd_netlink_open(&rtnl) >= 0);
     234                 :            : 
     235         [ -  + ]:          4 :         assert_se(sd_rtnl_message_new_link(rtnl, &m, RTM_GETLINK, ifindex) >= 0);
     236                 :            : 
     237         [ -  + ]:          4 :         assert_se(sd_netlink_call_async(rtnl, &slot, m, link_handler, test_async_destroy, ifname, 0, "hogehoge") >= 0);
     238                 :            : 
     239         [ -  + ]:          4 :         assert_se(sd_netlink_slot_get_netlink(slot) == rtnl);
     240         [ -  + ]:          4 :         assert_se(sd_netlink_slot_get_userdata(slot) == ifname);
     241         [ -  + ]:          4 :         assert_se(sd_netlink_slot_get_destroy_callback(slot, &destroy_callback) == 1);
     242         [ -  + ]:          4 :         assert_se(destroy_callback == test_async_destroy);
     243         [ -  + ]:          4 :         assert_se(sd_netlink_slot_get_floating(slot) == 0);
     244         [ -  + ]:          4 :         assert_se(sd_netlink_slot_get_description(slot, &description) == 1);
     245         [ -  + ]:          4 :         assert_se(streq(description, "hogehoge"));
     246                 :            : 
     247         [ -  + ]:          4 :         assert_se(sd_netlink_wait(rtnl, 0) >= 0);
     248         [ -  + ]:          4 :         assert_se(sd_netlink_process(rtnl, &r) >= 0);
     249                 :            : 
     250         [ -  + ]:          4 :         assert_se((rtnl = sd_netlink_unref(rtnl)) == NULL);
     251                 :          4 : }
     252                 :            : 
     253                 :          4 : static void test_slot_set(int ifindex) {
     254                 :          4 :         _cleanup_(sd_netlink_unrefp) sd_netlink *rtnl = NULL;
     255                 :          4 :         _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL, *r = NULL;
     256                 :          4 :         _cleanup_(sd_netlink_slot_unrefp) sd_netlink_slot *slot = NULL;
     257                 :            :         sd_netlink_destroy_t destroy_callback;
     258                 :            :         const char *description;
     259                 :            :         char *ifname;
     260                 :            : 
     261                 :          4 :         ifname = strdup("lo");
     262         [ -  + ]:          4 :         assert_se(ifname);
     263                 :            : 
     264         [ -  + ]:          4 :         assert_se(sd_netlink_open(&rtnl) >= 0);
     265                 :            : 
     266         [ -  + ]:          4 :         assert_se(sd_rtnl_message_new_link(rtnl, &m, RTM_GETLINK, ifindex) >= 0);
     267                 :            : 
     268         [ -  + ]:          4 :         assert_se(sd_netlink_call_async(rtnl, &slot, m, link_handler, NULL, NULL, 0, NULL) >= 0);
     269                 :            : 
     270         [ -  + ]:          4 :         assert_se(sd_netlink_slot_get_netlink(slot) == rtnl);
     271         [ -  + ]:          4 :         assert_se(!sd_netlink_slot_get_userdata(slot));
     272         [ -  + ]:          4 :         assert_se(!sd_netlink_slot_set_userdata(slot, ifname));
     273         [ -  + ]:          4 :         assert_se(sd_netlink_slot_get_userdata(slot) == ifname);
     274         [ -  + ]:          4 :         assert_se(sd_netlink_slot_get_destroy_callback(slot, NULL) == 0);
     275         [ -  + ]:          4 :         assert_se(sd_netlink_slot_set_destroy_callback(slot, test_async_destroy) >= 0);
     276         [ -  + ]:          4 :         assert_se(sd_netlink_slot_get_destroy_callback(slot, &destroy_callback) == 1);
     277         [ -  + ]:          4 :         assert_se(destroy_callback == test_async_destroy);
     278         [ -  + ]:          4 :         assert_se(sd_netlink_slot_get_floating(slot) == 0);
     279         [ -  + ]:          4 :         assert_se(sd_netlink_slot_set_floating(slot, 1) == 1);
     280         [ -  + ]:          4 :         assert_se(sd_netlink_slot_get_floating(slot) == 1);
     281         [ -  + ]:          4 :         assert_se(sd_netlink_slot_get_description(slot, NULL) == 0);
     282         [ -  + ]:          4 :         assert_se(sd_netlink_slot_set_description(slot, "hogehoge") >= 0);
     283         [ -  + ]:          4 :         assert_se(sd_netlink_slot_get_description(slot, &description) == 1);
     284         [ -  + ]:          4 :         assert_se(streq(description, "hogehoge"));
     285                 :            : 
     286         [ -  + ]:          4 :         assert_se(sd_netlink_wait(rtnl, 0) >= 0);
     287         [ -  + ]:          4 :         assert_se(sd_netlink_process(rtnl, &r) >= 0);
     288                 :            : 
     289         [ -  + ]:          4 :         assert_se((rtnl = sd_netlink_unref(rtnl)) == NULL);
     290                 :          4 : }
     291                 :            : 
     292                 :            : struct test_async_object {
     293                 :            :         unsigned n_ref;
     294                 :            :         char *ifname;
     295                 :            : };
     296                 :            : 
     297                 :          4 : static struct test_async_object *test_async_object_free(struct test_async_object *t) {
     298         [ -  + ]:          4 :         assert(t);
     299                 :            : 
     300                 :          4 :         free(t->ifname);
     301                 :          4 :         return mfree(t);
     302                 :            : }
     303                 :            : 
     304   [ -  +  -  +  :         28 : DEFINE_PRIVATE_TRIVIAL_REF_UNREF_FUNC(struct test_async_object, test_async_object, test_async_object_free);
                   +  + ]
     305         [ +  - ]:          4 : DEFINE_TRIVIAL_CLEANUP_FUNC(struct test_async_object *, test_async_object_unref);
     306                 :            : 
     307                 :          4 : static int link_handler2(sd_netlink *rtnl, sd_netlink_message *m, void *userdata) {
     308                 :          4 :         struct test_async_object *t = userdata;
     309                 :            :         const char *data;
     310                 :            : 
     311         [ -  + ]:          4 :         assert_se(rtnl);
     312         [ -  + ]:          4 :         assert_se(m);
     313         [ -  + ]:          4 :         assert_se(userdata);
     314                 :            : 
     315         [ +  - ]:          4 :         log_info("%s: got link info about %s", __func__, t->ifname);
     316                 :            : 
     317         [ -  + ]:          4 :         assert_se(sd_netlink_message_read_string(m, IFLA_IFNAME, &data) >= 0);
     318         [ -  + ]:          4 :         assert_se(streq(data, "lo"));
     319                 :            : 
     320                 :          4 :         return 1;
     321                 :            : }
     322                 :            : 
     323                 :         12 : static void test_async_object_destroy(void *userdata) {
     324                 :         12 :         struct test_async_object *t = userdata;
     325                 :            : 
     326         [ -  + ]:         12 :         assert(userdata);
     327                 :            : 
     328         [ +  - ]:         12 :         log_info("%s: n_ref=%u", __func__, t->n_ref);
     329                 :         12 :         test_async_object_unref(t);
     330                 :         12 : }
     331                 :            : 
     332                 :          4 : static void test_async_destroy_callback(int ifindex) {
     333                 :          4 :         _cleanup_(sd_netlink_unrefp) sd_netlink *rtnl = NULL;
     334                 :          4 :         _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL, *r = NULL;
     335                 :          4 :         _cleanup_(test_async_object_unrefp) struct test_async_object *t = NULL;
     336                 :          4 :         _cleanup_(sd_netlink_slot_unrefp) sd_netlink_slot *slot = NULL;
     337                 :            :         char *ifname;
     338                 :            : 
     339         [ -  + ]:          4 :         assert_se(t = new(struct test_async_object, 1));
     340         [ -  + ]:          4 :         assert_se(ifname = strdup("lo"));
     341                 :          4 :         *t = (struct test_async_object) {
     342                 :            :                 .n_ref = 1,
     343                 :            :                 .ifname = ifname,
     344                 :            :         };
     345                 :            : 
     346         [ -  + ]:          4 :         assert_se(sd_netlink_open(&rtnl) >= 0);
     347                 :            : 
     348                 :            :         /* destroy callback is called after processing message */
     349         [ -  + ]:          4 :         assert_se(sd_rtnl_message_new_link(rtnl, &m, RTM_GETLINK, ifindex) >= 0);
     350         [ -  + ]:          4 :         assert_se(sd_netlink_call_async(rtnl, NULL, m, link_handler2, test_async_object_destroy, t, 0, NULL) >= 0);
     351                 :            : 
     352         [ -  + ]:          4 :         assert_se(t->n_ref == 1);
     353         [ -  + ]:          4 :         assert_se(test_async_object_ref(t));
     354         [ -  + ]:          4 :         assert_se(t->n_ref == 2);
     355                 :            : 
     356         [ -  + ]:          4 :         assert_se(sd_netlink_wait(rtnl, 0) >= 0);
     357         [ -  + ]:          4 :         assert_se(sd_netlink_process(rtnl, &r) == 1);
     358         [ -  + ]:          4 :         assert_se(t->n_ref == 1);
     359                 :            : 
     360         [ -  + ]:          4 :         assert_se(!sd_netlink_message_unref(m));
     361                 :            : 
     362                 :            :         /* destroy callback is called when asynchronous call is cancelled, that is, slot is freed. */
     363         [ -  + ]:          4 :         assert_se(sd_rtnl_message_new_link(rtnl, &m, RTM_GETLINK, ifindex) >= 0);
     364         [ -  + ]:          4 :         assert_se(sd_netlink_call_async(rtnl, &slot, m, link_handler2, test_async_object_destroy, t, 0, NULL) >= 0);
     365                 :            : 
     366         [ -  + ]:          4 :         assert_se(t->n_ref == 1);
     367         [ -  + ]:          4 :         assert_se(test_async_object_ref(t));
     368         [ -  + ]:          4 :         assert_se(t->n_ref == 2);
     369                 :            : 
     370         [ -  + ]:          4 :         assert_se(!(slot = sd_netlink_slot_unref(slot)));
     371         [ -  + ]:          4 :         assert_se(t->n_ref == 1);
     372                 :            : 
     373         [ -  + ]:          4 :         assert_se(!sd_netlink_message_unref(m));
     374                 :            : 
     375                 :            :         /* destroy callback is also called by sd_netlink_unref() */
     376         [ -  + ]:          4 :         assert_se(sd_rtnl_message_new_link(rtnl, &m, RTM_GETLINK, ifindex) >= 0);
     377         [ -  + ]:          4 :         assert_se(sd_netlink_call_async(rtnl, NULL, m, link_handler2, test_async_object_destroy, t, 0, NULL) >= 0);
     378                 :            : 
     379         [ -  + ]:          4 :         assert_se(t->n_ref == 1);
     380         [ -  + ]:          4 :         assert_se(test_async_object_ref(t));
     381         [ -  + ]:          4 :         assert_se(t->n_ref == 2);
     382                 :            : 
     383         [ -  + ]:          4 :         assert_se((rtnl = sd_netlink_unref(rtnl)) == NULL);
     384         [ -  + ]:          4 :         assert_se(t->n_ref == 1);
     385                 :          4 : }
     386                 :            : 
     387                 :          8 : static int pipe_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userdata) {
     388                 :          8 :         int *counter = userdata;
     389                 :            :         int r;
     390                 :            : 
     391                 :          8 :         (*counter)--;
     392                 :            : 
     393                 :          8 :         r = sd_netlink_message_get_errno(m);
     394                 :            : 
     395         [ +  - ]:          8 :         log_info_errno(r, "%d left in pipe. got reply: %m", *counter);
     396                 :            : 
     397         [ -  + ]:          8 :         assert_se(r >= 0);
     398                 :            : 
     399                 :          8 :         return 1;
     400                 :            : }
     401                 :            : 
     402                 :          4 : static void test_pipe(int ifindex) {
     403                 :          4 :         _cleanup_(sd_netlink_unrefp) sd_netlink *rtnl = NULL;
     404                 :          4 :         _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m1 = NULL, *m2 = NULL;
     405                 :          4 :         int counter = 0;
     406                 :            : 
     407         [ -  + ]:          4 :         assert_se(sd_netlink_open(&rtnl) >= 0);
     408                 :            : 
     409         [ -  + ]:          4 :         assert_se(sd_rtnl_message_new_link(rtnl, &m1, RTM_GETLINK, ifindex) >= 0);
     410         [ -  + ]:          4 :         assert_se(sd_rtnl_message_new_link(rtnl, &m2, RTM_GETLINK, ifindex) >= 0);
     411                 :            : 
     412                 :          4 :         counter++;
     413         [ -  + ]:          4 :         assert_se(sd_netlink_call_async(rtnl, NULL, m1, pipe_handler, NULL, &counter, 0, NULL) >= 0);
     414                 :            : 
     415                 :          4 :         counter++;
     416         [ -  + ]:          4 :         assert_se(sd_netlink_call_async(rtnl, NULL, m2, pipe_handler, NULL, &counter, 0, NULL) >= 0);
     417                 :            : 
     418         [ +  + ]:         16 :         while (counter > 0) {
     419         [ -  + ]:         12 :                 assert_se(sd_netlink_wait(rtnl, 0) >= 0);
     420         [ -  + ]:         12 :                 assert_se(sd_netlink_process(rtnl, NULL) >= 0);
     421                 :            :         }
     422                 :            : 
     423         [ -  + ]:          4 :         assert_se((rtnl = sd_netlink_unref(rtnl)) == NULL);
     424                 :          4 : }
     425                 :            : 
     426                 :          4 : static void test_container(sd_netlink *rtnl) {
     427                 :          4 :         _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL;
     428                 :            :         uint16_t u16_data;
     429                 :            :         uint32_t u32_data;
     430                 :            :         const char *string_data;
     431                 :            : 
     432         [ -  + ]:          4 :         assert_se(sd_rtnl_message_new_link(rtnl, &m, RTM_NEWLINK, 0) >= 0);
     433                 :            : 
     434         [ -  + ]:          4 :         assert_se(sd_netlink_message_open_container(m, IFLA_LINKINFO) >= 0);
     435         [ -  + ]:          4 :         assert_se(sd_netlink_message_open_container_union(m, IFLA_INFO_DATA, "vlan") >= 0);
     436         [ -  + ]:          4 :         assert_se(sd_netlink_message_append_u16(m, IFLA_VLAN_ID, 100) >= 0);
     437         [ -  + ]:          4 :         assert_se(sd_netlink_message_close_container(m) >= 0);
     438         [ -  + ]:          4 :         assert_se(sd_netlink_message_append_string(m, IFLA_INFO_KIND, "vlan") >= 0);
     439         [ -  + ]:          4 :         assert_se(sd_netlink_message_close_container(m) >= 0);
     440         [ -  + ]:          4 :         assert_se(sd_netlink_message_close_container(m) == -EINVAL);
     441                 :            : 
     442         [ -  + ]:          4 :         assert_se(sd_netlink_message_rewind(m) >= 0);
     443                 :            : 
     444         [ -  + ]:          4 :         assert_se(sd_netlink_message_enter_container(m, IFLA_LINKINFO) >= 0);
     445         [ -  + ]:          4 :         assert_se(sd_netlink_message_read_string(m, IFLA_INFO_KIND, &string_data) >= 0);
     446         [ -  + ]:          4 :         assert_se(streq("vlan", string_data));
     447                 :            : 
     448         [ -  + ]:          4 :         assert_se(sd_netlink_message_enter_container(m, IFLA_INFO_DATA) >= 0);
     449         [ -  + ]:          4 :         assert_se(sd_netlink_message_read_u16(m, IFLA_VLAN_ID, &u16_data) >= 0);
     450         [ -  + ]:          4 :         assert_se(sd_netlink_message_exit_container(m) >= 0);
     451                 :            : 
     452         [ -  + ]:          4 :         assert_se(sd_netlink_message_read_string(m, IFLA_INFO_KIND, &string_data) >= 0);
     453         [ -  + ]:          4 :         assert_se(streq("vlan", string_data));
     454         [ -  + ]:          4 :         assert_se(sd_netlink_message_exit_container(m) >= 0);
     455                 :            : 
     456         [ -  + ]:          4 :         assert_se(sd_netlink_message_read_u32(m, IFLA_LINKINFO, &u32_data) < 0);
     457                 :            : 
     458         [ -  + ]:          4 :         assert_se(sd_netlink_message_exit_container(m) == -EINVAL);
     459                 :          4 : }
     460                 :            : 
     461                 :          4 : static void test_match(void) {
     462                 :          4 :         _cleanup_(sd_netlink_slot_unrefp) sd_netlink_slot *s1 = NULL, *s2 = NULL;
     463                 :          4 :         _cleanup_(sd_netlink_unrefp) sd_netlink *rtnl = NULL;
     464                 :            : 
     465         [ -  + ]:          4 :         assert_se(sd_netlink_open(&rtnl) >= 0);
     466                 :            : 
     467         [ -  + ]:          4 :         assert_se(sd_netlink_add_match(rtnl, &s1, RTM_NEWLINK, link_handler, NULL, NULL, NULL) >= 0);
     468         [ -  + ]:          4 :         assert_se(sd_netlink_add_match(rtnl, &s2, RTM_NEWLINK, link_handler, NULL, NULL, NULL) >= 0);
     469         [ -  + ]:          4 :         assert_se(sd_netlink_add_match(rtnl, NULL, RTM_NEWLINK, link_handler, NULL, NULL, NULL) >= 0);
     470                 :            : 
     471         [ -  + ]:          4 :         assert_se(!(s1 = sd_netlink_slot_unref(s1)));
     472         [ -  + ]:          4 :         assert_se(!(s2 = sd_netlink_slot_unref(s2)));
     473                 :            : 
     474         [ -  + ]:          4 :         assert_se((rtnl = sd_netlink_unref(rtnl)) == NULL);
     475                 :          4 : }
     476                 :            : 
     477                 :          4 : static void test_get_addresses(sd_netlink *rtnl) {
     478                 :          4 :         _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL, *reply = NULL;
     479                 :            :         sd_netlink_message *m;
     480                 :            : 
     481         [ -  + ]:          4 :         assert_se(sd_rtnl_message_new_addr(rtnl, &req, RTM_GETADDR, 0, AF_UNSPEC) >= 0);
     482                 :            : 
     483         [ -  + ]:          4 :         assert_se(sd_netlink_call(rtnl, req, 0, &reply) >= 0);
     484                 :            : 
     485         [ +  + ]:         40 :         for (m = reply; m; m = sd_netlink_message_next(m)) {
     486                 :            :                 uint16_t type;
     487                 :            :                 unsigned char scope, flags;
     488                 :            :                 int family, ifindex;
     489                 :            : 
     490         [ -  + ]:         36 :                 assert_se(sd_netlink_message_get_type(m, &type) >= 0);
     491         [ -  + ]:         36 :                 assert_se(type == RTM_NEWADDR);
     492                 :            : 
     493         [ -  + ]:         36 :                 assert_se(sd_rtnl_message_addr_get_ifindex(m, &ifindex) >= 0);
     494         [ -  + ]:         36 :                 assert_se(sd_rtnl_message_addr_get_family(m, &family) >= 0);
     495         [ -  + ]:         36 :                 assert_se(sd_rtnl_message_addr_get_scope(m, &scope) >= 0);
     496         [ -  + ]:         36 :                 assert_se(sd_rtnl_message_addr_get_flags(m, &flags) >= 0);
     497                 :            : 
     498         [ -  + ]:         36 :                 assert_se(ifindex > 0);
     499   [ +  -  -  + ]:         36 :                 assert_se(IN_SET(family, AF_INET, AF_INET6));
     500                 :            : 
     501   [ +  -  +  + ]:         36 :                 log_info("got IPv%u address on ifindex %i", family == AF_INET ? 4: 6, ifindex);
     502                 :            :         }
     503                 :          4 : }
     504                 :            : 
     505                 :          4 : static void test_message(sd_netlink *rtnl) {
     506                 :          4 :         _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL;
     507                 :            : 
     508         [ -  + ]:          4 :         assert_se(rtnl_message_new_synthetic_error(rtnl, -ETIMEDOUT, 1, &m) >= 0);
     509         [ -  + ]:          4 :         assert_se(sd_netlink_message_get_errno(m) == -ETIMEDOUT);
     510                 :          4 : }
     511                 :            : 
     512                 :          4 : static void test_array(void) {
     513                 :          4 :         _cleanup_(sd_netlink_unrefp) sd_netlink *genl = NULL;
     514                 :          4 :         _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL;
     515                 :            : 
     516         [ -  + ]:          4 :         assert_se(sd_genl_socket_open(&genl) >= 0);
     517         [ -  + ]:          4 :         assert_se(sd_genl_message_new(genl, SD_GENL_ID_CTRL, CTRL_CMD_GETFAMILY, &m) >= 0);
     518                 :            : 
     519         [ -  + ]:          4 :         assert_se(sd_netlink_message_open_container(m, CTRL_ATTR_MCAST_GROUPS) >= 0);
     520         [ +  + ]:         44 :         for (unsigned i = 0; i < 10; i++) {
     521                 :            :                 char name[STRLEN("hoge") + DECIMAL_STR_MAX(uint32_t)];
     522                 :         40 :                 uint32_t id = i + 1000;
     523                 :            : 
     524         [ -  + ]:         40 :                 xsprintf(name, "hoge%" PRIu32, id);
     525         [ -  + ]:         40 :                 assert_se(sd_netlink_message_open_array(m, i + 1) >= 0);
     526         [ -  + ]:         40 :                 assert_se(sd_netlink_message_append_u32(m, CTRL_ATTR_MCAST_GRP_ID, id) >= 0);
     527         [ -  + ]:         40 :                 assert_se(sd_netlink_message_append_string(m, CTRL_ATTR_MCAST_GRP_NAME, name) >= 0);
     528         [ -  + ]:         40 :                 assert_se(sd_netlink_message_close_container(m) >= 0);
     529                 :            :         }
     530         [ -  + ]:          4 :         assert_se(sd_netlink_message_close_container(m) >= 0);
     531                 :            : 
     532                 :          4 :         rtnl_message_seal(m);
     533         [ -  + ]:          4 :         assert_se(sd_netlink_message_rewind(m) >= 0);
     534                 :            : 
     535         [ -  + ]:          4 :         assert_se(sd_netlink_message_enter_container(m, CTRL_ATTR_MCAST_GROUPS) >= 0);
     536         [ +  + ]:         44 :         for (unsigned i = 0; i < 10; i++) {
     537                 :            :                 char expected[STRLEN("hoge") + DECIMAL_STR_MAX(uint32_t)];
     538                 :            :                 const char *name;
     539                 :            :                 uint32_t id;
     540                 :            : 
     541         [ -  + ]:         40 :                 assert_se(sd_netlink_message_enter_array(m, i + 1) >= 0);
     542         [ -  + ]:         40 :                 assert_se(sd_netlink_message_read_u32(m, CTRL_ATTR_MCAST_GRP_ID, &id) >= 0);
     543         [ -  + ]:         40 :                 assert_se(sd_netlink_message_read_string(m, CTRL_ATTR_MCAST_GRP_NAME, &name) >= 0);
     544         [ -  + ]:         40 :                 assert_se(sd_netlink_message_exit_container(m) >= 0);
     545                 :            : 
     546         [ -  + ]:         40 :                 assert_se(id == i + 1000);
     547         [ -  + ]:         40 :                 xsprintf(expected, "hoge%" PRIu32, id);
     548         [ -  + ]:         40 :                 assert_se(streq(name, expected));
     549                 :            :         }
     550         [ -  + ]:          4 :         assert_se(sd_netlink_message_exit_container(m) >= 0);
     551                 :            : 
     552                 :          4 : }
     553                 :            : 
     554                 :          4 : int main(void) {
     555                 :            :         sd_netlink *rtnl;
     556                 :            :         sd_netlink_message *m;
     557                 :            :         sd_netlink_message *r;
     558                 :            :         const char *string_data;
     559                 :            :         int if_loopback;
     560                 :            :         uint16_t type;
     561                 :            : 
     562                 :          4 :         test_match();
     563                 :          4 :         test_multiple();
     564                 :            : 
     565         [ -  + ]:          4 :         assert_se(sd_netlink_open(&rtnl) >= 0);
     566         [ -  + ]:          4 :         assert_se(rtnl);
     567                 :            : 
     568                 :          4 :         test_route(rtnl);
     569                 :          4 :         test_message(rtnl);
     570                 :          4 :         test_container(rtnl);
     571                 :          4 :         test_array();
     572                 :            : 
     573                 :          4 :         if_loopback = (int) if_nametoindex("lo");
     574         [ -  + ]:          4 :         assert_se(if_loopback > 0);
     575                 :            : 
     576                 :          4 :         test_async(if_loopback);
     577                 :          4 :         test_slot_set(if_loopback);
     578                 :          4 :         test_async_destroy_callback(if_loopback);
     579                 :          4 :         test_pipe(if_loopback);
     580                 :          4 :         test_event_loop(if_loopback);
     581                 :          4 :         test_link_configure(rtnl, if_loopback);
     582                 :            : 
     583                 :          4 :         test_get_addresses(rtnl);
     584                 :          4 :         test_message_link_bridge(rtnl);
     585                 :            : 
     586         [ -  + ]:          4 :         assert_se(sd_rtnl_message_new_link(rtnl, &m, RTM_GETLINK, if_loopback) >= 0);
     587         [ -  + ]:          4 :         assert_se(m);
     588                 :            : 
     589         [ -  + ]:          4 :         assert_se(sd_netlink_message_get_type(m, &type) >= 0);
     590         [ -  + ]:          4 :         assert_se(type == RTM_GETLINK);
     591                 :            : 
     592         [ -  + ]:          4 :         assert_se(sd_netlink_message_read_string(m, IFLA_IFNAME, &string_data) == -EPERM);
     593                 :            : 
     594         [ -  + ]:          4 :         assert_se(sd_netlink_call(rtnl, m, 0, &r) == 1);
     595         [ -  + ]:          4 :         assert_se(sd_netlink_message_get_type(r, &type) >= 0);
     596         [ -  + ]:          4 :         assert_se(type == RTM_NEWLINK);
     597                 :            : 
     598         [ -  + ]:          4 :         assert_se((r = sd_netlink_message_unref(r)) == NULL);
     599                 :            : 
     600         [ -  + ]:          4 :         assert_se(sd_netlink_call(rtnl, m, -1, &r) == -EPERM);
     601         [ -  + ]:          4 :         assert_se((m = sd_netlink_message_unref(m)) == NULL);
     602         [ -  + ]:          4 :         assert_se((r = sd_netlink_message_unref(r)) == NULL);
     603                 :            : 
     604                 :          4 :         test_link_get(rtnl, if_loopback);
     605                 :          4 :         test_address_get(rtnl, if_loopback);
     606                 :            : 
     607         [ -  + ]:          4 :         assert_se((m = sd_netlink_message_unref(m)) == NULL);
     608         [ -  + ]:          4 :         assert_se((r = sd_netlink_message_unref(r)) == NULL);
     609         [ -  + ]:          4 :         assert_se((rtnl = sd_netlink_unref(rtnl)) == NULL);
     610                 :            : 
     611                 :          4 :         return EXIT_SUCCESS;
     612                 :            : }

Generated by: LCOV version 1.14