1 #include <stdio.h> 2 #include <string.h> 3 #include <stdlib.h> 4 5 #include <sys/param.h> 6 #include <sys/module.h> 7 8 #include <netlink/netlink.h> 9 #include <netlink/netlink_route.h> 10 #include "netlink/netlink_snl.h" 11 #include "netlink/netlink_snl_route.h" 12 #include "netlink/netlink_snl_route_parsers.h" 13 14 #include <atf-c.h> 15 16 static const struct snl_hdr_parser *snl_all_core_parsers[] = { 17 &snl_errmsg_parser, &snl_donemsg_parser, 18 &_nla_bit_parser, &_nla_bitset_parser, 19 }; 20 21 static const struct snl_hdr_parser *snl_all_route_parsers[] = { 22 &_metrics_mp_nh_parser, &_mpath_nh_parser, &_metrics_parser, &snl_rtm_route_parser, 23 &_link_fbsd_parser, &snl_rtm_link_parser, &snl_rtm_link_parser_simple, 24 &_neigh_fbsd_parser, &snl_rtm_neigh_parser, 25 &_addr_fbsd_parser, &snl_rtm_addr_parser, &_nh_fbsd_parser, &snl_nhmsg_parser, 26 }; 27 28 ATF_TC(snl_verify_core_parsers); 29 ATF_TC_HEAD(snl_verify_core_parsers, tc) 30 { 31 atf_tc_set_md_var(tc, "descr", "Tests snl(3) core nlmsg parsers are correct"); 32 } 33 34 ATF_TC_BODY(snl_verify_core_parsers, tc) 35 { 36 SNL_VERIFY_PARSERS(snl_all_core_parsers); 37 38 } 39 40 ATF_TC(snl_verify_route_parsers); 41 ATF_TC_HEAD(snl_verify_route_parsers, tc) 42 { 43 atf_tc_set_md_var(tc, "descr", "Tests snl(3) route parsers are correct"); 44 } 45 46 ATF_TC_BODY(snl_verify_route_parsers, tc) 47 { 48 SNL_VERIFY_PARSERS(snl_all_route_parsers); 49 50 } 51 52 ATF_TC(snl_parse_errmsg_capped); 53 ATF_TC_HEAD(snl_parse_errmsg_capped, tc) 54 { 55 atf_tc_set_md_var(tc, "descr", "Tests snl(3) correctly parsing capped errors"); 56 atf_tc_set_md_var(tc, "require.kmods", "netlink"); 57 } 58 59 ATF_TC_BODY(snl_parse_errmsg_capped, tc) 60 { 61 struct snl_state ss; 62 struct snl_writer nw; 63 64 if (!snl_init(&ss, NETLINK_ROUTE)) 65 atf_tc_fail("snl_init() failed"); 66 67 atf_tc_skip("does not work"); 68 69 int optval = 1; 70 ATF_CHECK(setsockopt(ss.fd, SOL_NETLINK, NETLINK_CAP_ACK, &optval, sizeof(optval)) == 0); 71 72 snl_init_writer(&ss, &nw); 73 74 struct nlmsghdr *hdr = snl_create_msg_request(&nw, 255); 75 ATF_CHECK(hdr != NULL); 76 ATF_CHECK(snl_reserve_msg_object(&nw, struct ifinfomsg) != NULL); 77 snl_add_msg_attr_string(&nw, 143, "some random string"); 78 ATF_CHECK(snl_finalize_msg(&nw) != NULL); 79 80 ATF_CHECK(snl_send_message(&ss, hdr)); 81 82 struct nlmsghdr *rx_hdr = snl_read_reply(&ss, hdr->nlmsg_seq); 83 ATF_CHECK(rx_hdr != NULL); 84 ATF_CHECK(rx_hdr->nlmsg_type == NLMSG_ERROR); 85 86 struct snl_errmsg_data e = {}; 87 ATF_CHECK(rx_hdr->nlmsg_len == sizeof(struct nlmsghdr) + sizeof(struct nlmsgerr)); 88 ATF_CHECK(snl_parse_errmsg(&ss, rx_hdr, &e)); 89 ATF_CHECK(e.error != 0); 90 ATF_CHECK(!memcmp(hdr, e.orig_hdr, sizeof(struct nlmsghdr))); 91 } 92 93 ATF_TC(snl_parse_errmsg_capped_extack); 94 ATF_TC_HEAD(snl_parse_errmsg_capped_extack, tc) 95 { 96 atf_tc_set_md_var(tc, "descr", "Tests snl(3) correctly parsing capped errors with extack"); 97 atf_tc_set_md_var(tc, "require.kmods", "netlink"); 98 } 99 100 ATF_TC_BODY(snl_parse_errmsg_capped_extack, tc) 101 { 102 struct snl_state ss; 103 struct snl_writer nw; 104 105 if (!snl_init(&ss, NETLINK_ROUTE)) 106 atf_tc_fail("snl_init() failed"); 107 108 int optval = 1; 109 ATF_CHECK(setsockopt(ss.fd, SOL_NETLINK, NETLINK_CAP_ACK, &optval, sizeof(optval)) == 0); 110 optval = 1; 111 ATF_CHECK(setsockopt(ss.fd, SOL_NETLINK, NETLINK_EXT_ACK, &optval, sizeof(optval)) == 0); 112 113 snl_init_writer(&ss, &nw); 114 115 struct nlmsghdr *hdr = snl_create_msg_request(&nw, 255); 116 ATF_CHECK(hdr != NULL); 117 ATF_CHECK(snl_reserve_msg_object(&nw, struct ifinfomsg) != NULL); 118 snl_add_msg_attr_string(&nw, 143, "some random string"); 119 ATF_CHECK(snl_finalize_msg(&nw) != NULL); 120 121 ATF_CHECK(snl_send_message(&ss, hdr)); 122 123 struct nlmsghdr *rx_hdr = snl_read_reply(&ss, hdr->nlmsg_seq); 124 ATF_CHECK(rx_hdr != NULL); 125 ATF_CHECK(rx_hdr->nlmsg_type == NLMSG_ERROR); 126 127 struct snl_errmsg_data e = {}; 128 ATF_CHECK(snl_parse_errmsg(&ss, rx_hdr, &e)); 129 ATF_CHECK(e.error != 0); 130 ATF_CHECK(!memcmp(hdr, e.orig_hdr, sizeof(struct nlmsghdr))); 131 132 ATF_CHECK(e.error_str != NULL); 133 } 134 135 ATF_TC(snl_parse_errmsg_uncapped_extack); 136 ATF_TC_HEAD(snl_parse_errmsg_uncapped_extack, tc) 137 { 138 atf_tc_set_md_var(tc, "descr", "Tests snl(3) correctly parsing errors with extack"); 139 atf_tc_set_md_var(tc, "require.kmods", "netlink"); 140 } 141 142 ATF_TC_BODY(snl_parse_errmsg_uncapped_extack, tc) 143 { 144 struct snl_state ss; 145 struct snl_writer nw; 146 147 ATF_CHECK(snl_init(&ss, NETLINK_ROUTE)); 148 149 int optval = 1; 150 ATF_CHECK(setsockopt(ss.fd, SOL_NETLINK, NETLINK_EXT_ACK, &optval, sizeof(optval)) == 0); 151 152 snl_init_writer(&ss, &nw); 153 154 struct nlmsghdr *hdr = snl_create_msg_request(&nw, 255); 155 ATF_CHECK(hdr != NULL); 156 ATF_CHECK(snl_reserve_msg_object(&nw, struct ifinfomsg) != NULL); 157 snl_add_msg_attr_string(&nw, 143, "some random string"); 158 ATF_CHECK(snl_finalize_msg(&nw) != NULL); 159 160 ATF_CHECK(snl_send_message(&ss, hdr)); 161 162 struct nlmsghdr *rx_hdr = snl_read_reply(&ss, hdr->nlmsg_seq); 163 ATF_CHECK(rx_hdr != NULL); 164 ATF_CHECK(rx_hdr->nlmsg_type == NLMSG_ERROR); 165 166 struct snl_errmsg_data e = {}; 167 ATF_CHECK(snl_parse_errmsg(&ss, rx_hdr, &e)); 168 ATF_CHECK(e.error != 0); 169 ATF_CHECK(!memcmp(hdr, e.orig_hdr, hdr->nlmsg_len)); 170 171 ATF_CHECK(e.error_str != NULL); 172 } 173 174 ATF_TC(snl_list_ifaces); 175 ATF_TC_HEAD(snl_list_ifaces, tc) 176 { 177 atf_tc_set_md_var(tc, "descr", "Tests snl(3) listing interfaces"); 178 atf_tc_set_md_var(tc, "require.kmods", "netlink"); 179 } 180 181 struct nl_parsed_link { 182 uint32_t ifi_index; 183 uint32_t ifla_mtu; 184 char *ifla_ifname; 185 }; 186 187 #define _IN(_field) offsetof(struct ifinfomsg, _field) 188 #define _OUT(_field) offsetof(struct nl_parsed_link, _field) 189 static struct snl_attr_parser ap_link[] = { 190 { .type = IFLA_IFNAME, .off = _OUT(ifla_ifname), .cb = snl_attr_get_string }, 191 { .type = IFLA_MTU, .off = _OUT(ifla_mtu), .cb = snl_attr_get_uint32 }, 192 }; 193 static struct snl_field_parser fp_link[] = { 194 {.off_in = _IN(ifi_index), .off_out = _OUT(ifi_index), .cb = snl_field_get_uint32 }, 195 }; 196 #undef _IN 197 #undef _OUT 198 SNL_DECLARE_PARSER(link_parser, struct ifinfomsg, fp_link, ap_link); 199 200 201 ATF_TC_BODY(snl_list_ifaces, tc) 202 { 203 struct snl_state ss; 204 struct snl_writer nw; 205 206 if (!snl_init(&ss, NETLINK_ROUTE)) 207 atf_tc_fail("snl_init() failed"); 208 209 snl_init_writer(&ss, &nw); 210 211 struct nlmsghdr *hdr = snl_create_msg_request(&nw, RTM_GETLINK); 212 ATF_CHECK(hdr != NULL); 213 ATF_CHECK(snl_reserve_msg_object(&nw, struct ifinfomsg) != NULL); 214 ATF_CHECK(snl_finalize_msg(&nw) != NULL); 215 uint32_t seq_id = hdr->nlmsg_seq; 216 217 ATF_CHECK(snl_send_message(&ss, hdr)); 218 219 struct snl_errmsg_data e = {}; 220 int count = 0; 221 222 while ((hdr = snl_read_reply_multi(&ss, seq_id, &e)) != NULL) { 223 count++; 224 } 225 ATF_REQUIRE(e.error == 0); 226 227 ATF_REQUIRE_MSG(count > 0, "Empty interface list"); 228 } 229 230 ATF_TP_ADD_TCS(tp) 231 { 232 ATF_TP_ADD_TC(tp, snl_verify_core_parsers); 233 ATF_TP_ADD_TC(tp, snl_verify_route_parsers); 234 ATF_TP_ADD_TC(tp, snl_parse_errmsg_capped); 235 ATF_TP_ADD_TC(tp, snl_parse_errmsg_capped_extack); 236 ATF_TP_ADD_TC(tp, snl_parse_errmsg_uncapped_extack); 237 ATF_TP_ADD_TC(tp, snl_list_ifaces); 238 239 return (atf_no_error()); 240 } 241