xref: /freebsd/tests/sys/netlink/test_snl.c (revision af23369a6deaaeb612ab266eb88b8bb8d560c322)
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 
13 #include <atf-c.h>
14 
15 static void
16 require_netlink(void)
17 {
18 	if (modfind("netlink") == -1)
19 		atf_tc_skip("netlink module not loaded");
20 }
21 
22 
23 ATF_TC(snl_list_ifaces);
24 ATF_TC_HEAD(snl_list_ifaces, tc)
25 {
26 	atf_tc_set_md_var(tc, "descr", "Tests snl(3) listing interfaces");
27 }
28 
29 struct nl_parsed_link {
30 	uint32_t		ifi_index;
31 	uint32_t		ifla_mtu;
32 	char			*ifla_ifname;
33 };
34 
35 #define	_IN(_field)	offsetof(struct ifinfomsg, _field)
36 #define	_OUT(_field)	offsetof(struct nl_parsed_link, _field)
37 static struct snl_attr_parser ap_link[] = {
38 	{ .type = IFLA_IFNAME, .off = _OUT(ifla_ifname), .cb = snl_attr_get_string },
39 	{ .type = IFLA_MTU, .off = _OUT(ifla_mtu), .cb = snl_attr_get_uint32 },
40 };
41 static struct snl_field_parser fp_link[] = {
42 	{.off_in = _IN(ifi_index), .off_out = _OUT(ifi_index), .cb = snl_field_get_uint32 },
43 };
44 #undef _IN
45 #undef _OUT
46 SNL_DECLARE_PARSER(link_parser, struct ifinfomsg, fp_link, ap_link);
47 
48 
49 ATF_TC_BODY(snl_list_ifaces, tc)
50 {
51 	struct snl_state ss;
52 
53 	require_netlink();
54 
55 	if (!snl_init(&ss, NETLINK_ROUTE))
56 		atf_tc_fail("snl_init() failed");
57 
58 	struct {
59 		struct nlmsghdr hdr;
60 		struct ifinfomsg ifmsg;
61 	} msg = {
62 		.hdr.nlmsg_type = RTM_GETLINK,
63 		.hdr.nlmsg_flags = NLM_F_DUMP | NLM_F_REQUEST,
64 		.hdr.nlmsg_seq = snl_get_seq(&ss),
65 	};
66 	msg.hdr.nlmsg_len = sizeof(msg);
67 
68 	if (!snl_send(&ss, &msg, sizeof(msg))) {
69 		snl_free(&ss);
70 		atf_tc_fail("snl_send() failed");
71 	}
72 
73 	struct nlmsghdr *hdr;
74 	int count = 0;
75 	while ((hdr = snl_read_message(&ss)) != NULL && hdr->nlmsg_type != NLMSG_DONE) {
76 		if (hdr->nlmsg_seq != msg.hdr.nlmsg_seq)
77 			continue;
78 
79 		struct nl_parsed_link link = {};
80 		if (!snl_parse_nlmsg(&ss, hdr, &link_parser, &link))
81 			continue;
82 		count++;
83 	}
84 	ATF_REQUIRE_MSG(count > 0, "Empty interface list");
85 }
86 
87 ATF_TP_ADD_TCS(tp)
88 {
89 	ATF_TP_ADD_TC(tp, snl_list_ifaces);
90 
91 	return (atf_no_error());
92 }
93