1f2c8381fSAlexander V. Chernikov #include <stdio.h> 2f2c8381fSAlexander V. Chernikov #include <string.h> 3f2c8381fSAlexander V. Chernikov #include <stdlib.h> 4f2c8381fSAlexander V. Chernikov 5f2c8381fSAlexander V. Chernikov #include <sys/param.h> 6f2c8381fSAlexander V. Chernikov #include <sys/module.h> 7f2c8381fSAlexander V. Chernikov 8f2c8381fSAlexander V. Chernikov #include <netlink/netlink.h> 9f2c8381fSAlexander V. Chernikov #include <netlink/netlink_route.h> 10f2c8381fSAlexander V. Chernikov #include "netlink/netlink_snl.h" 11f2c8381fSAlexander V. Chernikov #include "netlink/netlink_snl_route.h" 12595d23f7SAlexander V. Chernikov #include "netlink/netlink_snl_route_parsers.h" 13f2c8381fSAlexander V. Chernikov 14f2c8381fSAlexander V. Chernikov #include <atf-c.h> 15f2c8381fSAlexander V. Chernikov 16f2c8381fSAlexander V. Chernikov static void 17f2c8381fSAlexander V. Chernikov require_netlink(void) 18f2c8381fSAlexander V. Chernikov { 19f2c8381fSAlexander V. Chernikov if (modfind("netlink") == -1) 20f2c8381fSAlexander V. Chernikov atf_tc_skip("netlink module not loaded"); 21f2c8381fSAlexander V. Chernikov } 22f2c8381fSAlexander V. Chernikov 2373ae25c1SAlexander V. Chernikov ATF_TC(snl_verify_core_parsers); 2473ae25c1SAlexander V. Chernikov ATF_TC_HEAD(snl_verify_core_parsers, tc) 25595d23f7SAlexander V. Chernikov { 2673ae25c1SAlexander V. Chernikov atf_tc_set_md_var(tc, "descr", "Tests snl(3) core nlmsg parsers are correct"); 27595d23f7SAlexander V. Chernikov } 28595d23f7SAlexander V. Chernikov 2973ae25c1SAlexander V. Chernikov ATF_TC_BODY(snl_verify_core_parsers, tc) 3073ae25c1SAlexander V. Chernikov { 3173ae25c1SAlexander V. Chernikov SNL_VERIFY_PARSERS(snl_all_core_parsers); 3273ae25c1SAlexander V. Chernikov 3373ae25c1SAlexander V. Chernikov } 3473ae25c1SAlexander V. Chernikov 3573ae25c1SAlexander V. Chernikov ATF_TC(snl_verify_route_parsers); 3673ae25c1SAlexander V. Chernikov ATF_TC_HEAD(snl_verify_route_parsers, tc) 3773ae25c1SAlexander V. Chernikov { 3873ae25c1SAlexander V. Chernikov atf_tc_set_md_var(tc, "descr", "Tests snl(3) route parsers are correct"); 3973ae25c1SAlexander V. Chernikov } 4073ae25c1SAlexander V. Chernikov 4173ae25c1SAlexander V. Chernikov ATF_TC_BODY(snl_verify_route_parsers, tc) 42595d23f7SAlexander V. Chernikov { 43595d23f7SAlexander V. Chernikov SNL_VERIFY_PARSERS(snl_all_route_parsers); 44595d23f7SAlexander V. Chernikov 45595d23f7SAlexander V. Chernikov } 46f2c8381fSAlexander V. Chernikov 47*568a645bSAlexander V. Chernikov ATF_TC(snl_parse_errmsg_capped); 48*568a645bSAlexander V. Chernikov ATF_TC_HEAD(snl_parse_errmsg_capped, tc) 49*568a645bSAlexander V. Chernikov { 50*568a645bSAlexander V. Chernikov atf_tc_set_md_var(tc, "descr", "Tests snl(3) correctly parsing capped errors"); 51*568a645bSAlexander V. Chernikov } 52*568a645bSAlexander V. Chernikov 53*568a645bSAlexander V. Chernikov ATF_TC_BODY(snl_parse_errmsg_capped, tc) 54*568a645bSAlexander V. Chernikov { 55*568a645bSAlexander V. Chernikov struct snl_state ss; 56*568a645bSAlexander V. Chernikov struct snl_writer nw; 57*568a645bSAlexander V. Chernikov 58*568a645bSAlexander V. Chernikov require_netlink(); 59*568a645bSAlexander V. Chernikov 60*568a645bSAlexander V. Chernikov if (!snl_init(&ss, NETLINK_ROUTE)) 61*568a645bSAlexander V. Chernikov atf_tc_fail("snl_init() failed"); 62*568a645bSAlexander V. Chernikov 63*568a645bSAlexander V. Chernikov int optval = 1; 64*568a645bSAlexander V. Chernikov ATF_CHECK(setsockopt(ss.fd, SOL_NETLINK, NETLINK_CAP_ACK, &optval, sizeof(optval)) == 0); 65*568a645bSAlexander V. Chernikov 66*568a645bSAlexander V. Chernikov snl_init_writer(&ss, &nw); 67*568a645bSAlexander V. Chernikov 68*568a645bSAlexander V. Chernikov struct nlmsghdr *hdr = snl_create_msg_request(&nw, 255); 69*568a645bSAlexander V. Chernikov ATF_CHECK(hdr != NULL); 70*568a645bSAlexander V. Chernikov ATF_CHECK(snl_reserve_msg_object(&nw, struct ifinfomsg) != NULL); 71*568a645bSAlexander V. Chernikov snl_add_msg_attr_string(&nw, 143, "some random string"); 72*568a645bSAlexander V. Chernikov ATF_CHECK(snl_finalize_msg(&nw) != NULL); 73*568a645bSAlexander V. Chernikov 74*568a645bSAlexander V. Chernikov ATF_CHECK(snl_send_message(&ss, hdr)); 75*568a645bSAlexander V. Chernikov 76*568a645bSAlexander V. Chernikov struct nlmsghdr *rx_hdr = snl_read_reply(&ss, hdr->nlmsg_seq); 77*568a645bSAlexander V. Chernikov ATF_CHECK(rx_hdr != NULL); 78*568a645bSAlexander V. Chernikov ATF_CHECK(rx_hdr->nlmsg_type == NLMSG_ERROR); 79*568a645bSAlexander V. Chernikov 80*568a645bSAlexander V. Chernikov struct snl_errmsg_data e = {}; 81*568a645bSAlexander V. Chernikov ATF_CHECK(rx_hdr->nlmsg_len == sizeof(struct nlmsghdr) + sizeof(struct nlmsgerr)); 82*568a645bSAlexander V. Chernikov ATF_CHECK(snl_parse_errmsg(&ss, rx_hdr, &e)); 83*568a645bSAlexander V. Chernikov ATF_CHECK(e.error != 0); 84*568a645bSAlexander V. Chernikov ATF_CHECK(!memcmp(hdr, e.orig_hdr, sizeof(struct nlmsghdr))); 85*568a645bSAlexander V. Chernikov } 86*568a645bSAlexander V. Chernikov 87*568a645bSAlexander V. Chernikov ATF_TC(snl_parse_errmsg_capped_extack); 88*568a645bSAlexander V. Chernikov ATF_TC_HEAD(snl_parse_errmsg_capped_extack, tc) 89*568a645bSAlexander V. Chernikov { 90*568a645bSAlexander V. Chernikov atf_tc_set_md_var(tc, "descr", "Tests snl(3) correctly parsing capped errors with extack"); 91*568a645bSAlexander V. Chernikov } 92*568a645bSAlexander V. Chernikov 93*568a645bSAlexander V. Chernikov ATF_TC_BODY(snl_parse_errmsg_capped_extack, tc) 94*568a645bSAlexander V. Chernikov { 95*568a645bSAlexander V. Chernikov struct snl_state ss; 96*568a645bSAlexander V. Chernikov struct snl_writer nw; 97*568a645bSAlexander V. Chernikov 98*568a645bSAlexander V. Chernikov require_netlink(); 99*568a645bSAlexander V. Chernikov 100*568a645bSAlexander V. Chernikov if (!snl_init(&ss, NETLINK_ROUTE)) 101*568a645bSAlexander V. Chernikov atf_tc_fail("snl_init() failed"); 102*568a645bSAlexander V. Chernikov 103*568a645bSAlexander V. Chernikov int optval = 1; 104*568a645bSAlexander V. Chernikov ATF_CHECK(setsockopt(ss.fd, SOL_NETLINK, NETLINK_CAP_ACK, &optval, sizeof(optval)) == 0); 105*568a645bSAlexander V. Chernikov optval = 1; 106*568a645bSAlexander V. Chernikov ATF_CHECK(setsockopt(ss.fd, SOL_NETLINK, NETLINK_EXT_ACK, &optval, sizeof(optval)) == 0); 107*568a645bSAlexander V. Chernikov 108*568a645bSAlexander V. Chernikov snl_init_writer(&ss, &nw); 109*568a645bSAlexander V. Chernikov 110*568a645bSAlexander V. Chernikov struct nlmsghdr *hdr = snl_create_msg_request(&nw, 255); 111*568a645bSAlexander V. Chernikov ATF_CHECK(hdr != NULL); 112*568a645bSAlexander V. Chernikov ATF_CHECK(snl_reserve_msg_object(&nw, struct ifinfomsg) != NULL); 113*568a645bSAlexander V. Chernikov snl_add_msg_attr_string(&nw, 143, "some random string"); 114*568a645bSAlexander V. Chernikov ATF_CHECK(snl_finalize_msg(&nw) != NULL); 115*568a645bSAlexander V. Chernikov 116*568a645bSAlexander V. Chernikov ATF_CHECK(snl_send_message(&ss, hdr)); 117*568a645bSAlexander V. Chernikov 118*568a645bSAlexander V. Chernikov struct nlmsghdr *rx_hdr = snl_read_reply(&ss, hdr->nlmsg_seq); 119*568a645bSAlexander V. Chernikov ATF_CHECK(rx_hdr != NULL); 120*568a645bSAlexander V. Chernikov ATF_CHECK(rx_hdr->nlmsg_type == NLMSG_ERROR); 121*568a645bSAlexander V. Chernikov 122*568a645bSAlexander V. Chernikov struct snl_errmsg_data e = {}; 123*568a645bSAlexander V. Chernikov ATF_CHECK(snl_parse_errmsg(&ss, rx_hdr, &e)); 124*568a645bSAlexander V. Chernikov ATF_CHECK(e.error != 0); 125*568a645bSAlexander V. Chernikov ATF_CHECK(!memcmp(hdr, e.orig_hdr, sizeof(struct nlmsghdr))); 126*568a645bSAlexander V. Chernikov 127*568a645bSAlexander V. Chernikov ATF_CHECK(e.error_str != NULL); 128*568a645bSAlexander V. Chernikov } 129*568a645bSAlexander V. Chernikov 130*568a645bSAlexander V. Chernikov ATF_TC(snl_parse_errmsg_uncapped_extack); 131*568a645bSAlexander V. Chernikov ATF_TC_HEAD(snl_parse_errmsg_uncapped_extack, tc) 132*568a645bSAlexander V. Chernikov { 133*568a645bSAlexander V. Chernikov atf_tc_set_md_var(tc, "descr", "Tests snl(3) correctly parsing errors with extack"); 134*568a645bSAlexander V. Chernikov } 135*568a645bSAlexander V. Chernikov 136*568a645bSAlexander V. Chernikov ATF_TC_BODY(snl_parse_errmsg_uncapped_extack, tc) 137*568a645bSAlexander V. Chernikov { 138*568a645bSAlexander V. Chernikov struct snl_state ss; 139*568a645bSAlexander V. Chernikov struct snl_writer nw; 140*568a645bSAlexander V. Chernikov 141*568a645bSAlexander V. Chernikov require_netlink(); 142*568a645bSAlexander V. Chernikov 143*568a645bSAlexander V. Chernikov ATF_CHECK(snl_init(&ss, NETLINK_ROUTE)); 144*568a645bSAlexander V. Chernikov 145*568a645bSAlexander V. Chernikov int optval = 1; 146*568a645bSAlexander V. Chernikov ATF_CHECK(setsockopt(ss.fd, SOL_NETLINK, NETLINK_EXT_ACK, &optval, sizeof(optval)) == 0); 147*568a645bSAlexander V. Chernikov 148*568a645bSAlexander V. Chernikov snl_init_writer(&ss, &nw); 149*568a645bSAlexander V. Chernikov 150*568a645bSAlexander V. Chernikov struct nlmsghdr *hdr = snl_create_msg_request(&nw, 255); 151*568a645bSAlexander V. Chernikov ATF_CHECK(hdr != NULL); 152*568a645bSAlexander V. Chernikov ATF_CHECK(snl_reserve_msg_object(&nw, struct ifinfomsg) != NULL); 153*568a645bSAlexander V. Chernikov snl_add_msg_attr_string(&nw, 143, "some random string"); 154*568a645bSAlexander V. Chernikov ATF_CHECK(snl_finalize_msg(&nw) != NULL); 155*568a645bSAlexander V. Chernikov 156*568a645bSAlexander V. Chernikov ATF_CHECK(snl_send_message(&ss, hdr)); 157*568a645bSAlexander V. Chernikov 158*568a645bSAlexander V. Chernikov struct nlmsghdr *rx_hdr = snl_read_reply(&ss, hdr->nlmsg_seq); 159*568a645bSAlexander V. Chernikov ATF_CHECK(rx_hdr != NULL); 160*568a645bSAlexander V. Chernikov ATF_CHECK(rx_hdr->nlmsg_type == NLMSG_ERROR); 161*568a645bSAlexander V. Chernikov 162*568a645bSAlexander V. Chernikov struct snl_errmsg_data e = {}; 163*568a645bSAlexander V. Chernikov ATF_CHECK(snl_parse_errmsg(&ss, rx_hdr, &e)); 164*568a645bSAlexander V. Chernikov ATF_CHECK(e.error != 0); 165*568a645bSAlexander V. Chernikov ATF_CHECK(!memcmp(hdr, e.orig_hdr, hdr->nlmsg_len)); 166*568a645bSAlexander V. Chernikov 167*568a645bSAlexander V. Chernikov ATF_CHECK(e.error_str != NULL); 168*568a645bSAlexander V. Chernikov } 169*568a645bSAlexander V. Chernikov 170f2c8381fSAlexander V. Chernikov ATF_TC(snl_list_ifaces); 171f2c8381fSAlexander V. Chernikov ATF_TC_HEAD(snl_list_ifaces, tc) 172f2c8381fSAlexander V. Chernikov { 173f2c8381fSAlexander V. Chernikov atf_tc_set_md_var(tc, "descr", "Tests snl(3) listing interfaces"); 174f2c8381fSAlexander V. Chernikov } 175f2c8381fSAlexander V. Chernikov 176f2c8381fSAlexander V. Chernikov struct nl_parsed_link { 177f2c8381fSAlexander V. Chernikov uint32_t ifi_index; 178f2c8381fSAlexander V. Chernikov uint32_t ifla_mtu; 179f2c8381fSAlexander V. Chernikov char *ifla_ifname; 180f2c8381fSAlexander V. Chernikov }; 181f2c8381fSAlexander V. Chernikov 182f2c8381fSAlexander V. Chernikov #define _IN(_field) offsetof(struct ifinfomsg, _field) 183f2c8381fSAlexander V. Chernikov #define _OUT(_field) offsetof(struct nl_parsed_link, _field) 184f2c8381fSAlexander V. Chernikov static struct snl_attr_parser ap_link[] = { 185f2c8381fSAlexander V. Chernikov { .type = IFLA_IFNAME, .off = _OUT(ifla_ifname), .cb = snl_attr_get_string }, 186f2c8381fSAlexander V. Chernikov { .type = IFLA_MTU, .off = _OUT(ifla_mtu), .cb = snl_attr_get_uint32 }, 187f2c8381fSAlexander V. Chernikov }; 188f2c8381fSAlexander V. Chernikov static struct snl_field_parser fp_link[] = { 189f2c8381fSAlexander V. Chernikov {.off_in = _IN(ifi_index), .off_out = _OUT(ifi_index), .cb = snl_field_get_uint32 }, 190f2c8381fSAlexander V. Chernikov }; 191f2c8381fSAlexander V. Chernikov #undef _IN 192f2c8381fSAlexander V. Chernikov #undef _OUT 193f2c8381fSAlexander V. Chernikov SNL_DECLARE_PARSER(link_parser, struct ifinfomsg, fp_link, ap_link); 194f2c8381fSAlexander V. Chernikov 195f2c8381fSAlexander V. Chernikov 196f2c8381fSAlexander V. Chernikov ATF_TC_BODY(snl_list_ifaces, tc) 197f2c8381fSAlexander V. Chernikov { 198f2c8381fSAlexander V. Chernikov struct snl_state ss; 19973ae25c1SAlexander V. Chernikov struct snl_writer nw; 200f2c8381fSAlexander V. Chernikov 201f2c8381fSAlexander V. Chernikov require_netlink(); 202f2c8381fSAlexander V. Chernikov 203f2c8381fSAlexander V. Chernikov if (!snl_init(&ss, NETLINK_ROUTE)) 204f2c8381fSAlexander V. Chernikov atf_tc_fail("snl_init() failed"); 205f2c8381fSAlexander V. Chernikov 20673ae25c1SAlexander V. Chernikov snl_init_writer(&ss, &nw); 207f2c8381fSAlexander V. Chernikov 20873ae25c1SAlexander V. Chernikov struct nlmsghdr *hdr = snl_create_msg_request(&nw, RTM_GETLINK); 20973ae25c1SAlexander V. Chernikov ATF_CHECK(hdr != NULL); 21073ae25c1SAlexander V. Chernikov ATF_CHECK(snl_reserve_msg_object(&nw, struct ifinfomsg) != NULL); 21173ae25c1SAlexander V. Chernikov ATF_CHECK(snl_finalize_msg(&nw) != NULL); 21273ae25c1SAlexander V. Chernikov uint32_t seq_id = hdr->nlmsg_seq; 213f2c8381fSAlexander V. Chernikov 21473ae25c1SAlexander V. Chernikov ATF_CHECK(snl_send_message(&ss, hdr)); 21573ae25c1SAlexander V. Chernikov 21673ae25c1SAlexander V. Chernikov struct snl_errmsg_data e = {}; 217f2c8381fSAlexander V. Chernikov int count = 0; 218f2c8381fSAlexander V. Chernikov 21973ae25c1SAlexander V. Chernikov while ((hdr = snl_read_reply_multi(&ss, seq_id, &e)) != NULL) { 220f2c8381fSAlexander V. Chernikov count++; 221f2c8381fSAlexander V. Chernikov } 22273ae25c1SAlexander V. Chernikov ATF_REQUIRE(e.error == 0); 22373ae25c1SAlexander V. Chernikov 224f2c8381fSAlexander V. Chernikov ATF_REQUIRE_MSG(count > 0, "Empty interface list"); 225f2c8381fSAlexander V. Chernikov } 226f2c8381fSAlexander V. Chernikov 227f2c8381fSAlexander V. Chernikov ATF_TP_ADD_TCS(tp) 228f2c8381fSAlexander V. Chernikov { 22973ae25c1SAlexander V. Chernikov ATF_TP_ADD_TC(tp, snl_verify_core_parsers); 23073ae25c1SAlexander V. Chernikov ATF_TP_ADD_TC(tp, snl_verify_route_parsers); 231*568a645bSAlexander V. Chernikov ATF_TP_ADD_TC(tp, snl_parse_errmsg_capped); 232*568a645bSAlexander V. Chernikov ATF_TP_ADD_TC(tp, snl_parse_errmsg_capped_extack); 233*568a645bSAlexander V. Chernikov ATF_TP_ADD_TC(tp, snl_parse_errmsg_uncapped_extack); 234f2c8381fSAlexander V. Chernikov ATF_TP_ADD_TC(tp, snl_list_ifaces); 235f2c8381fSAlexander V. Chernikov 236f2c8381fSAlexander V. Chernikov return (atf_no_error()); 237f2c8381fSAlexander V. Chernikov } 238