LCOV - code coverage report
Current view: top level - libsystemd/sd-netlink - test-netlink.c (source / functions) Hit Total Coverage
Test: main_coverage.info Lines: 360 366 98.4 %
Date: 2019-08-22 15:41:25 Functions: 26 26 100.0 %

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

Generated by: LCOV version 1.14