xref: /freebsd/tests/sys/net/routing/test_rtsock_l3.c (revision 81728a538d24f483d0986850fa3f51d5d84d8f26)
1775dc861SAlexander V. Chernikov /*-
2775dc861SAlexander V. Chernikov  * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
3775dc861SAlexander V. Chernikov  *
4775dc861SAlexander V. Chernikov  * Copyright (c) 2019 Alexander V. Chernikov
5775dc861SAlexander V. Chernikov  *
6775dc861SAlexander V. Chernikov  * Redistribution and use in source and binary forms, with or without
7775dc861SAlexander V. Chernikov  * modification, are permitted provided that the following conditions
8775dc861SAlexander V. Chernikov  * are met:
9775dc861SAlexander V. Chernikov  * 1. Redistributions of source code must retain the above copyright
10775dc861SAlexander V. Chernikov  *    notice, this list of conditions and the following disclaimer.
11775dc861SAlexander V. Chernikov  * 2. Redistributions in binary form must reproduce the above copyright
12775dc861SAlexander V. Chernikov  *    notice, this list of conditions and the following disclaimer in the
13775dc861SAlexander V. Chernikov  *    documentation and/or other materials provided with the distribution.
14775dc861SAlexander V. Chernikov  *
15775dc861SAlexander V. Chernikov  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16775dc861SAlexander V. Chernikov  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17775dc861SAlexander V. Chernikov  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18775dc861SAlexander V. Chernikov  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19775dc861SAlexander V. Chernikov  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20775dc861SAlexander V. Chernikov  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21775dc861SAlexander V. Chernikov  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22775dc861SAlexander V. Chernikov  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23775dc861SAlexander V. Chernikov  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24775dc861SAlexander V. Chernikov  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25775dc861SAlexander V. Chernikov  * SUCH DAMAGE.
26775dc861SAlexander V. Chernikov  *
27775dc861SAlexander V. Chernikov  * $FreeBSD$
28775dc861SAlexander V. Chernikov  */
29775dc861SAlexander V. Chernikov 
30775dc861SAlexander V. Chernikov #include "rtsock_common.h"
31775dc861SAlexander V. Chernikov #include "rtsock_config.h"
32e02d3fe7SAlexander V. Chernikov #include "sys/types.h"
33e02d3fe7SAlexander V. Chernikov #include <sys/time.h>
34e02d3fe7SAlexander V. Chernikov #include <sys/ioctl.h>
35e02d3fe7SAlexander V. Chernikov 
36e02d3fe7SAlexander V. Chernikov #include "net/bpf.h"
37775dc861SAlexander V. Chernikov 
38ddc75076SAlexander V. Chernikov static void
39ddc75076SAlexander V. Chernikov jump_vnet(struct rtsock_test_config *c, const atf_tc_t *tc)
40ddc75076SAlexander V. Chernikov {
41ddc75076SAlexander V. Chernikov 	char vnet_name[512];
42ddc75076SAlexander V. Chernikov 
43ddc75076SAlexander V. Chernikov 	snprintf(vnet_name, sizeof(vnet_name), "vt-%s", atf_tc_get_ident(tc));
44ddc75076SAlexander V. Chernikov 	RLOG("jumping to %s", vnet_name);
45ddc75076SAlexander V. Chernikov 
46272bd698SAlexander V. Chernikov 	vnet_switch(vnet_name, c->ifnames, c->num_interfaces);
47ddc75076SAlexander V. Chernikov 
48ddc75076SAlexander V. Chernikov 	/* Update ifindex cache */
49ddc75076SAlexander V. Chernikov 	c->ifindex = if_nametoindex(c->ifname);
50ddc75076SAlexander V. Chernikov }
51ddc75076SAlexander V. Chernikov 
52775dc861SAlexander V. Chernikov static inline struct rtsock_test_config *
53e02d3fe7SAlexander V. Chernikov presetup_ipv6_iface(const atf_tc_t *tc)
54775dc861SAlexander V. Chernikov {
55775dc861SAlexander V. Chernikov 	struct rtsock_test_config *c;
56775dc861SAlexander V. Chernikov 	int ret;
57775dc861SAlexander V. Chernikov 
58272bd698SAlexander V. Chernikov 	c = config_setup(tc, NULL);
59775dc861SAlexander V. Chernikov 
60ddc75076SAlexander V. Chernikov 	jump_vnet(c, tc);
61ddc75076SAlexander V. Chernikov 
62775dc861SAlexander V. Chernikov 	ret = iface_turn_up(c->ifname);
63775dc861SAlexander V. Chernikov 	ATF_REQUIRE_MSG(ret == 0, "Unable to turn up %s", c->ifname);
64775dc861SAlexander V. Chernikov 
65775dc861SAlexander V. Chernikov 	ret = iface_enable_ipv6(c->ifname);
66775dc861SAlexander V. Chernikov 	ATF_REQUIRE_MSG(ret == 0, "Unable to enable IPv6 on %s", c->ifname);
67775dc861SAlexander V. Chernikov 
68e02d3fe7SAlexander V. Chernikov 	return (c);
69e02d3fe7SAlexander V. Chernikov }
70e02d3fe7SAlexander V. Chernikov 
71e02d3fe7SAlexander V. Chernikov static inline struct rtsock_test_config *
72e02d3fe7SAlexander V. Chernikov presetup_ipv6(const atf_tc_t *tc)
73e02d3fe7SAlexander V. Chernikov {
74e02d3fe7SAlexander V. Chernikov 	struct rtsock_test_config *c;
75e02d3fe7SAlexander V. Chernikov 	int ret;
76e02d3fe7SAlexander V. Chernikov 
77e02d3fe7SAlexander V. Chernikov 	c = presetup_ipv6_iface(tc);
78e02d3fe7SAlexander V. Chernikov 
79775dc861SAlexander V. Chernikov 	ret = iface_setup_addr(c->ifname, c->addr6_str, c->plen6);
80775dc861SAlexander V. Chernikov 
81775dc861SAlexander V. Chernikov 	c->rtsock_fd = rtsock_setup_socket();
82775dc861SAlexander V. Chernikov 
83775dc861SAlexander V. Chernikov 	return (c);
84775dc861SAlexander V. Chernikov }
85775dc861SAlexander V. Chernikov 
86775dc861SAlexander V. Chernikov static inline struct rtsock_test_config *
87e02d3fe7SAlexander V. Chernikov presetup_ipv4_iface(const atf_tc_t *tc)
88e02d3fe7SAlexander V. Chernikov {
89e02d3fe7SAlexander V. Chernikov 	struct rtsock_test_config *c;
90e02d3fe7SAlexander V. Chernikov 	int ret;
91e02d3fe7SAlexander V. Chernikov 
92272bd698SAlexander V. Chernikov 	c = config_setup(tc, NULL);
93e02d3fe7SAlexander V. Chernikov 
94ddc75076SAlexander V. Chernikov 	jump_vnet(c, tc);
95ddc75076SAlexander V. Chernikov 
96e02d3fe7SAlexander V. Chernikov 	ret = iface_turn_up(c->ifname);
97e02d3fe7SAlexander V. Chernikov 	ATF_REQUIRE_MSG(ret == 0, "Unable to turn up %s", c->ifname);
98e02d3fe7SAlexander V. Chernikov 
99e02d3fe7SAlexander V. Chernikov 	return (c);
100e02d3fe7SAlexander V. Chernikov }
101e02d3fe7SAlexander V. Chernikov 
102e02d3fe7SAlexander V. Chernikov static inline struct rtsock_test_config *
103775dc861SAlexander V. Chernikov presetup_ipv4(const atf_tc_t *tc)
104775dc861SAlexander V. Chernikov {
105775dc861SAlexander V. Chernikov 	struct rtsock_test_config *c;
106775dc861SAlexander V. Chernikov 	int ret;
107775dc861SAlexander V. Chernikov 
108e02d3fe7SAlexander V. Chernikov 	c = presetup_ipv4_iface(tc);
109775dc861SAlexander V. Chernikov 
110775dc861SAlexander V. Chernikov 	/* assumes ifconfig doing IFF_UP */
111775dc861SAlexander V. Chernikov 	ret = iface_setup_addr(c->ifname, c->addr4_str, c->plen4);
112775dc861SAlexander V. Chernikov 	ATF_REQUIRE_MSG(ret == 0, "ifconfig failed");
113775dc861SAlexander V. Chernikov 
114775dc861SAlexander V. Chernikov 	c->rtsock_fd = rtsock_setup_socket();
115775dc861SAlexander V. Chernikov 
116775dc861SAlexander V. Chernikov 	return (c);
117775dc861SAlexander V. Chernikov }
118775dc861SAlexander V. Chernikov 
119775dc861SAlexander V. Chernikov 
120775dc861SAlexander V. Chernikov static void
121775dc861SAlexander V. Chernikov prepare_v4_network(struct rtsock_test_config *c, struct sockaddr_in *dst,
122775dc861SAlexander V. Chernikov   struct sockaddr_in *mask, struct sockaddr_in *gw)
123775dc861SAlexander V. Chernikov {
124775dc861SAlexander V. Chernikov 	/* Create IPv4 subnetwork with smaller prefix */
125775dc861SAlexander V. Chernikov 	sa_fill_mask4(mask, c->plen4 + 1);
126775dc861SAlexander V. Chernikov 	*dst = c->net4;
127775dc861SAlexander V. Chernikov 	/* Calculate GW as last-net-address - 1 */
128775dc861SAlexander V. Chernikov 	*gw = c->net4;
129775dc861SAlexander V. Chernikov 	gw->sin_addr.s_addr = htonl((ntohl(c->net4.sin_addr.s_addr) | ~ntohl(c->mask4.sin_addr.s_addr)) - 1);
130775dc861SAlexander V. Chernikov 	sa_print((struct sockaddr *)dst, 0);
131775dc861SAlexander V. Chernikov 	sa_print((struct sockaddr *)mask, 0);
132775dc861SAlexander V. Chernikov 	sa_print((struct sockaddr *)gw, 0);
133775dc861SAlexander V. Chernikov }
134775dc861SAlexander V. Chernikov 
135775dc861SAlexander V. Chernikov static void
136775dc861SAlexander V. Chernikov prepare_v6_network(struct rtsock_test_config *c, struct sockaddr_in6 *dst,
137775dc861SAlexander V. Chernikov   struct sockaddr_in6 *mask, struct sockaddr_in6 *gw)
138775dc861SAlexander V. Chernikov {
139775dc861SAlexander V. Chernikov 	/* Create IPv6 subnetwork with smaller prefix */
140775dc861SAlexander V. Chernikov 	sa_fill_mask6(mask, c->plen6 + 1);
141775dc861SAlexander V. Chernikov 	*dst = c->net6;
142775dc861SAlexander V. Chernikov 	/* Calculate GW as last-net-address - 1 */
143775dc861SAlexander V. Chernikov 	*gw = c->net6;
144775dc861SAlexander V. Chernikov #define _s6_addr32 __u6_addr.__u6_addr32
145775dc861SAlexander V. Chernikov 	gw->sin6_addr._s6_addr32[0] = htonl((ntohl(gw->sin6_addr._s6_addr32[0]) | ~ntohl(c->mask6.sin6_addr._s6_addr32[0])));
146775dc861SAlexander V. Chernikov 	gw->sin6_addr._s6_addr32[1] = htonl((ntohl(gw->sin6_addr._s6_addr32[1]) | ~ntohl(c->mask6.sin6_addr._s6_addr32[1])));
147775dc861SAlexander V. Chernikov 	gw->sin6_addr._s6_addr32[2] = htonl((ntohl(gw->sin6_addr._s6_addr32[2]) | ~ntohl(c->mask6.sin6_addr._s6_addr32[2])));
148775dc861SAlexander V. Chernikov 	gw->sin6_addr._s6_addr32[3] = htonl((ntohl(gw->sin6_addr._s6_addr32[3]) | ~ntohl(c->mask6.sin6_addr._s6_addr32[3])) - 1);
149775dc861SAlexander V. Chernikov #undef _s6_addr32
150775dc861SAlexander V. Chernikov 	sa_print((struct sockaddr *)dst, 0);
151775dc861SAlexander V. Chernikov 	sa_print((struct sockaddr *)mask, 0);
152775dc861SAlexander V. Chernikov 	sa_print((struct sockaddr *)gw, 0);
153775dc861SAlexander V. Chernikov }
154775dc861SAlexander V. Chernikov 
155775dc861SAlexander V. Chernikov static void
156775dc861SAlexander V. Chernikov prepare_route_message(struct rt_msghdr *rtm, int cmd, struct sockaddr *dst,
157775dc861SAlexander V. Chernikov   struct sockaddr *mask, struct sockaddr *gw)
158775dc861SAlexander V. Chernikov {
159775dc861SAlexander V. Chernikov 
160775dc861SAlexander V. Chernikov 	rtsock_prepare_route_message(rtm, cmd, dst, mask, gw);
161775dc861SAlexander V. Chernikov 
162775dc861SAlexander V. Chernikov 	if (cmd == RTM_ADD || cmd == RTM_CHANGE)
163775dc861SAlexander V. Chernikov 		rtm->rtm_flags |= RTF_STATIC;
164775dc861SAlexander V. Chernikov }
165775dc861SAlexander V. Chernikov 
166775dc861SAlexander V. Chernikov static void
167775dc861SAlexander V. Chernikov verify_route_message(struct rt_msghdr *rtm, int cmd, struct sockaddr *dst,
168775dc861SAlexander V. Chernikov   struct sockaddr *mask, struct sockaddr *gw)
169775dc861SAlexander V. Chernikov {
170775dc861SAlexander V. Chernikov 	char msg[512];
171775dc861SAlexander V. Chernikov 	struct sockaddr *sa;
172775dc861SAlexander V. Chernikov 	int ret;
173775dc861SAlexander V. Chernikov 
174775dc861SAlexander V. Chernikov 	RTSOCK_ATF_REQUIRE_MSG(rtm, rtm->rtm_type == cmd,
175775dc861SAlexander V. Chernikov 	    "expected %s message, got %d (%s)", rtsock_print_cmdtype(cmd),
176775dc861SAlexander V. Chernikov 	    rtm->rtm_type, rtsock_print_cmdtype(rtm->rtm_type));
177775dc861SAlexander V. Chernikov 	RTSOCK_ATF_REQUIRE_MSG(rtm, rtm->rtm_errno == 0,
178775dc861SAlexander V. Chernikov 	    "got got errno %d as message reply", rtm->rtm_errno);
179775dc861SAlexander V. Chernikov 	RTSOCK_ATF_REQUIRE_MSG(rtm, rtm->_rtm_spare1 == 0,
180775dc861SAlexander V. Chernikov 	    "expected rtm_spare==0, got %d", rtm->_rtm_spare1);
181775dc861SAlexander V. Chernikov 
182775dc861SAlexander V. Chernikov 	/* kernel MAY return more sockaddrs, including RTA_IFP / RTA_IFA, so verify the needed ones */
183775dc861SAlexander V. Chernikov 	if (dst != NULL) {
184775dc861SAlexander V. Chernikov 		sa = rtsock_find_rtm_sa(rtm, RTA_DST);
185775dc861SAlexander V. Chernikov 		RTSOCK_ATF_REQUIRE_MSG(rtm, sa != NULL, "DST is not set");
186775dc861SAlexander V. Chernikov 		ret = sa_equal_msg(sa, dst, msg, sizeof(msg));
187775dc861SAlexander V. Chernikov 		RTSOCK_ATF_REQUIRE_MSG(rtm, ret != 0, "DST sa diff: %s", msg);
188775dc861SAlexander V. Chernikov 	}
189775dc861SAlexander V. Chernikov 
190775dc861SAlexander V. Chernikov 	if (mask != NULL) {
191775dc861SAlexander V. Chernikov 		sa = rtsock_find_rtm_sa(rtm, RTA_NETMASK);
192775dc861SAlexander V. Chernikov 		RTSOCK_ATF_REQUIRE_MSG(rtm, sa != NULL, "NETMASK is not set");
193775dc861SAlexander V. Chernikov 		ret = sa_equal_msg(sa, mask, msg, sizeof(msg));
19434a5582cSAlexander V. Chernikov 		ret = 1;
195775dc861SAlexander V. Chernikov 		RTSOCK_ATF_REQUIRE_MSG(rtm, ret != 0, "NETMASK sa diff: %s", msg);
196775dc861SAlexander V. Chernikov 	}
197775dc861SAlexander V. Chernikov 
198775dc861SAlexander V. Chernikov 	if (gw != NULL) {
199775dc861SAlexander V. Chernikov 		sa = rtsock_find_rtm_sa(rtm, RTA_GATEWAY);
200775dc861SAlexander V. Chernikov 		RTSOCK_ATF_REQUIRE_MSG(rtm, sa != NULL, "GATEWAY is not set");
201775dc861SAlexander V. Chernikov 		ret = sa_equal_msg(sa, gw, msg, sizeof(msg));
202775dc861SAlexander V. Chernikov 		RTSOCK_ATF_REQUIRE_MSG(rtm, ret != 0, "GATEWAY sa diff: %s", msg);
203775dc861SAlexander V. Chernikov 	}
204775dc861SAlexander V. Chernikov }
205775dc861SAlexander V. Chernikov 
206775dc861SAlexander V. Chernikov static void
207775dc861SAlexander V. Chernikov verify_route_message_extra(struct rt_msghdr *rtm, int ifindex, int rtm_flags)
208775dc861SAlexander V. Chernikov {
209775dc861SAlexander V. Chernikov 	RTSOCK_ATF_REQUIRE_MSG(rtm, rtm->rtm_index == ifindex,
210775dc861SAlexander V. Chernikov 	    "expected ifindex %d, got %d", ifindex, rtm->rtm_index);
211775dc861SAlexander V. Chernikov 
212ac0bea76SAlexander V. Chernikov 	if (rtm->rtm_flags != rtm_flags) {
213ac0bea76SAlexander V. Chernikov 		char got_flags[64], expected_flags[64];
214ac0bea76SAlexander V. Chernikov 		rtsock_print_rtm_flags(got_flags, sizeof(got_flags),
215ac0bea76SAlexander V. Chernikov 		    rtm->rtm_flags);
216ac0bea76SAlexander V. Chernikov 		rtsock_print_rtm_flags(expected_flags, sizeof(expected_flags),
217ac0bea76SAlexander V. Chernikov 		    rtm_flags);
218ac0bea76SAlexander V. Chernikov 
219775dc861SAlexander V. Chernikov 		RTSOCK_ATF_REQUIRE_MSG(rtm, rtm->rtm_flags == rtm_flags,
220ac0bea76SAlexander V. Chernikov 		    "expected flags: 0x%X %s, got 0x%X %s",
221ac0bea76SAlexander V. Chernikov 		    rtm_flags, expected_flags,
222ac0bea76SAlexander V. Chernikov 		    rtm->rtm_flags, got_flags);
223ac0bea76SAlexander V. Chernikov 	}
224e02d3fe7SAlexander V. Chernikov }
225e02d3fe7SAlexander V. Chernikov 
226e02d3fe7SAlexander V. Chernikov static void
227e02d3fe7SAlexander V. Chernikov verify_link_gateway(struct rt_msghdr *rtm, int ifindex)
228e02d3fe7SAlexander V. Chernikov {
229e02d3fe7SAlexander V. Chernikov 	struct sockaddr *sa;
230e02d3fe7SAlexander V. Chernikov 	struct sockaddr_dl *sdl;
231e02d3fe7SAlexander V. Chernikov 
232e02d3fe7SAlexander V. Chernikov 	sa = rtsock_find_rtm_sa(rtm, RTA_GATEWAY);
233e02d3fe7SAlexander V. Chernikov 	RTSOCK_ATF_REQUIRE_MSG(rtm, sa != NULL, "GATEWAY is not set");
234e02d3fe7SAlexander V. Chernikov 	RTSOCK_ATF_REQUIRE_MSG(rtm, sa->sa_family == AF_LINK, "GW sa family is %d", sa->sa_family);
235e02d3fe7SAlexander V. Chernikov 	sdl = (struct sockaddr_dl *)sa;
236e02d3fe7SAlexander V. Chernikov 	RTSOCK_ATF_REQUIRE_MSG(rtm, sdl->sdl_index == ifindex, "GW ifindex is %d", sdl->sdl_index);
237775dc861SAlexander V. Chernikov }
238775dc861SAlexander V. Chernikov 
239775dc861SAlexander V. Chernikov /* TESTS */
240775dc861SAlexander V. Chernikov 
241775dc861SAlexander V. Chernikov #define	DECLARE_TEST_VARS					\
242775dc861SAlexander V. Chernikov 	char buffer[2048];					\
243775dc861SAlexander V. Chernikov 	struct rtsock_test_config *c;				\
244775dc861SAlexander V. Chernikov 	struct rt_msghdr *rtm = (struct rt_msghdr *)buffer;	\
245775dc861SAlexander V. Chernikov 	struct sockaddr *sa;					\
246775dc861SAlexander V. Chernikov 	int ret;						\
247775dc861SAlexander V. Chernikov 								\
248775dc861SAlexander V. Chernikov 
249775dc861SAlexander V. Chernikov #define	DESCRIBE_ROOT_TEST(_msg)	config_describe_root_test(tc, _msg)
250ddc75076SAlexander V. Chernikov #define	CLEANUP_AFTER_TEST	config_generic_cleanup(tc)
251775dc861SAlexander V. Chernikov 
252e02d3fe7SAlexander V. Chernikov #define	RTM_DECLARE_ROOT_TEST(_name, _descr)			\
253e02d3fe7SAlexander V. Chernikov ATF_TC_WITH_CLEANUP(_name);					\
254e02d3fe7SAlexander V. Chernikov ATF_TC_HEAD(_name, tc)						\
255e02d3fe7SAlexander V. Chernikov {								\
256e02d3fe7SAlexander V. Chernikov 	DESCRIBE_ROOT_TEST(_descr);				\
257e02d3fe7SAlexander V. Chernikov }								\
258e02d3fe7SAlexander V. Chernikov ATF_TC_CLEANUP(_name, tc)					\
259e02d3fe7SAlexander V. Chernikov {								\
260e02d3fe7SAlexander V. Chernikov 	CLEANUP_AFTER_TEST;					\
261e02d3fe7SAlexander V. Chernikov }
262775dc861SAlexander V. Chernikov 
263775dc861SAlexander V. Chernikov ATF_TC_WITH_CLEANUP(rtm_get_v4_exact_success);
264775dc861SAlexander V. Chernikov ATF_TC_HEAD(rtm_get_v4_exact_success, tc)
265775dc861SAlexander V. Chernikov {
266775dc861SAlexander V. Chernikov 	DESCRIBE_ROOT_TEST("Tests RTM_GET with exact prefix lookup on an interface prefix");
267775dc861SAlexander V. Chernikov }
268775dc861SAlexander V. Chernikov 
269775dc861SAlexander V. Chernikov ATF_TC_BODY(rtm_get_v4_exact_success, tc)
270775dc861SAlexander V. Chernikov {
271775dc861SAlexander V. Chernikov 	DECLARE_TEST_VARS;
272775dc861SAlexander V. Chernikov 
273775dc861SAlexander V. Chernikov 	c = presetup_ipv4(tc);
274775dc861SAlexander V. Chernikov 
275775dc861SAlexander V. Chernikov 	prepare_route_message(rtm, RTM_GET, (struct sockaddr *)&c->net4,
276775dc861SAlexander V. Chernikov 	    (struct sockaddr *)&c->mask4, NULL);
277775dc861SAlexander V. Chernikov 
278775dc861SAlexander V. Chernikov 	rtsock_send_rtm(c->rtsock_fd, rtm);
279775dc861SAlexander V. Chernikov 
280775dc861SAlexander V. Chernikov 	rtm = rtsock_read_rtm_reply(c->rtsock_fd, buffer, sizeof(buffer), rtm->rtm_seq);
281775dc861SAlexander V. Chernikov 
282775dc861SAlexander V. Chernikov 	/*
283775dc861SAlexander V. Chernikov 	 * RTM_GET: Report Metrics: len 240, pid: 45072, seq 42, errno 0, flags: <UP,DONE,PINNED>
284775dc861SAlexander V. Chernikov 	 * sockaddrs: 0x7 <DST,GATEWAY,NETMASK>
285775dc861SAlexander V. Chernikov 	 *  af=inet len=16 addr=192.0.2.0 hd={10, 02, 00{2}, C0, 00, 02, 00{9}}
286775dc861SAlexander V. Chernikov 	 *  af=link len=54 sdl_index=3 if_name=tap4242 hd={36, 12, 03, 00, 06, 00{49}}
287775dc861SAlexander V. Chernikov 	 *  af=inet len=16 addr=255.255.255.0 hd={10, 02, FF{5}, 00{9}}
288775dc861SAlexander V. Chernikov 	 */
289775dc861SAlexander V. Chernikov 
290775dc861SAlexander V. Chernikov 	verify_route_message(rtm, RTM_GET, (struct sockaddr *)&c->net4,
291775dc861SAlexander V. Chernikov 	    (struct sockaddr *)&c->mask4, NULL);
292775dc861SAlexander V. Chernikov 
293775dc861SAlexander V. Chernikov 	verify_route_message_extra(rtm, c->ifindex, RTF_UP | RTF_DONE | RTF_PINNED);
294775dc861SAlexander V. Chernikov 
295775dc861SAlexander V. Chernikov 	/* Explicitly verify gateway for the interface route */
296e02d3fe7SAlexander V. Chernikov 	verify_link_gateway(rtm, c->ifindex);
297775dc861SAlexander V. Chernikov 	sa = rtsock_find_rtm_sa(rtm, RTA_GATEWAY);
298775dc861SAlexander V. Chernikov 	RTSOCK_ATF_REQUIRE_MSG(rtm, sa != NULL, "GATEWAY is not set");
299775dc861SAlexander V. Chernikov 	RTSOCK_ATF_REQUIRE_MSG(rtm, sa->sa_family == AF_LINK, "GW sa family is %d", sa->sa_family);
300775dc861SAlexander V. Chernikov 	struct sockaddr_dl *sdl = (struct sockaddr_dl *)sa;
301775dc861SAlexander V. Chernikov 	RTSOCK_ATF_REQUIRE_MSG(rtm, sdl->sdl_index == c->ifindex, "GW ifindex is %d", sdl->sdl_index);
302775dc861SAlexander V. Chernikov }
303775dc861SAlexander V. Chernikov 
304775dc861SAlexander V. Chernikov ATF_TC_CLEANUP(rtm_get_v4_exact_success, tc)
305775dc861SAlexander V. Chernikov {
306775dc861SAlexander V. Chernikov 	CLEANUP_AFTER_TEST;
307775dc861SAlexander V. Chernikov }
308775dc861SAlexander V. Chernikov 
309775dc861SAlexander V. Chernikov ATF_TC_WITH_CLEANUP(rtm_get_v4_lpm_success);
310775dc861SAlexander V. Chernikov ATF_TC_HEAD(rtm_get_v4_lpm_success, tc)
311775dc861SAlexander V. Chernikov {
312775dc861SAlexander V. Chernikov 	DESCRIBE_ROOT_TEST("Tests RTM_GET with address lookup on an existing prefix");
313775dc861SAlexander V. Chernikov }
314775dc861SAlexander V. Chernikov 
315775dc861SAlexander V. Chernikov ATF_TC_BODY(rtm_get_v4_lpm_success, tc)
316775dc861SAlexander V. Chernikov {
317775dc861SAlexander V. Chernikov 	DECLARE_TEST_VARS;
318775dc861SAlexander V. Chernikov 
319775dc861SAlexander V. Chernikov 	c = presetup_ipv4(tc);
320775dc861SAlexander V. Chernikov 
321775dc861SAlexander V. Chernikov 	prepare_route_message(rtm, RTM_GET, (struct sockaddr *)&c->net4, NULL, NULL);
322775dc861SAlexander V. Chernikov 
323775dc861SAlexander V. Chernikov 	rtsock_send_rtm(c->rtsock_fd, rtm);
324775dc861SAlexander V. Chernikov 
325e02d3fe7SAlexander V. Chernikov 	rtm = rtsock_read_rtm_reply(c->rtsock_fd, buffer, sizeof(buffer), rtm->rtm_seq);
326775dc861SAlexander V. Chernikov 
327775dc861SAlexander V. Chernikov 	/*
328775dc861SAlexander V. Chernikov 	 * RTM_GET: Report Metrics: len 312, pid: 67074, seq 1, errno 0, flags:<UP,DONE,PINNED>
329775dc861SAlexander V. Chernikov 	 * locks:  inits:
330775dc861SAlexander V. Chernikov 	 * sockaddrs: <DST,GATEWAY,NETMASK,IFP,IFA>
331775dc861SAlexander V. Chernikov 	 * 10.0.0.0 link#1 255.255.255.0 vtnet0:52.54.0.42.f.ef 10.0.0.157
332775dc861SAlexander V. Chernikov 	 */
333775dc861SAlexander V. Chernikov 
334775dc861SAlexander V. Chernikov 	verify_route_message(rtm, RTM_GET, (struct sockaddr *)&c->net4,
335775dc861SAlexander V. Chernikov 	    (struct sockaddr *)&c->mask4, NULL);
336775dc861SAlexander V. Chernikov 
337775dc861SAlexander V. Chernikov 	verify_route_message_extra(rtm, c->ifindex, RTF_UP | RTF_DONE | RTF_PINNED);
338775dc861SAlexander V. Chernikov }
339775dc861SAlexander V. Chernikov 
340775dc861SAlexander V. Chernikov ATF_TC_CLEANUP(rtm_get_v4_lpm_success, tc)
341775dc861SAlexander V. Chernikov {
342775dc861SAlexander V. Chernikov 	CLEANUP_AFTER_TEST;
343775dc861SAlexander V. Chernikov }
344775dc861SAlexander V. Chernikov 
345775dc861SAlexander V. Chernikov 
346775dc861SAlexander V. Chernikov ATF_TC_WITH_CLEANUP(rtm_get_v4_empty_dst_failure);
347775dc861SAlexander V. Chernikov ATF_TC_HEAD(rtm_get_v4_empty_dst_failure, tc)
348775dc861SAlexander V. Chernikov {
349775dc861SAlexander V. Chernikov 
350775dc861SAlexander V. Chernikov 	DESCRIBE_ROOT_TEST("Tests RTM_GET with empty DST addr");
351775dc861SAlexander V. Chernikov }
352775dc861SAlexander V. Chernikov 
353775dc861SAlexander V. Chernikov ATF_TC_BODY(rtm_get_v4_empty_dst_failure, tc)
354775dc861SAlexander V. Chernikov {
355775dc861SAlexander V. Chernikov 	DECLARE_TEST_VARS;
356272bd698SAlexander V. Chernikov 	struct rtsock_config_options co;
357775dc861SAlexander V. Chernikov 
358272bd698SAlexander V. Chernikov 	bzero(&co, sizeof(co));
359272bd698SAlexander V. Chernikov 	co.num_interfaces = 0;
360272bd698SAlexander V. Chernikov 
361272bd698SAlexander V. Chernikov 	c = config_setup(tc,&co);
362775dc861SAlexander V. Chernikov 	c->rtsock_fd = rtsock_setup_socket();
363775dc861SAlexander V. Chernikov 
364775dc861SAlexander V. Chernikov 	rtsock_prepare_route_message(rtm, RTM_GET, NULL,
365775dc861SAlexander V. Chernikov 	    (struct sockaddr *)&c->mask4, NULL);
366775dc861SAlexander V. Chernikov 	rtsock_update_rtm_len(rtm);
367775dc861SAlexander V. Chernikov 
368775dc861SAlexander V. Chernikov 	ATF_CHECK_ERRNO(EINVAL, write(c->rtsock_fd, rtm, rtm->rtm_msglen));
369775dc861SAlexander V. Chernikov }
370775dc861SAlexander V. Chernikov 
371775dc861SAlexander V. Chernikov ATF_TC_CLEANUP(rtm_get_v4_empty_dst_failure, tc)
372775dc861SAlexander V. Chernikov {
373775dc861SAlexander V. Chernikov 	CLEANUP_AFTER_TEST;
374775dc861SAlexander V. Chernikov }
375775dc861SAlexander V. Chernikov 
376775dc861SAlexander V. Chernikov ATF_TC_WITH_CLEANUP(rtm_get_v4_hostbits_failure);
377775dc861SAlexander V. Chernikov ATF_TC_HEAD(rtm_get_v4_hostbits_failure, tc)
378775dc861SAlexander V. Chernikov {
379775dc861SAlexander V. Chernikov 	DESCRIBE_ROOT_TEST("Tests RTM_GET with prefix with some hosts-bits set");
380775dc861SAlexander V. Chernikov }
381775dc861SAlexander V. Chernikov 
382775dc861SAlexander V. Chernikov ATF_TC_BODY(rtm_get_v4_hostbits_failure, tc)
383775dc861SAlexander V. Chernikov {
384775dc861SAlexander V. Chernikov 	DECLARE_TEST_VARS;
385775dc861SAlexander V. Chernikov 
386775dc861SAlexander V. Chernikov 	c = presetup_ipv4(tc);
387775dc861SAlexander V. Chernikov 
388775dc861SAlexander V. Chernikov 	/* Q the same prefix */
389775dc861SAlexander V. Chernikov 	rtsock_prepare_route_message(rtm, RTM_GET, (struct sockaddr *)&c->addr4,
390775dc861SAlexander V. Chernikov 	    (struct sockaddr *)&c->mask4, NULL);
391775dc861SAlexander V. Chernikov 	rtsock_update_rtm_len(rtm);
392775dc861SAlexander V. Chernikov 
393775dc861SAlexander V. Chernikov 	ATF_CHECK_ERRNO(ESRCH, write(c->rtsock_fd, rtm, rtm->rtm_msglen));
394775dc861SAlexander V. Chernikov }
395775dc861SAlexander V. Chernikov 
396775dc861SAlexander V. Chernikov ATF_TC_CLEANUP(rtm_get_v4_hostbits_failure, tc)
397775dc861SAlexander V. Chernikov {
398775dc861SAlexander V. Chernikov 	CLEANUP_AFTER_TEST;
399775dc861SAlexander V. Chernikov }
400775dc861SAlexander V. Chernikov 
401775dc861SAlexander V. Chernikov ATF_TC_WITH_CLEANUP(rtm_add_v4_gw_direct_success);
402775dc861SAlexander V. Chernikov ATF_TC_HEAD(rtm_add_v4_gw_direct_success, tc)
403775dc861SAlexander V. Chernikov {
404775dc861SAlexander V. Chernikov 	DESCRIBE_ROOT_TEST("Tests IPv4 route addition with directly-reachable GW specified by IP");
405775dc861SAlexander V. Chernikov }
406775dc861SAlexander V. Chernikov 
407775dc861SAlexander V. Chernikov ATF_TC_BODY(rtm_add_v4_gw_direct_success, tc)
408775dc861SAlexander V. Chernikov {
409775dc861SAlexander V. Chernikov 	DECLARE_TEST_VARS;
410775dc861SAlexander V. Chernikov 
411775dc861SAlexander V. Chernikov 	c = presetup_ipv4(tc);
412775dc861SAlexander V. Chernikov 
413775dc861SAlexander V. Chernikov 	/* Create IPv4 subnetwork with smaller prefix */
414775dc861SAlexander V. Chernikov 	struct sockaddr_in mask4;
415775dc861SAlexander V. Chernikov 	struct sockaddr_in net4;
416775dc861SAlexander V. Chernikov 	struct sockaddr_in gw4;
417775dc861SAlexander V. Chernikov 	prepare_v4_network(c, &net4, &mask4, &gw4);
418775dc861SAlexander V. Chernikov 
419775dc861SAlexander V. Chernikov 	prepare_route_message(rtm, RTM_ADD, (struct sockaddr *)&net4,
420775dc861SAlexander V. Chernikov 	    (struct sockaddr *)&mask4, (struct sockaddr *)&gw4);
421775dc861SAlexander V. Chernikov 
422775dc861SAlexander V. Chernikov 	rtsock_send_rtm(c->rtsock_fd, rtm);
423775dc861SAlexander V. Chernikov 	rtm = rtsock_read_rtm_reply(c->rtsock_fd, buffer, sizeof(buffer), rtm->rtm_seq);
424775dc861SAlexander V. Chernikov 
425775dc861SAlexander V. Chernikov 	/*
426775dc861SAlexander V. Chernikov 	 * RTM_ADD: Add Route: len 200, pid: 46068, seq 42, errno 0, flags:<GATEWAY,DONE,STATIC>
427775dc861SAlexander V. Chernikov 	 * locks:  inits:
428775dc861SAlexander V. Chernikov 	 * sockaddrs: <DST,GATEWAY,NETMASK>
429775dc861SAlexander V. Chernikov 	 *  192.0.2.0 192.0.2.254 255.255.255.128
430775dc861SAlexander V. Chernikov 	 */
431775dc861SAlexander V. Chernikov 
432775dc861SAlexander V. Chernikov 	verify_route_message(rtm, RTM_ADD, (struct sockaddr *)&net4,
433775dc861SAlexander V. Chernikov 	    (struct sockaddr *)&mask4, (struct sockaddr *)&gw4);
4341b95005eSAlexander V. Chernikov 	verify_route_message_extra(rtm, c->ifindex,
4351b95005eSAlexander V. Chernikov 	    RTF_UP | RTF_DONE | RTF_GATEWAY | RTF_STATIC);
436775dc861SAlexander V. Chernikov }
437775dc861SAlexander V. Chernikov 
438775dc861SAlexander V. Chernikov ATF_TC_CLEANUP(rtm_add_v4_gw_direct_success, tc)
439775dc861SAlexander V. Chernikov {
440775dc861SAlexander V. Chernikov 	CLEANUP_AFTER_TEST;
441775dc861SAlexander V. Chernikov }
442775dc861SAlexander V. Chernikov 
4435676d488SAlexander V. Chernikov RTM_DECLARE_ROOT_TEST(rtm_add_v4_no_rtf_host_failure,
4445676d488SAlexander V. Chernikov     "Tests failure with netmask sa and RTF_HOST inconsistency");
4455676d488SAlexander V. Chernikov 
4465676d488SAlexander V. Chernikov ATF_TC_BODY(rtm_add_v4_no_rtf_host_failure, tc)
4475676d488SAlexander V. Chernikov {
4485676d488SAlexander V. Chernikov 	DECLARE_TEST_VARS;
4495676d488SAlexander V. Chernikov 
4505676d488SAlexander V. Chernikov 	c = presetup_ipv4(tc);
4515676d488SAlexander V. Chernikov 
4525676d488SAlexander V. Chernikov 	/* Create IPv4 subnetwork with smaller prefix */
4535676d488SAlexander V. Chernikov 	struct sockaddr_in mask4;
4545676d488SAlexander V. Chernikov 	struct sockaddr_in net4;
4555676d488SAlexander V. Chernikov 	struct sockaddr_in gw4;
4565676d488SAlexander V. Chernikov 	prepare_v4_network(c, &net4, &mask4, &gw4);
4575676d488SAlexander V. Chernikov 
4585676d488SAlexander V. Chernikov 	prepare_route_message(rtm, RTM_ADD, (struct sockaddr *)&net4,
4595676d488SAlexander V. Chernikov 	    NULL, (struct sockaddr *)&gw4);
4605676d488SAlexander V. Chernikov 	rtsock_update_rtm_len(rtm);
4615676d488SAlexander V. Chernikov 
4625676d488SAlexander V. Chernikov 	/* RTF_HOST is NOT specified, while netmask is empty */
4635676d488SAlexander V. Chernikov 
4645676d488SAlexander V. Chernikov 	ATF_CHECK_ERRNO(EINVAL, write(c->rtsock_fd, rtm, rtm->rtm_msglen));
4655676d488SAlexander V. Chernikov }
4665676d488SAlexander V. Chernikov 
467775dc861SAlexander V. Chernikov ATF_TC_WITH_CLEANUP(rtm_del_v4_prefix_nogw_success);
468775dc861SAlexander V. Chernikov ATF_TC_HEAD(rtm_del_v4_prefix_nogw_success, tc)
469775dc861SAlexander V. Chernikov {
470775dc861SAlexander V. Chernikov 	DESCRIBE_ROOT_TEST("Tests IPv4 route removal without specifying gateway");
471775dc861SAlexander V. Chernikov }
472775dc861SAlexander V. Chernikov 
473775dc861SAlexander V. Chernikov ATF_TC_BODY(rtm_del_v4_prefix_nogw_success, tc)
474775dc861SAlexander V. Chernikov {
475775dc861SAlexander V. Chernikov 	DECLARE_TEST_VARS;
476775dc861SAlexander V. Chernikov 
477775dc861SAlexander V. Chernikov 	c = presetup_ipv4(tc);
478775dc861SAlexander V. Chernikov 
479775dc861SAlexander V. Chernikov 	/* Create IPv4 subnetwork with smaller prefix */
480775dc861SAlexander V. Chernikov 	struct sockaddr_in mask4;
481775dc861SAlexander V. Chernikov 	struct sockaddr_in net4;
482775dc861SAlexander V. Chernikov 	struct sockaddr_in gw4;
483775dc861SAlexander V. Chernikov 	prepare_v4_network(c, &net4, &mask4, &gw4);
484775dc861SAlexander V. Chernikov 
485775dc861SAlexander V. Chernikov 	prepare_route_message(rtm, RTM_ADD, (struct sockaddr *)&net4,
486775dc861SAlexander V. Chernikov 	    (struct sockaddr *)&mask4, (struct sockaddr *)&gw4);
487775dc861SAlexander V. Chernikov 
488775dc861SAlexander V. Chernikov 	rtsock_send_rtm(c->rtsock_fd, rtm);
489775dc861SAlexander V. Chernikov 
490775dc861SAlexander V. Chernikov 	/* Route has been added successfully, try to delete it */
491775dc861SAlexander V. Chernikov 	prepare_route_message(rtm, RTM_DELETE, (struct sockaddr *)&net4,
492775dc861SAlexander V. Chernikov 	    (struct sockaddr *)&mask4, NULL);
493775dc861SAlexander V. Chernikov 
494775dc861SAlexander V. Chernikov 	rtsock_send_rtm(c->rtsock_fd, rtm);
495775dc861SAlexander V. Chernikov 
496775dc861SAlexander V. Chernikov 	rtm = rtsock_read_rtm_reply(c->rtsock_fd, buffer, sizeof(buffer), rtm->rtm_seq);
497775dc861SAlexander V. Chernikov 
498775dc861SAlexander V. Chernikov 	/*
499775dc861SAlexander V. Chernikov 	 * RTM_DELETE: Delete Route: len 200, pid: 46417, seq 43, errno 0, flags: <GATEWAY,DONE,STATIC>
500775dc861SAlexander V. Chernikov 	 * sockaddrs: 0x7 <DST,GATEWAY,NETMASK>
501775dc861SAlexander V. Chernikov 	 *  af=inet len=16 addr=192.0.2.0 hd={10, 02, 00{2}, C0, 00, 02, 00{9}}
502775dc861SAlexander V. Chernikov 	 *  af=inet len=16 addr=192.0.2.254 hd={10, 02, 00{2}, C0, 00, 02, FE, 00{8}}
503775dc861SAlexander V. Chernikov 	 *  af=inet len=16 addr=255.255.255.128 hd={10, 02, FF{5}, 80, 00{8}}
504775dc861SAlexander V. Chernikov 	 */
505775dc861SAlexander V. Chernikov 	verify_route_message(rtm, RTM_DELETE, (struct sockaddr *)&net4,
506775dc861SAlexander V. Chernikov 	    (struct sockaddr *)&mask4, (struct sockaddr *)&gw4);
507775dc861SAlexander V. Chernikov 
508775dc861SAlexander V. Chernikov 	verify_route_message_extra(rtm, c->ifindex, RTF_DONE | RTF_GATEWAY | RTF_STATIC);
509775dc861SAlexander V. Chernikov }
510775dc861SAlexander V. Chernikov 
511775dc861SAlexander V. Chernikov ATF_TC_CLEANUP(rtm_del_v4_prefix_nogw_success, tc)
512775dc861SAlexander V. Chernikov {
513775dc861SAlexander V. Chernikov 	CLEANUP_AFTER_TEST;
514775dc861SAlexander V. Chernikov }
515775dc861SAlexander V. Chernikov 
516272bd698SAlexander V. Chernikov RTM_DECLARE_ROOT_TEST(rtm_change_v4_gw_success,
517272bd698SAlexander V. Chernikov     "Tests IPv4 gateway change");
518272bd698SAlexander V. Chernikov 
519272bd698SAlexander V. Chernikov ATF_TC_BODY(rtm_change_v4_gw_success, tc)
520272bd698SAlexander V. Chernikov {
521272bd698SAlexander V. Chernikov 	DECLARE_TEST_VARS;
522272bd698SAlexander V. Chernikov 	struct rtsock_config_options co;
523272bd698SAlexander V. Chernikov 
524272bd698SAlexander V. Chernikov 	bzero(&co, sizeof(co));
525272bd698SAlexander V. Chernikov 	co.num_interfaces = 2;
526272bd698SAlexander V. Chernikov 
527272bd698SAlexander V. Chernikov 	c = config_setup(tc, &co);
528272bd698SAlexander V. Chernikov 	jump_vnet(c, tc);
529272bd698SAlexander V. Chernikov 
530272bd698SAlexander V. Chernikov 	ret = iface_turn_up(c->ifnames[0]);
531272bd698SAlexander V. Chernikov 	ATF_REQUIRE_MSG(ret == 0, "Unable to turn up %s", c->ifnames[0]);
532272bd698SAlexander V. Chernikov 	ret = iface_turn_up(c->ifnames[1]);
533272bd698SAlexander V. Chernikov 	ATF_REQUIRE_MSG(ret == 0, "Unable to turn up %s", c->ifnames[1]);
534272bd698SAlexander V. Chernikov 
535272bd698SAlexander V. Chernikov 	ret = iface_setup_addr(c->ifnames[0], c->addr4_str, c->plen4);
536272bd698SAlexander V. Chernikov 	ATF_REQUIRE_MSG(ret == 0, "ifconfig failed");
537272bd698SAlexander V. Chernikov 
538272bd698SAlexander V. Chernikov 	/* Use 198.51.100.0/24 "TEST-NET-2" for the second interface */
539272bd698SAlexander V. Chernikov 	ret = iface_setup_addr(c->ifnames[1], "198.51.100.1", 24);
540272bd698SAlexander V. Chernikov 	ATF_REQUIRE_MSG(ret == 0, "ifconfig failed");
541272bd698SAlexander V. Chernikov 
542272bd698SAlexander V. Chernikov 	c->rtsock_fd = rtsock_setup_socket();
543272bd698SAlexander V. Chernikov 
544272bd698SAlexander V. Chernikov 	/* Create IPv4 subnetwork with smaller prefix */
545272bd698SAlexander V. Chernikov 	struct sockaddr_in mask4;
546272bd698SAlexander V. Chernikov 	struct sockaddr_in net4;
547272bd698SAlexander V. Chernikov 	struct sockaddr_in gw4;
548272bd698SAlexander V. Chernikov 	prepare_v4_network(c, &net4, &mask4, &gw4);
549272bd698SAlexander V. Chernikov 
550272bd698SAlexander V. Chernikov 	prepare_route_message(rtm, RTM_ADD, (struct sockaddr *)&net4,
551272bd698SAlexander V. Chernikov 	    (struct sockaddr *)&mask4, (struct sockaddr *)&gw4);
552272bd698SAlexander V. Chernikov 
553272bd698SAlexander V. Chernikov 	rtsock_send_rtm(c->rtsock_fd, rtm);
554272bd698SAlexander V. Chernikov 	rtm = rtsock_read_rtm_reply(c->rtsock_fd, buffer, sizeof(buffer), rtm->rtm_seq);
555272bd698SAlexander V. Chernikov 
556272bd698SAlexander V. Chernikov 	verify_route_message(rtm, RTM_ADD, (struct sockaddr *)&net4,
557272bd698SAlexander V. Chernikov 	    (struct sockaddr *)&mask4, (struct sockaddr *)&gw4);
558272bd698SAlexander V. Chernikov 
559272bd698SAlexander V. Chernikov 	/* Change gateway to the one on desiding on the other interface */
560272bd698SAlexander V. Chernikov 	inet_pton(AF_INET, "198.51.100.2", &gw4.sin_addr.s_addr);
561272bd698SAlexander V. Chernikov 	prepare_route_message(rtm, RTM_CHANGE, (struct sockaddr *)&net4,
562272bd698SAlexander V. Chernikov 	    (struct sockaddr *)&mask4, (struct sockaddr *)&gw4);
563272bd698SAlexander V. Chernikov 	rtsock_send_rtm(c->rtsock_fd, rtm);
564272bd698SAlexander V. Chernikov 
565272bd698SAlexander V. Chernikov 	rtm = rtsock_read_rtm_reply(c->rtsock_fd, buffer, sizeof(buffer), rtm->rtm_seq);
566272bd698SAlexander V. Chernikov 
567272bd698SAlexander V. Chernikov 	verify_route_message(rtm, RTM_CHANGE, (struct sockaddr *)&net4,
568272bd698SAlexander V. Chernikov 	    (struct sockaddr *)&mask4, (struct sockaddr *)&gw4);
569272bd698SAlexander V. Chernikov 
570272bd698SAlexander V. Chernikov 	verify_route_message_extra(rtm, if_nametoindex(c->ifnames[1]),
5711b95005eSAlexander V. Chernikov 	    RTF_UP | RTF_DONE | RTF_GATEWAY | RTF_STATIC);
572272bd698SAlexander V. Chernikov 
573272bd698SAlexander V. Chernikov 	/* Verify the change has actually taken place */
574272bd698SAlexander V. Chernikov 	prepare_route_message(rtm, RTM_GET, (struct sockaddr *)&net4,
575272bd698SAlexander V. Chernikov 	    (struct sockaddr *)&mask4, NULL);
576272bd698SAlexander V. Chernikov 
577272bd698SAlexander V. Chernikov 	rtsock_send_rtm(c->rtsock_fd, rtm);
578272bd698SAlexander V. Chernikov 
579272bd698SAlexander V. Chernikov 	/*
580272bd698SAlexander V. Chernikov 	 * RTM_GET: len 200, pid: 3894, seq 44, errno 0, flags: <UP,GATEWAY,DONE,STATIC>
581272bd698SAlexander V. Chernikov 	 *  sockaddrs: 0x7 <DST,GATEWAY,NETMASK>
582272bd698SAlexander V. Chernikov  	 *  af=inet len=16 addr=192.0.2.0 hd={x10, x02, x00{2}, xC0, x00, x02, x00{9}}
583272bd698SAlexander V. Chernikov 	 *  af=inet len=16 addr=198.51.100.2 hd={x10, x02, x00{2}, xC6, x33, x64, x02, x00{8}}
584272bd698SAlexander V. Chernikov 	 *  af=inet len=16 addr=255.255.255.128 hd={x10, x02, xFF, xFF, xFF, xFF, xFF, x80, x00{8}}
585272bd698SAlexander V. Chernikov 	 */
586272bd698SAlexander V. Chernikov 
587272bd698SAlexander V. Chernikov 	rtm = rtsock_read_rtm_reply(c->rtsock_fd, buffer, sizeof(buffer), rtm->rtm_seq);
588272bd698SAlexander V. Chernikov 	verify_route_message_extra(rtm, if_nametoindex(c->ifnames[1]),
589272bd698SAlexander V. Chernikov 	    RTF_UP | RTF_DONE | RTF_GATEWAY | RTF_STATIC);
590272bd698SAlexander V. Chernikov 
591272bd698SAlexander V. Chernikov }
592272bd698SAlexander V. Chernikov 
593272bd698SAlexander V. Chernikov RTM_DECLARE_ROOT_TEST(rtm_change_v4_mtu_success,
594272bd698SAlexander V. Chernikov     "Tests IPv4 path mtu change");
595272bd698SAlexander V. Chernikov 
596272bd698SAlexander V. Chernikov ATF_TC_BODY(rtm_change_v4_mtu_success, tc)
597272bd698SAlexander V. Chernikov {
598272bd698SAlexander V. Chernikov 	DECLARE_TEST_VARS;
599272bd698SAlexander V. Chernikov 
600272bd698SAlexander V. Chernikov 	unsigned long test_mtu = 1442;
601272bd698SAlexander V. Chernikov 
602272bd698SAlexander V. Chernikov 	c = presetup_ipv4(tc);
603272bd698SAlexander V. Chernikov 
604272bd698SAlexander V. Chernikov 	/* Create IPv4 subnetwork with smaller prefix */
605272bd698SAlexander V. Chernikov 	struct sockaddr_in mask4;
606272bd698SAlexander V. Chernikov 	struct sockaddr_in net4;
607272bd698SAlexander V. Chernikov 	struct sockaddr_in gw4;
608272bd698SAlexander V. Chernikov 	prepare_v4_network(c, &net4, &mask4, &gw4);
609272bd698SAlexander V. Chernikov 
610272bd698SAlexander V. Chernikov 	prepare_route_message(rtm, RTM_ADD, (struct sockaddr *)&net4,
611272bd698SAlexander V. Chernikov 	    (struct sockaddr *)&mask4, (struct sockaddr *)&gw4);
612272bd698SAlexander V. Chernikov 
613272bd698SAlexander V. Chernikov 	rtsock_send_rtm(c->rtsock_fd, rtm);
614272bd698SAlexander V. Chernikov 	rtm = rtsock_read_rtm_reply(c->rtsock_fd, buffer, sizeof(buffer), rtm->rtm_seq);
615272bd698SAlexander V. Chernikov 
616272bd698SAlexander V. Chernikov 	/* Change MTU */
617272bd698SAlexander V. Chernikov 	prepare_route_message(rtm, RTM_CHANGE, (struct sockaddr *)&net4,
618272bd698SAlexander V. Chernikov 	    (struct sockaddr *)&mask4, NULL);
619272bd698SAlexander V. Chernikov 	rtm->rtm_inits |= RTV_MTU;
620272bd698SAlexander V. Chernikov 	rtm->rtm_rmx.rmx_mtu = test_mtu;
621272bd698SAlexander V. Chernikov 
622272bd698SAlexander V. Chernikov 	rtsock_send_rtm(c->rtsock_fd, rtm);
623272bd698SAlexander V. Chernikov 	rtm = rtsock_read_rtm_reply(c->rtsock_fd, buffer, sizeof(buffer), rtm->rtm_seq);
624272bd698SAlexander V. Chernikov 
625272bd698SAlexander V. Chernikov 	verify_route_message(rtm, RTM_CHANGE, (struct sockaddr *)&net4,
626272bd698SAlexander V. Chernikov 	    (struct sockaddr *)&mask4, NULL);
627272bd698SAlexander V. Chernikov 
628272bd698SAlexander V. Chernikov 	RTSOCK_ATF_REQUIRE_MSG(rtm, rtm->rtm_rmx.rmx_mtu == test_mtu,
629272bd698SAlexander V. Chernikov 	    "expected mtu: %lu, got %lu", test_mtu, rtm->rtm_rmx.rmx_mtu);
630272bd698SAlexander V. Chernikov 
631272bd698SAlexander V. Chernikov 	/* Verify the change has actually taken place */
632272bd698SAlexander V. Chernikov 	prepare_route_message(rtm, RTM_GET, (struct sockaddr *)&net4,
633272bd698SAlexander V. Chernikov 	    (struct sockaddr *)&mask4, NULL);
634272bd698SAlexander V. Chernikov 
635272bd698SAlexander V. Chernikov 	rtsock_send_rtm(c->rtsock_fd, rtm);
636272bd698SAlexander V. Chernikov 	rtm = rtsock_read_rtm_reply(c->rtsock_fd, buffer, sizeof(buffer), rtm->rtm_seq);
637272bd698SAlexander V. Chernikov 
638272bd698SAlexander V. Chernikov 	RTSOCK_ATF_REQUIRE_MSG(rtm, rtm->rtm_rmx.rmx_mtu == test_mtu,
639272bd698SAlexander V. Chernikov 	    "expected mtu: %lu, got %lu", test_mtu, rtm->rtm_rmx.rmx_mtu);
640272bd698SAlexander V. Chernikov }
641272bd698SAlexander V. Chernikov 
6421b95005eSAlexander V. Chernikov RTM_DECLARE_ROOT_TEST(rtm_change_v4_flags_success,
6431b95005eSAlexander V. Chernikov     "Tests IPv4 path flags change");
6441b95005eSAlexander V. Chernikov 
6451b95005eSAlexander V. Chernikov ATF_TC_BODY(rtm_change_v4_flags_success, tc)
6461b95005eSAlexander V. Chernikov {
6471b95005eSAlexander V. Chernikov 	DECLARE_TEST_VARS;
6481b95005eSAlexander V. Chernikov 
6491b95005eSAlexander V. Chernikov 	uint32_t test_flags = RTF_PROTO1 | RTF_PROTO2 | RTF_PROTO3 | RTF_STATIC;
6501b95005eSAlexander V. Chernikov 	uint32_t desired_flags;
6511b95005eSAlexander V. Chernikov 
6521b95005eSAlexander V. Chernikov 	c = presetup_ipv4(tc);
6531b95005eSAlexander V. Chernikov 
6541b95005eSAlexander V. Chernikov 	/* Create IPv4 subnetwork with smaller prefix */
6551b95005eSAlexander V. Chernikov 	struct sockaddr_in mask4;
6561b95005eSAlexander V. Chernikov 	struct sockaddr_in net4;
6571b95005eSAlexander V. Chernikov 	struct sockaddr_in gw4;
6581b95005eSAlexander V. Chernikov 	prepare_v4_network(c, &net4, &mask4, &gw4);
6591b95005eSAlexander V. Chernikov 
6601b95005eSAlexander V. Chernikov 	prepare_route_message(rtm, RTM_ADD, (struct sockaddr *)&net4,
6611b95005eSAlexander V. Chernikov 	    (struct sockaddr *)&mask4, (struct sockaddr *)&gw4);
6621b95005eSAlexander V. Chernikov 
6631b95005eSAlexander V. Chernikov 	/* Set test flags during route addition */
6641b95005eSAlexander V. Chernikov 	desired_flags = RTF_UP | RTF_DONE | RTF_GATEWAY | test_flags;
6651b95005eSAlexander V. Chernikov 	rtm->rtm_flags |= test_flags;
6661b95005eSAlexander V. Chernikov 	rtsock_send_rtm(c->rtsock_fd, rtm);
6671b95005eSAlexander V. Chernikov 	rtm = rtsock_read_rtm_reply(c->rtsock_fd, buffer, sizeof(buffer), rtm->rtm_seq);
6681b95005eSAlexander V. Chernikov 
6691b95005eSAlexander V. Chernikov 	/* Change flags */
6701b95005eSAlexander V. Chernikov 	prepare_route_message(rtm, RTM_CHANGE, (struct sockaddr *)&net4,
6711b95005eSAlexander V. Chernikov 	    (struct sockaddr *)&mask4, NULL);
6721b95005eSAlexander V. Chernikov 	rtm->rtm_flags &= ~test_flags;
6731b95005eSAlexander V. Chernikov 	desired_flags &= ~test_flags;
6741b95005eSAlexander V. Chernikov 
6751b95005eSAlexander V. Chernikov 	rtsock_send_rtm(c->rtsock_fd, rtm);
6761b95005eSAlexander V. Chernikov 	rtm = rtsock_read_rtm_reply(c->rtsock_fd, buffer, sizeof(buffer), rtm->rtm_seq);
6771b95005eSAlexander V. Chernikov 
6781b95005eSAlexander V. Chernikov 	/* Verify updated flags */
6791b95005eSAlexander V. Chernikov 	verify_route_message_extra(rtm, c->ifindex, desired_flags | RTF_DONE);
6801b95005eSAlexander V. Chernikov 
6811b95005eSAlexander V. Chernikov 	/* Verify the change has actually taken place */
6821b95005eSAlexander V. Chernikov 	prepare_route_message(rtm, RTM_GET, (struct sockaddr *)&net4,
6831b95005eSAlexander V. Chernikov 	    (struct sockaddr *)&mask4, NULL);
6841b95005eSAlexander V. Chernikov 
6851b95005eSAlexander V. Chernikov 	rtsock_send_rtm(c->rtsock_fd, rtm);
6861b95005eSAlexander V. Chernikov 	rtm = rtsock_read_rtm_reply(c->rtsock_fd, buffer, sizeof(buffer), rtm->rtm_seq);
6871b95005eSAlexander V. Chernikov 
6881b95005eSAlexander V. Chernikov 	verify_route_message_extra(rtm, c->ifindex, desired_flags | RTF_DONE);
6891b95005eSAlexander V. Chernikov }
6901b95005eSAlexander V. Chernikov 
691272bd698SAlexander V. Chernikov 
692775dc861SAlexander V. Chernikov ATF_TC_WITH_CLEANUP(rtm_add_v6_gu_gw_gu_direct_success);
693775dc861SAlexander V. Chernikov ATF_TC_HEAD(rtm_add_v6_gu_gw_gu_direct_success, tc)
694775dc861SAlexander V. Chernikov {
695775dc861SAlexander V. Chernikov 	DESCRIBE_ROOT_TEST("Tests IPv6 global unicast prefix addition with directly-reachable GU GW");
696775dc861SAlexander V. Chernikov }
697775dc861SAlexander V. Chernikov 
698775dc861SAlexander V. Chernikov ATF_TC_BODY(rtm_add_v6_gu_gw_gu_direct_success, tc)
699775dc861SAlexander V. Chernikov {
700775dc861SAlexander V. Chernikov 	DECLARE_TEST_VARS;
701775dc861SAlexander V. Chernikov 
702775dc861SAlexander V. Chernikov 	c = presetup_ipv6(tc);
703775dc861SAlexander V. Chernikov 
704775dc861SAlexander V. Chernikov 	/* Create IPv6 subnetwork with smaller prefix */
705775dc861SAlexander V. Chernikov 	struct sockaddr_in6 mask6;
706775dc861SAlexander V. Chernikov 	struct sockaddr_in6 net6;
707775dc861SAlexander V. Chernikov 	struct sockaddr_in6 gw6;
708775dc861SAlexander V. Chernikov 	prepare_v6_network(c, &net6, &mask6, &gw6);
709775dc861SAlexander V. Chernikov 
710775dc861SAlexander V. Chernikov 	prepare_route_message(rtm, RTM_ADD, (struct sockaddr *)&net6,
711775dc861SAlexander V. Chernikov 	    (struct sockaddr *)&mask6, (struct sockaddr *)&gw6);
712775dc861SAlexander V. Chernikov 
713775dc861SAlexander V. Chernikov 	rtsock_send_rtm(c->rtsock_fd, rtm);
714775dc861SAlexander V. Chernikov 	rtm = rtsock_read_rtm_reply(c->rtsock_fd, buffer, sizeof(buffer), rtm->rtm_seq);
715775dc861SAlexander V. Chernikov 
716775dc861SAlexander V. Chernikov 	/*
717775dc861SAlexander V. Chernikov 	 * RTM_ADD: Add Route: len 200, pid: 46068, seq 42, errno 0, flags:<GATEWAY,DONE,STATIC>
718775dc861SAlexander V. Chernikov 	 * locks:  inits:
719775dc861SAlexander V. Chernikov 	 * sockaddrs: <DST,GATEWAY,NETMASK>
720775dc861SAlexander V. Chernikov 	 *  192.0.2.0 192.0.2.254 255.255.255.128
721775dc861SAlexander V. Chernikov 	 */
722775dc861SAlexander V. Chernikov 
723775dc861SAlexander V. Chernikov 	verify_route_message(rtm, RTM_ADD, (struct sockaddr *)&net6,
724775dc861SAlexander V. Chernikov 	    (struct sockaddr *)&mask6, (struct sockaddr *)&gw6);
725775dc861SAlexander V. Chernikov 
7261b95005eSAlexander V. Chernikov 	verify_route_message_extra(rtm, c->ifindex,
7271b95005eSAlexander V. Chernikov 	    RTF_UP | RTF_DONE | RTF_GATEWAY | RTF_STATIC);
728775dc861SAlexander V. Chernikov }
729775dc861SAlexander V. Chernikov 
730775dc861SAlexander V. Chernikov ATF_TC_CLEANUP(rtm_add_v6_gu_gw_gu_direct_success, tc)
731775dc861SAlexander V. Chernikov {
732775dc861SAlexander V. Chernikov 	CLEANUP_AFTER_TEST;
733775dc861SAlexander V. Chernikov }
734775dc861SAlexander V. Chernikov 
735775dc861SAlexander V. Chernikov ATF_TC_WITH_CLEANUP(rtm_del_v6_gu_prefix_nogw_success);
736775dc861SAlexander V. Chernikov ATF_TC_HEAD(rtm_del_v6_gu_prefix_nogw_success, tc)
737775dc861SAlexander V. Chernikov {
738775dc861SAlexander V. Chernikov 
739775dc861SAlexander V. Chernikov 	DESCRIBE_ROOT_TEST("Tests IPv6 global unicast prefix removal without specifying gateway");
740775dc861SAlexander V. Chernikov }
741775dc861SAlexander V. Chernikov 
742775dc861SAlexander V. Chernikov ATF_TC_BODY(rtm_del_v6_gu_prefix_nogw_success, tc)
743775dc861SAlexander V. Chernikov {
744775dc861SAlexander V. Chernikov 	DECLARE_TEST_VARS;
745775dc861SAlexander V. Chernikov 
746775dc861SAlexander V. Chernikov 	c = presetup_ipv6(tc);
747775dc861SAlexander V. Chernikov 
748775dc861SAlexander V. Chernikov 	/* Create IPv6 subnetwork with smaller prefix */
749775dc861SAlexander V. Chernikov 	struct sockaddr_in6 mask6;
750775dc861SAlexander V. Chernikov 	struct sockaddr_in6 net6;
751775dc861SAlexander V. Chernikov 	struct sockaddr_in6 gw6;
752775dc861SAlexander V. Chernikov 	prepare_v6_network(c, &net6, &mask6, &gw6);
753775dc861SAlexander V. Chernikov 
754775dc861SAlexander V. Chernikov 	prepare_route_message(rtm, RTM_ADD, (struct sockaddr *)&net6,
755775dc861SAlexander V. Chernikov 	    (struct sockaddr *)&mask6, (struct sockaddr *)&gw6);
756775dc861SAlexander V. Chernikov 
757775dc861SAlexander V. Chernikov 	rtsock_send_rtm(c->rtsock_fd, rtm);
758775dc861SAlexander V. Chernikov 
759775dc861SAlexander V. Chernikov 	/* Route has been added successfully, try to delete it */
760775dc861SAlexander V. Chernikov 	prepare_route_message(rtm, RTM_DELETE, (struct sockaddr *)&net6,
761775dc861SAlexander V. Chernikov 	    (struct sockaddr *)&mask6, NULL);
762775dc861SAlexander V. Chernikov 
763775dc861SAlexander V. Chernikov 	rtsock_send_rtm(c->rtsock_fd, rtm);
764775dc861SAlexander V. Chernikov 	rtm = rtsock_read_rtm_reply(c->rtsock_fd, buffer, sizeof(buffer), rtm->rtm_seq);
765775dc861SAlexander V. Chernikov 
766775dc861SAlexander V. Chernikov 	/*
767775dc861SAlexander V. Chernikov 	 * RTM_DELETE: Delete Route: len 200, pid: 46417, seq 43, errno 0, flags: <GATEWAY,DONE,STATIC>
768775dc861SAlexander V. Chernikov 	 * sockaddrs: 0x7 <DST,GATEWAY,NETMASK>
769775dc861SAlexander V. Chernikov 	 *  af=inet len=16 addr=192.0.2.0 hd={10, 02, 00{2}, C0, 00, 02, 00{9}}
770775dc861SAlexander V. Chernikov 	 *  af=inet len=16 addr=192.0.2.254 hd={10, 02, 00{2}, C0, 00, 02, FE, 00{8}}
771775dc861SAlexander V. Chernikov 	 *  af=inet len=16 addr=255.255.255.128 hd={10, 02, FF{5}, 80, 00{8}}
772775dc861SAlexander V. Chernikov 	 */
773775dc861SAlexander V. Chernikov 
774775dc861SAlexander V. Chernikov 	verify_route_message(rtm, RTM_DELETE, (struct sockaddr *)&net6,
775775dc861SAlexander V. Chernikov 	    (struct sockaddr *)&mask6, (struct sockaddr *)&gw6);
776775dc861SAlexander V. Chernikov 	verify_route_message_extra(rtm, c->ifindex, RTF_DONE | RTF_GATEWAY | RTF_STATIC);
777775dc861SAlexander V. Chernikov }
778775dc861SAlexander V. Chernikov 
779775dc861SAlexander V. Chernikov ATF_TC_CLEANUP(rtm_del_v6_gu_prefix_nogw_success, tc)
780775dc861SAlexander V. Chernikov {
781775dc861SAlexander V. Chernikov 	CLEANUP_AFTER_TEST;
782775dc861SAlexander V. Chernikov }
783775dc861SAlexander V. Chernikov 
784272bd698SAlexander V. Chernikov RTM_DECLARE_ROOT_TEST(rtm_change_v6_gw_success,
785272bd698SAlexander V. Chernikov     "Tests IPv6 gateway change");
786272bd698SAlexander V. Chernikov 
787272bd698SAlexander V. Chernikov ATF_TC_BODY(rtm_change_v6_gw_success, tc)
788272bd698SAlexander V. Chernikov {
789272bd698SAlexander V. Chernikov 	DECLARE_TEST_VARS;
790272bd698SAlexander V. Chernikov 	struct rtsock_config_options co;
791272bd698SAlexander V. Chernikov 
792272bd698SAlexander V. Chernikov 	bzero(&co, sizeof(co));
793272bd698SAlexander V. Chernikov 	co.num_interfaces = 2;
794272bd698SAlexander V. Chernikov 
795272bd698SAlexander V. Chernikov 	c = config_setup(tc, &co);
796272bd698SAlexander V. Chernikov 	jump_vnet(c, tc);
797272bd698SAlexander V. Chernikov 
798272bd698SAlexander V. Chernikov 	ret = iface_turn_up(c->ifnames[0]);
799272bd698SAlexander V. Chernikov 	ATF_REQUIRE_MSG(ret == 0, "Unable to turn up %s", c->ifnames[0]);
800272bd698SAlexander V. Chernikov 	ret = iface_turn_up(c->ifnames[1]);
801272bd698SAlexander V. Chernikov 	ATF_REQUIRE_MSG(ret == 0, "Unable to turn up %s", c->ifnames[1]);
802272bd698SAlexander V. Chernikov 
803272bd698SAlexander V. Chernikov 	ret = iface_enable_ipv6(c->ifnames[0]);
804272bd698SAlexander V. Chernikov 	ATF_REQUIRE_MSG(ret == 0, "Unable to enable IPv6 on %s", c->ifnames[0]);
805272bd698SAlexander V. Chernikov 	ret = iface_enable_ipv6(c->ifnames[1]);
806272bd698SAlexander V. Chernikov 	ATF_REQUIRE_MSG(ret == 0, "Unable to enable IPv6 on %s", c->ifnames[1]);
807272bd698SAlexander V. Chernikov 
808272bd698SAlexander V. Chernikov 	ret = iface_setup_addr(c->ifnames[0], c->addr6_str, c->plen6);
809272bd698SAlexander V. Chernikov 	ATF_REQUIRE_MSG(ret == 0, "ifconfig failed");
810272bd698SAlexander V. Chernikov 
811272bd698SAlexander V. Chernikov 	ret = iface_setup_addr(c->ifnames[1], "2001:DB8:4242::1", 64);
812272bd698SAlexander V. Chernikov 	ATF_REQUIRE_MSG(ret == 0, "ifconfig failed");
813272bd698SAlexander V. Chernikov 
814272bd698SAlexander V. Chernikov 	c->rtsock_fd = rtsock_setup_socket();
815272bd698SAlexander V. Chernikov 
816272bd698SAlexander V. Chernikov 	/* Create IPv6 subnetwork with smaller prefix */
817272bd698SAlexander V. Chernikov 	struct sockaddr_in6 mask6;
818272bd698SAlexander V. Chernikov 	struct sockaddr_in6 net6;
819272bd698SAlexander V. Chernikov 	struct sockaddr_in6 gw6;
820272bd698SAlexander V. Chernikov 	prepare_v6_network(c, &net6, &mask6, &gw6);
821272bd698SAlexander V. Chernikov 
822272bd698SAlexander V. Chernikov 	prepare_route_message(rtm, RTM_ADD, (struct sockaddr *)&net6,
823272bd698SAlexander V. Chernikov 	    (struct sockaddr *)&mask6, (struct sockaddr *)&gw6);
824272bd698SAlexander V. Chernikov 
825272bd698SAlexander V. Chernikov 	rtsock_send_rtm(c->rtsock_fd, rtm);
826272bd698SAlexander V. Chernikov 	rtm = rtsock_read_rtm_reply(c->rtsock_fd, buffer, sizeof(buffer), rtm->rtm_seq);
827272bd698SAlexander V. Chernikov 
828272bd698SAlexander V. Chernikov 	verify_route_message(rtm, RTM_ADD, (struct sockaddr *)&net6,
829272bd698SAlexander V. Chernikov 	    (struct sockaddr *)&mask6, (struct sockaddr *)&gw6);
830272bd698SAlexander V. Chernikov 
831272bd698SAlexander V. Chernikov 	/* Change gateway to the one on residing on the other interface */
832272bd698SAlexander V. Chernikov 	inet_pton(AF_INET6, "2001:DB8:4242::4242", &gw6.sin6_addr);
833272bd698SAlexander V. Chernikov 	prepare_route_message(rtm, RTM_CHANGE, (struct sockaddr *)&net6,
834272bd698SAlexander V. Chernikov 	    (struct sockaddr *)&mask6, (struct sockaddr *)&gw6);
835272bd698SAlexander V. Chernikov 	rtsock_send_rtm(c->rtsock_fd, rtm);
836272bd698SAlexander V. Chernikov 
837272bd698SAlexander V. Chernikov 	rtm = rtsock_read_rtm_reply(c->rtsock_fd, buffer, sizeof(buffer), rtm->rtm_seq);
838272bd698SAlexander V. Chernikov 
839272bd698SAlexander V. Chernikov 	verify_route_message(rtm, RTM_CHANGE, (struct sockaddr *)&net6,
840272bd698SAlexander V. Chernikov 	    (struct sockaddr *)&mask6, (struct sockaddr *)&gw6);
841272bd698SAlexander V. Chernikov 
842272bd698SAlexander V. Chernikov 	verify_route_message_extra(rtm, if_nametoindex(c->ifnames[1]),
8431b95005eSAlexander V. Chernikov 	    RTF_UP | RTF_DONE | RTF_GATEWAY | RTF_STATIC);
844272bd698SAlexander V. Chernikov 
845272bd698SAlexander V. Chernikov 	/* Verify the change has actually taken place */
846272bd698SAlexander V. Chernikov 	prepare_route_message(rtm, RTM_GET, (struct sockaddr *)&net6,
847272bd698SAlexander V. Chernikov 	    (struct sockaddr *)&mask6, NULL);
848272bd698SAlexander V. Chernikov 
849272bd698SAlexander V. Chernikov 	rtsock_send_rtm(c->rtsock_fd, rtm);
850272bd698SAlexander V. Chernikov 
851272bd698SAlexander V. Chernikov 	/*
852272bd698SAlexander V. Chernikov 	 * RTM_GET: len 248, pid: 2268, seq 44, errno 0, flags: <UP,GATEWAY,DONE,STATIC>
853272bd698SAlexander V. Chernikov 	 *  sockaddrs: 0x7 <DST,GATEWAY,NETMASK>
854272bd698SAlexander V. Chernikov 	 *  af=inet6 len=28 addr=2001:db8:: hd={x1C, x1C, x00{6}, x20, x01, x0D, xB8, x00{16}}
855272bd698SAlexander V. Chernikov 	 *  af=inet6 len=28 addr=2001:db8:4242::4242 hd={x1C, x1C, x00{6}, x20, x01, x0D, xB8, x42, x42, x00{8}, x42, x42, x00{4}}
856272bd698SAlexander V. Chernikov 	 *  af=inet6 len=28 addr=ffff:ffff:8000:: hd={x1C, x1C, xFF, xFF, xFF, xFF, xFF, xFF, xFF, xFF, xFF, xFF, x80, x00{15}}
857272bd698SAlexander V. Chernikov 	 */
858272bd698SAlexander V. Chernikov 
859272bd698SAlexander V. Chernikov 	rtm = rtsock_read_rtm_reply(c->rtsock_fd, buffer, sizeof(buffer), rtm->rtm_seq);
860272bd698SAlexander V. Chernikov 	verify_route_message_extra(rtm, if_nametoindex(c->ifnames[1]),
861272bd698SAlexander V. Chernikov 	    RTF_UP | RTF_DONE | RTF_GATEWAY | RTF_STATIC);
862272bd698SAlexander V. Chernikov }
863272bd698SAlexander V. Chernikov 
864272bd698SAlexander V. Chernikov RTM_DECLARE_ROOT_TEST(rtm_change_v6_mtu_success,
865272bd698SAlexander V. Chernikov     "Tests IPv6 path mtu change");
866272bd698SAlexander V. Chernikov 
867272bd698SAlexander V. Chernikov ATF_TC_BODY(rtm_change_v6_mtu_success, tc)
868272bd698SAlexander V. Chernikov {
869272bd698SAlexander V. Chernikov 	DECLARE_TEST_VARS;
870272bd698SAlexander V. Chernikov 
871272bd698SAlexander V. Chernikov 	unsigned long test_mtu = 1442;
872272bd698SAlexander V. Chernikov 
873272bd698SAlexander V. Chernikov 	c = presetup_ipv6(tc);
874272bd698SAlexander V. Chernikov 
875272bd698SAlexander V. Chernikov 	/* Create IPv6 subnetwork with smaller prefix */
876272bd698SAlexander V. Chernikov 	struct sockaddr_in6 mask6;
877272bd698SAlexander V. Chernikov 	struct sockaddr_in6 net6;
878272bd698SAlexander V. Chernikov 	struct sockaddr_in6 gw6;
879272bd698SAlexander V. Chernikov 	prepare_v6_network(c, &net6, &mask6, &gw6);
880272bd698SAlexander V. Chernikov 
881272bd698SAlexander V. Chernikov 	prepare_route_message(rtm, RTM_ADD, (struct sockaddr *)&net6,
882272bd698SAlexander V. Chernikov 	    (struct sockaddr *)&mask6, (struct sockaddr *)&gw6);
883272bd698SAlexander V. Chernikov 
884272bd698SAlexander V. Chernikov 	/* Send route add */
885272bd698SAlexander V. Chernikov 	rtsock_send_rtm(c->rtsock_fd, rtm);
886272bd698SAlexander V. Chernikov 	rtm = rtsock_read_rtm_reply(c->rtsock_fd, buffer, sizeof(buffer), rtm->rtm_seq);
887272bd698SAlexander V. Chernikov 
888272bd698SAlexander V. Chernikov 	/* Change MTU */
889272bd698SAlexander V. Chernikov 	prepare_route_message(rtm, RTM_CHANGE, (struct sockaddr *)&net6,
890272bd698SAlexander V. Chernikov 	    (struct sockaddr *)&mask6, NULL);
891272bd698SAlexander V. Chernikov 	rtm->rtm_inits |= RTV_MTU;
892272bd698SAlexander V. Chernikov 	rtm->rtm_rmx.rmx_mtu = test_mtu;
893272bd698SAlexander V. Chernikov 
894272bd698SAlexander V. Chernikov 	rtsock_send_rtm(c->rtsock_fd, rtm);
895272bd698SAlexander V. Chernikov 	rtm = rtsock_read_rtm_reply(c->rtsock_fd, buffer, sizeof(buffer), rtm->rtm_seq);
896272bd698SAlexander V. Chernikov 
897272bd698SAlexander V. Chernikov 	verify_route_message(rtm, RTM_CHANGE, (struct sockaddr *)&net6,
898272bd698SAlexander V. Chernikov 	    (struct sockaddr *)&mask6, NULL);
899272bd698SAlexander V. Chernikov 
900272bd698SAlexander V. Chernikov 	RTSOCK_ATF_REQUIRE_MSG(rtm, rtm->rtm_rmx.rmx_mtu == test_mtu,
901272bd698SAlexander V. Chernikov 	    "expected mtu: %lu, got %lu", test_mtu, rtm->rtm_rmx.rmx_mtu);
902272bd698SAlexander V. Chernikov 
903272bd698SAlexander V. Chernikov 	/* Verify the change has actually taken place */
904272bd698SAlexander V. Chernikov 	prepare_route_message(rtm, RTM_GET, (struct sockaddr *)&net6,
905272bd698SAlexander V. Chernikov 	    (struct sockaddr *)&mask6, NULL);
906272bd698SAlexander V. Chernikov 
907272bd698SAlexander V. Chernikov 	rtsock_send_rtm(c->rtsock_fd, rtm);
908272bd698SAlexander V. Chernikov 	rtm = rtsock_read_rtm_reply(c->rtsock_fd, buffer, sizeof(buffer), rtm->rtm_seq);
909272bd698SAlexander V. Chernikov 
910272bd698SAlexander V. Chernikov 	RTSOCK_ATF_REQUIRE_MSG(rtm, rtm->rtm_rmx.rmx_mtu == test_mtu,
911272bd698SAlexander V. Chernikov 	    "expected mtu: %lu, got %lu", test_mtu, rtm->rtm_rmx.rmx_mtu);
912272bd698SAlexander V. Chernikov }
913272bd698SAlexander V. Chernikov 
9141b95005eSAlexander V. Chernikov RTM_DECLARE_ROOT_TEST(rtm_change_v6_flags_success,
9151b95005eSAlexander V. Chernikov     "Tests IPv6 path flags change");
9161b95005eSAlexander V. Chernikov 
9171b95005eSAlexander V. Chernikov ATF_TC_BODY(rtm_change_v6_flags_success, tc)
9181b95005eSAlexander V. Chernikov {
9191b95005eSAlexander V. Chernikov 	DECLARE_TEST_VARS;
9201b95005eSAlexander V. Chernikov 
9211b95005eSAlexander V. Chernikov 	uint32_t test_flags = RTF_PROTO1 | RTF_PROTO2 | RTF_PROTO3 | RTF_STATIC;
9221b95005eSAlexander V. Chernikov 	uint32_t desired_flags;
9231b95005eSAlexander V. Chernikov 
9241b95005eSAlexander V. Chernikov 	c = presetup_ipv6(tc);
9251b95005eSAlexander V. Chernikov 
9261b95005eSAlexander V. Chernikov 	/* Create IPv6 subnetwork with smaller prefix */
9271b95005eSAlexander V. Chernikov 	struct sockaddr_in6 mask6;
9281b95005eSAlexander V. Chernikov 	struct sockaddr_in6 net6;
9291b95005eSAlexander V. Chernikov 	struct sockaddr_in6 gw6;
9301b95005eSAlexander V. Chernikov 	prepare_v6_network(c, &net6, &mask6, &gw6);
9311b95005eSAlexander V. Chernikov 
9321b95005eSAlexander V. Chernikov 	prepare_route_message(rtm, RTM_ADD, (struct sockaddr *)&net6,
9331b95005eSAlexander V. Chernikov 	    (struct sockaddr *)&mask6, (struct sockaddr *)&gw6);
9341b95005eSAlexander V. Chernikov 
9351b95005eSAlexander V. Chernikov 	/* Set test flags during route addition */
9361b95005eSAlexander V. Chernikov 	desired_flags = RTF_UP | RTF_DONE | RTF_GATEWAY | test_flags;
9371b95005eSAlexander V. Chernikov 	rtm->rtm_flags |= test_flags;
9381b95005eSAlexander V. Chernikov 	rtsock_send_rtm(c->rtsock_fd, rtm);
9391b95005eSAlexander V. Chernikov 	rtm = rtsock_read_rtm_reply(c->rtsock_fd, buffer, sizeof(buffer), rtm->rtm_seq);
9401b95005eSAlexander V. Chernikov 
9411b95005eSAlexander V. Chernikov 	/* Change flags */
9421b95005eSAlexander V. Chernikov 	prepare_route_message(rtm, RTM_CHANGE, (struct sockaddr *)&net6,
9431b95005eSAlexander V. Chernikov 	    (struct sockaddr *)&mask6, NULL);
9441b95005eSAlexander V. Chernikov 	rtm->rtm_flags &= ~test_flags;
9451b95005eSAlexander V. Chernikov 	desired_flags &= ~test_flags;
9461b95005eSAlexander V. Chernikov 
9471b95005eSAlexander V. Chernikov 	rtsock_send_rtm(c->rtsock_fd, rtm);
9481b95005eSAlexander V. Chernikov 	rtm = rtsock_read_rtm_reply(c->rtsock_fd, buffer, sizeof(buffer), rtm->rtm_seq);
9491b95005eSAlexander V. Chernikov 
9501b95005eSAlexander V. Chernikov 	/* Verify updated flags */
9511b95005eSAlexander V. Chernikov 	verify_route_message_extra(rtm, c->ifindex, desired_flags | RTF_DONE);
9521b95005eSAlexander V. Chernikov 
9531b95005eSAlexander V. Chernikov 	/* Verify the change has actually taken place */
9541b95005eSAlexander V. Chernikov 	prepare_route_message(rtm, RTM_GET, (struct sockaddr *)&net6,
9551b95005eSAlexander V. Chernikov 	    (struct sockaddr *)&mask6, NULL);
9561b95005eSAlexander V. Chernikov 
9571b95005eSAlexander V. Chernikov 	rtsock_send_rtm(c->rtsock_fd, rtm);
9581b95005eSAlexander V. Chernikov 	rtm = rtsock_read_rtm_reply(c->rtsock_fd, buffer, sizeof(buffer), rtm->rtm_seq);
9591b95005eSAlexander V. Chernikov 
9601b95005eSAlexander V. Chernikov 	verify_route_message_extra(rtm, c->ifindex, desired_flags | RTF_DONE);
9611b95005eSAlexander V. Chernikov }
9621b95005eSAlexander V. Chernikov 
963e02d3fe7SAlexander V. Chernikov ATF_TC_WITH_CLEANUP(rtm_add_v4_temporal1_success);
964e02d3fe7SAlexander V. Chernikov ATF_TC_HEAD(rtm_add_v4_temporal1_success, tc)
965e02d3fe7SAlexander V. Chernikov {
966e02d3fe7SAlexander V. Chernikov 	DESCRIBE_ROOT_TEST("Tests IPv4 route expiration with expire time set");
967e02d3fe7SAlexander V. Chernikov }
968e02d3fe7SAlexander V. Chernikov 
969e02d3fe7SAlexander V. Chernikov ATF_TC_BODY(rtm_add_v4_temporal1_success, tc)
970e02d3fe7SAlexander V. Chernikov {
971e02d3fe7SAlexander V. Chernikov 	DECLARE_TEST_VARS;
972e02d3fe7SAlexander V. Chernikov 
973e02d3fe7SAlexander V. Chernikov 	c = presetup_ipv4(tc);
974e02d3fe7SAlexander V. Chernikov 
975e02d3fe7SAlexander V. Chernikov 	/* Create IPv4 subnetwork with smaller prefix */
976e02d3fe7SAlexander V. Chernikov 	struct sockaddr_in mask4;
977e02d3fe7SAlexander V. Chernikov 	struct sockaddr_in net4;
978e02d3fe7SAlexander V. Chernikov 	struct sockaddr_in gw4;
979e02d3fe7SAlexander V. Chernikov 	prepare_v4_network(c, &net4, &mask4, &gw4);
980e02d3fe7SAlexander V. Chernikov 
981e02d3fe7SAlexander V. Chernikov 	prepare_route_message(rtm, RTM_ADD, (struct sockaddr *)&net4,
982e02d3fe7SAlexander V. Chernikov 	    (struct sockaddr *)&mask4, (struct sockaddr *)&gw4);
983e02d3fe7SAlexander V. Chernikov 
984e02d3fe7SAlexander V. Chernikov 	/* Set expire time to now */
985e02d3fe7SAlexander V. Chernikov 	struct timeval tv;
986e02d3fe7SAlexander V. Chernikov 	gettimeofday(&tv, NULL);
987e02d3fe7SAlexander V. Chernikov 	rtm->rtm_rmx.rmx_expire = tv.tv_sec - 1;
988e02d3fe7SAlexander V. Chernikov 	rtm->rtm_inits |= RTV_EXPIRE;
989e02d3fe7SAlexander V. Chernikov 
990e02d3fe7SAlexander V. Chernikov 	rtsock_send_rtm(c->rtsock_fd, rtm);
991e02d3fe7SAlexander V. Chernikov 	rtm = rtsock_read_rtm_reply(c->rtsock_fd, buffer, sizeof(buffer), rtm->rtm_seq);
992e02d3fe7SAlexander V. Chernikov 	ATF_REQUIRE_MSG(rtm != NULL, "unable to get rtsock reply for RTM_ADD");
993e02d3fe7SAlexander V. Chernikov 	RTSOCK_ATF_REQUIRE_MSG(rtm, rtm->rtm_inits & RTV_EXPIRE, "RTV_EXPIRE not set");
994e02d3fe7SAlexander V. Chernikov 
995e02d3fe7SAlexander V. Chernikov 	/* The next should be route deletion */
996e02d3fe7SAlexander V. Chernikov 	rtm = rtsock_read_rtm(c->rtsock_fd, buffer, sizeof(buffer));
997e02d3fe7SAlexander V. Chernikov 
998e02d3fe7SAlexander V. Chernikov 	verify_route_message(rtm, RTM_DELETE, (struct sockaddr *)&net4,
999e02d3fe7SAlexander V. Chernikov 	    (struct sockaddr *)&mask4, (struct sockaddr *)&gw4);
1000e02d3fe7SAlexander V. Chernikov 
10011b95005eSAlexander V. Chernikov 	verify_route_message_extra(rtm, c->ifindex,
10021b95005eSAlexander V. Chernikov 	    RTF_DONE | RTF_GATEWAY | RTF_STATIC);
1003e02d3fe7SAlexander V. Chernikov }
1004e02d3fe7SAlexander V. Chernikov 
1005e02d3fe7SAlexander V. Chernikov ATF_TC_CLEANUP(rtm_add_v4_temporal1_success, tc)
1006e02d3fe7SAlexander V. Chernikov {
1007e02d3fe7SAlexander V. Chernikov 	CLEANUP_AFTER_TEST;
1008e02d3fe7SAlexander V. Chernikov }
1009e02d3fe7SAlexander V. Chernikov 
1010e02d3fe7SAlexander V. Chernikov ATF_TC_WITH_CLEANUP(rtm_add_v6_temporal1_success);
1011e02d3fe7SAlexander V. Chernikov ATF_TC_HEAD(rtm_add_v6_temporal1_success, tc)
1012e02d3fe7SAlexander V. Chernikov {
1013e02d3fe7SAlexander V. Chernikov 	DESCRIBE_ROOT_TEST("Tests IPv6 global unicast prefix addition with directly-reachable GU GW");
1014e02d3fe7SAlexander V. Chernikov }
1015e02d3fe7SAlexander V. Chernikov 
1016e02d3fe7SAlexander V. Chernikov ATF_TC_BODY(rtm_add_v6_temporal1_success, tc)
1017e02d3fe7SAlexander V. Chernikov {
1018e02d3fe7SAlexander V. Chernikov 	DECLARE_TEST_VARS;
1019e02d3fe7SAlexander V. Chernikov 
1020e02d3fe7SAlexander V. Chernikov 	c = presetup_ipv6(tc);
1021e02d3fe7SAlexander V. Chernikov 
1022e02d3fe7SAlexander V. Chernikov 	/* Create IPv6 subnetwork with smaller prefix */
1023e02d3fe7SAlexander V. Chernikov 	struct sockaddr_in6 mask6;
1024e02d3fe7SAlexander V. Chernikov 	struct sockaddr_in6 net6;
1025e02d3fe7SAlexander V. Chernikov 	struct sockaddr_in6 gw6;
1026e02d3fe7SAlexander V. Chernikov 	prepare_v6_network(c, &net6, &mask6, &gw6);
1027e02d3fe7SAlexander V. Chernikov 
1028e02d3fe7SAlexander V. Chernikov 	prepare_route_message(rtm, RTM_ADD, (struct sockaddr *)&net6,
1029e02d3fe7SAlexander V. Chernikov 	    (struct sockaddr *)&mask6, (struct sockaddr *)&gw6);
1030e02d3fe7SAlexander V. Chernikov 
1031e02d3fe7SAlexander V. Chernikov 	/* Set expire time to now */
1032e02d3fe7SAlexander V. Chernikov 	struct timeval tv;
1033e02d3fe7SAlexander V. Chernikov 	gettimeofday(&tv, NULL);
1034e02d3fe7SAlexander V. Chernikov 	rtm->rtm_rmx.rmx_expire = tv.tv_sec - 1;
1035e02d3fe7SAlexander V. Chernikov 	rtm->rtm_inits |= RTV_EXPIRE;
1036e02d3fe7SAlexander V. Chernikov 
1037e02d3fe7SAlexander V. Chernikov 	rtsock_send_rtm(c->rtsock_fd, rtm);
1038e02d3fe7SAlexander V. Chernikov 	rtm = rtsock_read_rtm_reply(c->rtsock_fd, buffer, sizeof(buffer), rtm->rtm_seq);
1039e02d3fe7SAlexander V. Chernikov 	ATF_REQUIRE_MSG(rtm != NULL, "unable to get rtsock reply for RTM_ADD");
1040e02d3fe7SAlexander V. Chernikov 	RTSOCK_ATF_REQUIRE_MSG(rtm, rtm->rtm_inits & RTV_EXPIRE, "RTV_EXPIRE not set");
1041e02d3fe7SAlexander V. Chernikov 
1042e02d3fe7SAlexander V. Chernikov 	/* The next should be route deletion */
1043e02d3fe7SAlexander V. Chernikov 	rtm = rtsock_read_rtm(c->rtsock_fd, buffer, sizeof(buffer));
1044e02d3fe7SAlexander V. Chernikov 
1045e02d3fe7SAlexander V. Chernikov 	verify_route_message(rtm, RTM_DELETE, (struct sockaddr *)&net6,
1046e02d3fe7SAlexander V. Chernikov 	    (struct sockaddr *)&mask6, (struct sockaddr *)&gw6);
1047e02d3fe7SAlexander V. Chernikov 
10481b95005eSAlexander V. Chernikov 	verify_route_message_extra(rtm, c->ifindex,
10491b95005eSAlexander V. Chernikov 	    RTF_DONE | RTF_GATEWAY | RTF_STATIC);
1050e02d3fe7SAlexander V. Chernikov }
1051e02d3fe7SAlexander V. Chernikov 
1052e02d3fe7SAlexander V. Chernikov ATF_TC_CLEANUP(rtm_add_v6_temporal1_success, tc)
1053e02d3fe7SAlexander V. Chernikov {
1054e02d3fe7SAlexander V. Chernikov 	CLEANUP_AFTER_TEST;
1055e02d3fe7SAlexander V. Chernikov }
1056e02d3fe7SAlexander V. Chernikov 
1057e02d3fe7SAlexander V. Chernikov /* Interface address messages tests */
1058e02d3fe7SAlexander V. Chernikov 
1059e02d3fe7SAlexander V. Chernikov RTM_DECLARE_ROOT_TEST(rtm_add_v6_gu_ifa_hostroute_success,
1060e02d3fe7SAlexander V. Chernikov     "Tests validness for /128 host route announce after ifaddr assignment");
1061e02d3fe7SAlexander V. Chernikov 
1062e02d3fe7SAlexander V. Chernikov ATF_TC_BODY(rtm_add_v6_gu_ifa_hostroute_success, tc)
1063e02d3fe7SAlexander V. Chernikov {
1064e02d3fe7SAlexander V. Chernikov 	DECLARE_TEST_VARS;
1065e02d3fe7SAlexander V. Chernikov 
1066e02d3fe7SAlexander V. Chernikov 	c = presetup_ipv6_iface(tc);
1067e02d3fe7SAlexander V. Chernikov 
1068e02d3fe7SAlexander V. Chernikov 	c->rtsock_fd = rtsock_setup_socket();
1069e02d3fe7SAlexander V. Chernikov 
1070e02d3fe7SAlexander V. Chernikov 	ret = iface_setup_addr(c->ifname, c->addr6_str, c->plen6);
1071e02d3fe7SAlexander V. Chernikov 
1072e02d3fe7SAlexander V. Chernikov 	/*
1073e02d3fe7SAlexander V. Chernikov 	 * There will be multiple.
1074e02d3fe7SAlexander V. Chernikov 	 * RTM_ADD without llinfo.
1075e02d3fe7SAlexander V. Chernikov 	 */
1076e02d3fe7SAlexander V. Chernikov 
1077e02d3fe7SAlexander V. Chernikov 	while (true) {
1078e02d3fe7SAlexander V. Chernikov 		rtm = rtsock_read_rtm(c->rtsock_fd, buffer, sizeof(buffer));
1079e02d3fe7SAlexander V. Chernikov 		if ((rtm->rtm_type == RTM_ADD) && ((rtm->rtm_flags & RTF_LLINFO) == 0))
1080e02d3fe7SAlexander V. Chernikov 			break;
1081e02d3fe7SAlexander V. Chernikov 	}
1082e02d3fe7SAlexander V. Chernikov 	/* This should be a message for the host route */
1083e02d3fe7SAlexander V. Chernikov 
1084e02d3fe7SAlexander V. Chernikov 	verify_route_message(rtm, RTM_ADD, (struct sockaddr *)&c->addr6, NULL, NULL);
1085e02d3fe7SAlexander V. Chernikov 	rtsock_validate_pid_kernel(rtm);
1086e02d3fe7SAlexander V. Chernikov 	/* No netmask should be set */
1087e02d3fe7SAlexander V. Chernikov 	RTSOCK_ATF_REQUIRE_MSG(rtm, rtsock_find_rtm_sa(rtm, RTA_NETMASK) == NULL, "netmask is set");
1088e02d3fe7SAlexander V. Chernikov 
1089e02d3fe7SAlexander V. Chernikov 	/* gateway should be link sdl with ifindex of an address interface */
1090e02d3fe7SAlexander V. Chernikov 	verify_link_gateway(rtm, c->ifindex);
1091e02d3fe7SAlexander V. Chernikov 
1092e02d3fe7SAlexander V. Chernikov 	int expected_rt_flags = RTF_UP | RTF_HOST | RTF_DONE | RTF_STATIC | RTF_PINNED;
1093e02d3fe7SAlexander V. Chernikov 	verify_route_message_extra(rtm, if_nametoindex("lo0"), expected_rt_flags);
1094e02d3fe7SAlexander V. Chernikov }
1095e02d3fe7SAlexander V. Chernikov 
1096e02d3fe7SAlexander V. Chernikov RTM_DECLARE_ROOT_TEST(rtm_add_v6_gu_ifa_prefixroute_success,
1097e02d3fe7SAlexander V. Chernikov     "Tests validness for the prefix route announce after ifaddr assignment");
1098e02d3fe7SAlexander V. Chernikov 
1099e02d3fe7SAlexander V. Chernikov ATF_TC_BODY(rtm_add_v6_gu_ifa_prefixroute_success, tc)
1100e02d3fe7SAlexander V. Chernikov {
1101e02d3fe7SAlexander V. Chernikov 	DECLARE_TEST_VARS;
1102e02d3fe7SAlexander V. Chernikov 
1103e02d3fe7SAlexander V. Chernikov 	c = presetup_ipv6_iface(tc);
1104e02d3fe7SAlexander V. Chernikov 
1105e02d3fe7SAlexander V. Chernikov 	c->rtsock_fd = rtsock_setup_socket();
1106e02d3fe7SAlexander V. Chernikov 
1107e02d3fe7SAlexander V. Chernikov 	ret = iface_setup_addr(c->ifname, c->addr6_str, c->plen6);
1108e02d3fe7SAlexander V. Chernikov 
1109e02d3fe7SAlexander V. Chernikov 	/*
1110e02d3fe7SAlexander V. Chernikov 	 * Multiple RTM_ADD messages will be generated:
1111e02d3fe7SAlexander V. Chernikov 	 * 1) lladdr mapping (RTF_LLDATA)
1112e02d3fe7SAlexander V. Chernikov 	 * 2) host route (one w/o netmask)
1113e02d3fe7SAlexander V. Chernikov 	 * 3) prefix route
1114e02d3fe7SAlexander V. Chernikov 	 */
1115e02d3fe7SAlexander V. Chernikov 
1116e02d3fe7SAlexander V. Chernikov 	while (true) {
1117e02d3fe7SAlexander V. Chernikov 		rtm = rtsock_read_rtm(c->rtsock_fd, buffer, sizeof(buffer));
1118e02d3fe7SAlexander V. Chernikov 		/* Find RTM_ADD with netmask - this should skip both host route and LLADDR */
1119e02d3fe7SAlexander V. Chernikov 		if ((rtm->rtm_type == RTM_ADD) && (rtsock_find_rtm_sa(rtm, RTA_NETMASK)))
1120e02d3fe7SAlexander V. Chernikov 			break;
1121e02d3fe7SAlexander V. Chernikov 	}
1122e02d3fe7SAlexander V. Chernikov 
1123e02d3fe7SAlexander V. Chernikov 	/* This should be a message for the prefix route */
1124e02d3fe7SAlexander V. Chernikov 	verify_route_message(rtm, RTM_ADD, (struct sockaddr *)&c->net6,
1125e02d3fe7SAlexander V. Chernikov 	    (struct sockaddr *)&c->mask6, NULL);
1126e02d3fe7SAlexander V. Chernikov 
1127e02d3fe7SAlexander V. Chernikov 	/* gateway should be link sdl with ifindex of an address interface */
1128e02d3fe7SAlexander V. Chernikov 	verify_link_gateway(rtm, c->ifindex);
1129e02d3fe7SAlexander V. Chernikov 
1130*81728a53SAlexander V. Chernikov 	int expected_rt_flags = RTF_UP | RTF_DONE | RTF_PINNED;
1131e02d3fe7SAlexander V. Chernikov 	verify_route_message_extra(rtm, c->ifindex, expected_rt_flags);
1132e02d3fe7SAlexander V. Chernikov }
1133e02d3fe7SAlexander V. Chernikov 
1134e02d3fe7SAlexander V. Chernikov RTM_DECLARE_ROOT_TEST(rtm_add_v6_gu_ifa_ordered_success,
1135e02d3fe7SAlexander V. Chernikov     "Tests ordering of the messages for IPv6 global unicast ifaddr assignment");
1136e02d3fe7SAlexander V. Chernikov 
1137e02d3fe7SAlexander V. Chernikov ATF_TC_BODY(rtm_add_v6_gu_ifa_ordered_success, tc)
1138e02d3fe7SAlexander V. Chernikov {
1139e02d3fe7SAlexander V. Chernikov 	DECLARE_TEST_VARS;
1140e02d3fe7SAlexander V. Chernikov 
1141e02d3fe7SAlexander V. Chernikov 	c = presetup_ipv6_iface(tc);
1142e02d3fe7SAlexander V. Chernikov 
1143e02d3fe7SAlexander V. Chernikov 	c->rtsock_fd = rtsock_setup_socket();
1144e02d3fe7SAlexander V. Chernikov 
1145e02d3fe7SAlexander V. Chernikov 	ret = iface_setup_addr(c->ifname, c->addr6_str, c->plen6);
1146e02d3fe7SAlexander V. Chernikov 
1147e02d3fe7SAlexander V. Chernikov 	int count = 0, tries = 0;
1148e02d3fe7SAlexander V. Chernikov 
1149e02d3fe7SAlexander V. Chernikov 	enum msgtype {
1150e02d3fe7SAlexander V. Chernikov 		MSG_IFADDR,
1151e02d3fe7SAlexander V. Chernikov 		MSG_HOSTROUTE,
1152e02d3fe7SAlexander V. Chernikov 		MSG_PREFIXROUTE,
1153e02d3fe7SAlexander V. Chernikov 		MSG_MAX,
1154e02d3fe7SAlexander V. Chernikov 	};
1155e02d3fe7SAlexander V. Chernikov 
1156e02d3fe7SAlexander V. Chernikov 	int msg_array[MSG_MAX];
1157e02d3fe7SAlexander V. Chernikov 
1158e02d3fe7SAlexander V. Chernikov 	bzero(msg_array, sizeof(msg_array));
1159e02d3fe7SAlexander V. Chernikov 
1160e02d3fe7SAlexander V. Chernikov 	while (count < 3 && tries < 20) {
1161e02d3fe7SAlexander V. Chernikov 		rtm = rtsock_read_rtm(c->rtsock_fd, buffer, sizeof(buffer));
1162e02d3fe7SAlexander V. Chernikov 		tries++;
1163e02d3fe7SAlexander V. Chernikov 		/* Classify */
1164e02d3fe7SAlexander V. Chernikov 		if (rtm->rtm_type == RTM_NEWADDR) {
1165e02d3fe7SAlexander V. Chernikov 			RLOG("MSG_IFADDR: %d", count);
1166e02d3fe7SAlexander V. Chernikov 			msg_array[MSG_IFADDR] = count++;
1167e02d3fe7SAlexander V. Chernikov 			continue;
1168e02d3fe7SAlexander V. Chernikov 		}
1169e02d3fe7SAlexander V. Chernikov 
1170e02d3fe7SAlexander V. Chernikov 		/* Find RTM_ADD with netmask - this should skip both host route and LLADDR */
1171e02d3fe7SAlexander V. Chernikov 		if ((rtm->rtm_type == RTM_ADD) && (rtsock_find_rtm_sa(rtm, RTA_NETMASK))) {
1172e02d3fe7SAlexander V. Chernikov 			RLOG("MSG_PREFIXROUTE: %d", count);
1173e02d3fe7SAlexander V. Chernikov 			msg_array[MSG_PREFIXROUTE] = count++;
1174e02d3fe7SAlexander V. Chernikov 			continue;
1175e02d3fe7SAlexander V. Chernikov 		}
1176e02d3fe7SAlexander V. Chernikov 
1177e02d3fe7SAlexander V. Chernikov 		if ((rtm->rtm_type == RTM_ADD) && ((rtm->rtm_flags & RTF_LLDATA) == 0)) {
1178e02d3fe7SAlexander V. Chernikov 			RLOG("MSG_HOSTROUTE: %d", count);
1179e02d3fe7SAlexander V. Chernikov 			msg_array[MSG_HOSTROUTE] = count++;
1180e02d3fe7SAlexander V. Chernikov 			continue;
1181e02d3fe7SAlexander V. Chernikov 		}
1182e02d3fe7SAlexander V. Chernikov 
1183e02d3fe7SAlexander V. Chernikov 		RLOG("skipping msg type %s, try: %d", rtsock_print_cmdtype(rtm->rtm_type),
1184e02d3fe7SAlexander V. Chernikov 		    tries);
1185e02d3fe7SAlexander V. Chernikov 	}
1186e02d3fe7SAlexander V. Chernikov 
1187e02d3fe7SAlexander V. Chernikov 	/* TODO: verify multicast */
1188e02d3fe7SAlexander V. Chernikov 	ATF_REQUIRE_MSG(count == 3, "Received only %d/3 messages", count);
1189e02d3fe7SAlexander V. Chernikov 	ATF_REQUIRE_MSG(msg_array[MSG_IFADDR] == 0, "ifaddr message is not the first");
1190e02d3fe7SAlexander V. Chernikov }
1191e02d3fe7SAlexander V. Chernikov 
1192e02d3fe7SAlexander V. Chernikov RTM_DECLARE_ROOT_TEST(rtm_del_v6_gu_ifa_hostroute_success,
1193e02d3fe7SAlexander V. Chernikov     "Tests validness for /128 host route removal after ifaddr removal");
1194e02d3fe7SAlexander V. Chernikov 
1195e02d3fe7SAlexander V. Chernikov ATF_TC_BODY(rtm_del_v6_gu_ifa_hostroute_success, tc)
1196e02d3fe7SAlexander V. Chernikov {
1197e02d3fe7SAlexander V. Chernikov 	DECLARE_TEST_VARS;
1198e02d3fe7SAlexander V. Chernikov 
1199e02d3fe7SAlexander V. Chernikov 	c = presetup_ipv6_iface(tc);
1200e02d3fe7SAlexander V. Chernikov 
1201e02d3fe7SAlexander V. Chernikov 	ret = iface_setup_addr(c->ifname, c->addr6_str, c->plen6);
1202e02d3fe7SAlexander V. Chernikov 
1203e02d3fe7SAlexander V. Chernikov 	c->rtsock_fd = rtsock_setup_socket();
1204e02d3fe7SAlexander V. Chernikov 
1205e02d3fe7SAlexander V. Chernikov 	ret = iface_delete_addr(c->ifname, c->addr6_str);
1206e02d3fe7SAlexander V. Chernikov 
1207e02d3fe7SAlexander V. Chernikov 	while (true) {
1208e02d3fe7SAlexander V. Chernikov 		rtm = rtsock_read_rtm(c->rtsock_fd, buffer, sizeof(buffer));
1209e02d3fe7SAlexander V. Chernikov 		if ((rtm->rtm_type == RTM_DELETE) &&
1210e02d3fe7SAlexander V. Chernikov 		    ((rtm->rtm_flags & RTF_LLINFO) == 0) &&
1211e02d3fe7SAlexander V. Chernikov 		    rtsock_find_rtm_sa(rtm, RTA_NETMASK) == NULL)
1212e02d3fe7SAlexander V. Chernikov 			break;
1213e02d3fe7SAlexander V. Chernikov 	}
1214e02d3fe7SAlexander V. Chernikov 	/* This should be a message for the host route */
1215e02d3fe7SAlexander V. Chernikov 
1216e02d3fe7SAlexander V. Chernikov 	verify_route_message(rtm, RTM_DELETE, (struct sockaddr *)&c->addr6, NULL, NULL);
1217e02d3fe7SAlexander V. Chernikov 	rtsock_validate_pid_kernel(rtm);
1218e02d3fe7SAlexander V. Chernikov 	/* No netmask should be set */
1219e02d3fe7SAlexander V. Chernikov 	RTSOCK_ATF_REQUIRE_MSG(rtm, rtsock_find_rtm_sa(rtm, RTA_NETMASK) == NULL, "netmask is set");
1220e02d3fe7SAlexander V. Chernikov 
1221e02d3fe7SAlexander V. Chernikov 	/* gateway should be link sdl with ifindex of an address interface */
1222e02d3fe7SAlexander V. Chernikov 	verify_link_gateway(rtm, c->ifindex);
1223e02d3fe7SAlexander V. Chernikov 
1224e02d3fe7SAlexander V. Chernikov 	/* XXX: consider passing ifindex in rtm_index as done in RTM_ADD. */
1225e02d3fe7SAlexander V. Chernikov 	int expected_rt_flags = RTF_HOST | RTF_DONE | RTF_STATIC | RTF_PINNED;
1226e02d3fe7SAlexander V. Chernikov 	RTSOCK_ATF_REQUIRE_MSG(rtm, rtm->rtm_flags == expected_rt_flags,
1227e02d3fe7SAlexander V. Chernikov 	    "expected rtm flags: 0x%X, got 0x%X", expected_rt_flags, rtm->rtm_flags);
1228e02d3fe7SAlexander V. Chernikov }
1229e02d3fe7SAlexander V. Chernikov 
1230e02d3fe7SAlexander V. Chernikov RTM_DECLARE_ROOT_TEST(rtm_del_v6_gu_ifa_prefixroute_success,
1231e02d3fe7SAlexander V. Chernikov     "Tests validness for the prefix route removal after ifaddr assignment");
1232e02d3fe7SAlexander V. Chernikov 
1233e02d3fe7SAlexander V. Chernikov ATF_TC_BODY(rtm_del_v6_gu_ifa_prefixroute_success, tc)
1234e02d3fe7SAlexander V. Chernikov {
1235e02d3fe7SAlexander V. Chernikov 	DECLARE_TEST_VARS;
1236e02d3fe7SAlexander V. Chernikov 
1237e02d3fe7SAlexander V. Chernikov 	c = presetup_ipv6_iface(tc);
1238e02d3fe7SAlexander V. Chernikov 
1239e02d3fe7SAlexander V. Chernikov 	ret = iface_setup_addr(c->ifname, c->addr6_str, c->plen6);
1240e02d3fe7SAlexander V. Chernikov 
1241e02d3fe7SAlexander V. Chernikov 	c->rtsock_fd = rtsock_setup_socket();
1242e02d3fe7SAlexander V. Chernikov 
1243e02d3fe7SAlexander V. Chernikov 	ret = iface_delete_addr(c->ifname, c->addr6_str);
1244e02d3fe7SAlexander V. Chernikov 
1245e02d3fe7SAlexander V. Chernikov 	while (true) {
1246e02d3fe7SAlexander V. Chernikov 		rtm = rtsock_read_rtm(c->rtsock_fd, buffer, sizeof(buffer));
1247e02d3fe7SAlexander V. Chernikov 		/* Find RTM_DELETE with netmask - this should skip both host route and LLADDR */
1248e02d3fe7SAlexander V. Chernikov 		if ((rtm->rtm_type == RTM_DELETE) && (rtsock_find_rtm_sa(rtm, RTA_NETMASK)))
1249e02d3fe7SAlexander V. Chernikov 			break;
1250e02d3fe7SAlexander V. Chernikov 	}
1251e02d3fe7SAlexander V. Chernikov 
1252e02d3fe7SAlexander V. Chernikov 	/* This should be a message for the prefix route */
1253e02d3fe7SAlexander V. Chernikov 	verify_route_message(rtm, RTM_DELETE, (struct sockaddr *)&c->net6,
1254e02d3fe7SAlexander V. Chernikov 	    (struct sockaddr *)&c->mask6, NULL);
1255e02d3fe7SAlexander V. Chernikov 
1256e02d3fe7SAlexander V. Chernikov 	/* gateway should be link sdl with ifindex of an address interface */
1257e02d3fe7SAlexander V. Chernikov 	verify_link_gateway(rtm, c->ifindex);
1258e02d3fe7SAlexander V. Chernikov 
1259*81728a53SAlexander V. Chernikov 	int expected_rt_flags = RTF_DONE | RTF_PINNED;
1260e02d3fe7SAlexander V. Chernikov 	verify_route_message_extra(rtm, c->ifindex, expected_rt_flags);
1261e02d3fe7SAlexander V. Chernikov }
1262e02d3fe7SAlexander V. Chernikov 
1263e02d3fe7SAlexander V. Chernikov RTM_DECLARE_ROOT_TEST(rtm_add_v4_gu_ifa_prefixroute_success,
1264e02d3fe7SAlexander V. Chernikov     "Tests validness for the prefix route announce after ifaddr assignment");
1265e02d3fe7SAlexander V. Chernikov 
1266e02d3fe7SAlexander V. Chernikov ATF_TC_BODY(rtm_add_v4_gu_ifa_prefixroute_success, tc)
1267e02d3fe7SAlexander V. Chernikov {
1268e02d3fe7SAlexander V. Chernikov 	DECLARE_TEST_VARS;
1269e02d3fe7SAlexander V. Chernikov 
1270e02d3fe7SAlexander V. Chernikov 	c = presetup_ipv4_iface(tc);
1271e02d3fe7SAlexander V. Chernikov 
1272e02d3fe7SAlexander V. Chernikov 	c->rtsock_fd = rtsock_setup_socket();
1273e02d3fe7SAlexander V. Chernikov 
1274e02d3fe7SAlexander V. Chernikov 	ret = iface_setup_addr(c->ifname, c->addr6_str, c->plen6);
1275e02d3fe7SAlexander V. Chernikov 
1276e02d3fe7SAlexander V. Chernikov 	/*
1277e02d3fe7SAlexander V. Chernikov 	 * Multiple RTM_ADD messages will be generated:
1278e02d3fe7SAlexander V. Chernikov 	 * 1) lladdr mapping (RTF_LLDATA)
1279e02d3fe7SAlexander V. Chernikov 	 * 3) prefix route
1280e02d3fe7SAlexander V. Chernikov 	 */
1281e02d3fe7SAlexander V. Chernikov 
1282e02d3fe7SAlexander V. Chernikov 	while (true) {
1283e02d3fe7SAlexander V. Chernikov 		rtm = rtsock_read_rtm(c->rtsock_fd, buffer, sizeof(buffer));
1284e02d3fe7SAlexander V. Chernikov 		/* Find RTM_ADD with netmask - this should skip both host route and LLADDR */
1285e02d3fe7SAlexander V. Chernikov 		if ((rtm->rtm_type == RTM_ADD) && (rtsock_find_rtm_sa(rtm, RTA_NETMASK)))
1286e02d3fe7SAlexander V. Chernikov 			break;
1287e02d3fe7SAlexander V. Chernikov 	}
1288e02d3fe7SAlexander V. Chernikov 
1289e02d3fe7SAlexander V. Chernikov 	/* This should be a message for the prefix route */
1290e02d3fe7SAlexander V. Chernikov 	verify_route_message(rtm, RTM_ADD, (struct sockaddr *)&c->net4,
1291e02d3fe7SAlexander V. Chernikov 	    (struct sockaddr *)&c->mask4, NULL);
1292e02d3fe7SAlexander V. Chernikov 
1293e02d3fe7SAlexander V. Chernikov 	/* gateway should be link sdl with ifindex of an address interface */
1294e02d3fe7SAlexander V. Chernikov 	verify_link_gateway(rtm, c->ifindex);
1295e02d3fe7SAlexander V. Chernikov 
1296e02d3fe7SAlexander V. Chernikov 	int expected_rt_flags = RTF_UP | RTF_DONE | RTF_PINNED;
1297e02d3fe7SAlexander V. Chernikov 	verify_route_message_extra(rtm, c->ifindex, expected_rt_flags);
1298e02d3fe7SAlexander V. Chernikov }
1299e02d3fe7SAlexander V. Chernikov 
1300e02d3fe7SAlexander V. Chernikov RTM_DECLARE_ROOT_TEST(rtm_add_v4_gu_ifa_ordered_success,
1301e02d3fe7SAlexander V. Chernikov     "Tests ordering of the messages for IPv4 unicast ifaddr assignment");
1302e02d3fe7SAlexander V. Chernikov 
1303e02d3fe7SAlexander V. Chernikov ATF_TC_BODY(rtm_add_v4_gu_ifa_ordered_success, tc)
1304e02d3fe7SAlexander V. Chernikov {
1305e02d3fe7SAlexander V. Chernikov 	DECLARE_TEST_VARS;
1306e02d3fe7SAlexander V. Chernikov 
1307e02d3fe7SAlexander V. Chernikov 	c = presetup_ipv4_iface(tc);
1308e02d3fe7SAlexander V. Chernikov 
1309e02d3fe7SAlexander V. Chernikov 	c->rtsock_fd = rtsock_setup_socket();
1310e02d3fe7SAlexander V. Chernikov 
1311e02d3fe7SAlexander V. Chernikov 	ret = iface_setup_addr(c->ifname, c->addr4_str, c->plen4);
1312e02d3fe7SAlexander V. Chernikov 
1313e02d3fe7SAlexander V. Chernikov 	int count = 0, tries = 0;
1314e02d3fe7SAlexander V. Chernikov 
1315e02d3fe7SAlexander V. Chernikov 	enum msgtype {
1316e02d3fe7SAlexander V. Chernikov 		MSG_IFADDR,
1317e02d3fe7SAlexander V. Chernikov 		MSG_PREFIXROUTE,
1318e02d3fe7SAlexander V. Chernikov 		MSG_MAX,
1319e02d3fe7SAlexander V. Chernikov 	};
1320e02d3fe7SAlexander V. Chernikov 
1321e02d3fe7SAlexander V. Chernikov 	int msg_array[MSG_MAX];
1322e02d3fe7SAlexander V. Chernikov 
1323e02d3fe7SAlexander V. Chernikov 	bzero(msg_array, sizeof(msg_array));
1324e02d3fe7SAlexander V. Chernikov 
1325e02d3fe7SAlexander V. Chernikov 	while (count < 2 && tries < 20) {
1326e02d3fe7SAlexander V. Chernikov 		rtm = rtsock_read_rtm(c->rtsock_fd, buffer, sizeof(buffer));
1327e02d3fe7SAlexander V. Chernikov 		tries++;
1328e02d3fe7SAlexander V. Chernikov 		/* Classify */
1329e02d3fe7SAlexander V. Chernikov 		if (rtm->rtm_type == RTM_NEWADDR) {
1330e02d3fe7SAlexander V. Chernikov 			RLOG("MSG_IFADDR: %d", count);
1331e02d3fe7SAlexander V. Chernikov 			msg_array[MSG_IFADDR] = count++;
1332e02d3fe7SAlexander V. Chernikov 			continue;
1333e02d3fe7SAlexander V. Chernikov 		}
1334e02d3fe7SAlexander V. Chernikov 
1335e02d3fe7SAlexander V. Chernikov 		/* Find RTM_ADD with netmask - this should skip both host route and LLADDR */
1336e02d3fe7SAlexander V. Chernikov 		if ((rtm->rtm_type == RTM_ADD) && (rtsock_find_rtm_sa(rtm, RTA_NETMASK))) {
1337e02d3fe7SAlexander V. Chernikov 			RLOG("MSG_PREFIXROUTE: %d", count);
1338e02d3fe7SAlexander V. Chernikov 			msg_array[MSG_PREFIXROUTE] = count++;
1339e02d3fe7SAlexander V. Chernikov 			continue;
1340e02d3fe7SAlexander V. Chernikov 		}
1341e02d3fe7SAlexander V. Chernikov 
1342e02d3fe7SAlexander V. Chernikov 		RLOG("skipping msg type %s, try: %d", rtsock_print_cmdtype(rtm->rtm_type),
1343e02d3fe7SAlexander V. Chernikov 		    tries);
1344e02d3fe7SAlexander V. Chernikov 	}
1345e02d3fe7SAlexander V. Chernikov 
1346e02d3fe7SAlexander V. Chernikov 	/* TODO: verify multicast */
1347e02d3fe7SAlexander V. Chernikov 	ATF_REQUIRE_MSG(count == 2, "Received only %d/2 messages", count);
1348e02d3fe7SAlexander V. Chernikov 	ATF_REQUIRE_MSG(msg_array[MSG_IFADDR] == 0, "ifaddr message is not the first");
1349e02d3fe7SAlexander V. Chernikov }
1350e02d3fe7SAlexander V. Chernikov 
1351e02d3fe7SAlexander V. Chernikov RTM_DECLARE_ROOT_TEST(rtm_del_v4_gu_ifa_prefixroute_success,
1352e02d3fe7SAlexander V. Chernikov     "Tests validness for the prefix route removal after ifaddr assignment");
1353e02d3fe7SAlexander V. Chernikov 
1354e02d3fe7SAlexander V. Chernikov ATF_TC_BODY(rtm_del_v4_gu_ifa_prefixroute_success, tc)
1355e02d3fe7SAlexander V. Chernikov {
1356e02d3fe7SAlexander V. Chernikov 	DECLARE_TEST_VARS;
1357e02d3fe7SAlexander V. Chernikov 
1358e02d3fe7SAlexander V. Chernikov 	c = presetup_ipv4_iface(tc);
1359e02d3fe7SAlexander V. Chernikov 
1360e02d3fe7SAlexander V. Chernikov 
1361e02d3fe7SAlexander V. Chernikov 	ret = iface_setup_addr(c->ifname, c->addr4_str, c->plen4);
1362e02d3fe7SAlexander V. Chernikov 
1363e02d3fe7SAlexander V. Chernikov 	c->rtsock_fd = rtsock_setup_socket();
1364e02d3fe7SAlexander V. Chernikov 
1365e02d3fe7SAlexander V. Chernikov 	ret = iface_delete_addr(c->ifname, c->addr4_str);
1366e02d3fe7SAlexander V. Chernikov 
1367e02d3fe7SAlexander V. Chernikov 	while (true) {
1368e02d3fe7SAlexander V. Chernikov 		rtm = rtsock_read_rtm(c->rtsock_fd, buffer, sizeof(buffer));
1369e02d3fe7SAlexander V. Chernikov 		/* Find RTM_ADD with netmask - this should skip both host route and LLADDR */
1370e02d3fe7SAlexander V. Chernikov 		if ((rtm->rtm_type == RTM_DELETE) && (rtsock_find_rtm_sa(rtm, RTA_NETMASK)))
1371e02d3fe7SAlexander V. Chernikov 			break;
1372e02d3fe7SAlexander V. Chernikov 	}
1373e02d3fe7SAlexander V. Chernikov 
1374e02d3fe7SAlexander V. Chernikov 	/* This should be a message for the prefix route */
1375e02d3fe7SAlexander V. Chernikov 	verify_route_message(rtm, RTM_DELETE, (struct sockaddr *)&c->net4,
1376e02d3fe7SAlexander V. Chernikov 	    (struct sockaddr *)&c->mask4, NULL);
1377e02d3fe7SAlexander V. Chernikov 
1378e02d3fe7SAlexander V. Chernikov 	/* gateway should be link sdl with ifindex of an address interface */
1379e02d3fe7SAlexander V. Chernikov 	verify_link_gateway(rtm, c->ifindex);
1380e02d3fe7SAlexander V. Chernikov 
1381e02d3fe7SAlexander V. Chernikov 	int expected_rt_flags = RTF_DONE | RTF_PINNED;
1382e02d3fe7SAlexander V. Chernikov 	verify_route_message_extra(rtm, c->ifindex, expected_rt_flags);
1383e02d3fe7SAlexander V. Chernikov }
1384775dc861SAlexander V. Chernikov 
1385775dc861SAlexander V. Chernikov 
1386775dc861SAlexander V. Chernikov ATF_TP_ADD_TCS(tp)
1387775dc861SAlexander V. Chernikov {
1388775dc861SAlexander V. Chernikov 	ATF_TP_ADD_TC(tp, rtm_get_v4_exact_success);
1389775dc861SAlexander V. Chernikov 	ATF_TP_ADD_TC(tp, rtm_get_v4_lpm_success);
1390775dc861SAlexander V. Chernikov 	ATF_TP_ADD_TC(tp, rtm_get_v4_hostbits_failure);
1391775dc861SAlexander V. Chernikov 	ATF_TP_ADD_TC(tp, rtm_get_v4_empty_dst_failure);
13925676d488SAlexander V. Chernikov 	ATF_TP_ADD_TC(tp, rtm_add_v4_no_rtf_host_failure);
1393775dc861SAlexander V. Chernikov 	ATF_TP_ADD_TC(tp, rtm_add_v4_gw_direct_success);
1394775dc861SAlexander V. Chernikov 	ATF_TP_ADD_TC(tp, rtm_del_v4_prefix_nogw_success);
1395775dc861SAlexander V. Chernikov 	ATF_TP_ADD_TC(tp, rtm_add_v6_gu_gw_gu_direct_success);
1396775dc861SAlexander V. Chernikov 	ATF_TP_ADD_TC(tp, rtm_del_v6_gu_prefix_nogw_success);
1397272bd698SAlexander V. Chernikov 	ATF_TP_ADD_TC(tp, rtm_change_v4_gw_success);
1398272bd698SAlexander V. Chernikov 	ATF_TP_ADD_TC(tp, rtm_change_v4_mtu_success);
13991b95005eSAlexander V. Chernikov 	ATF_TP_ADD_TC(tp, rtm_change_v4_flags_success);
1400272bd698SAlexander V. Chernikov 	ATF_TP_ADD_TC(tp, rtm_change_v6_gw_success);
1401272bd698SAlexander V. Chernikov 	ATF_TP_ADD_TC(tp, rtm_change_v6_mtu_success);
14021b95005eSAlexander V. Chernikov 	ATF_TP_ADD_TC(tp, rtm_change_v6_flags_success);
1403e02d3fe7SAlexander V. Chernikov 	/* ifaddr tests */
1404e02d3fe7SAlexander V. Chernikov 	ATF_TP_ADD_TC(tp, rtm_add_v6_gu_ifa_hostroute_success);
1405e02d3fe7SAlexander V. Chernikov 	ATF_TP_ADD_TC(tp, rtm_add_v6_gu_ifa_prefixroute_success);
1406e02d3fe7SAlexander V. Chernikov 	ATF_TP_ADD_TC(tp, rtm_add_v6_gu_ifa_ordered_success);
1407e02d3fe7SAlexander V. Chernikov 	ATF_TP_ADD_TC(tp, rtm_del_v6_gu_ifa_hostroute_success);
1408e02d3fe7SAlexander V. Chernikov 	ATF_TP_ADD_TC(tp, rtm_del_v6_gu_ifa_prefixroute_success);
1409e02d3fe7SAlexander V. Chernikov 	ATF_TP_ADD_TC(tp, rtm_add_v4_gu_ifa_ordered_success);
1410e02d3fe7SAlexander V. Chernikov 	ATF_TP_ADD_TC(tp, rtm_del_v4_gu_ifa_prefixroute_success);
141134a5582cSAlexander V. Chernikov 	/* temporal routes */
141234a5582cSAlexander V. Chernikov 	ATF_TP_ADD_TC(tp, rtm_add_v4_temporal1_success);
141334a5582cSAlexander V. Chernikov 	ATF_TP_ADD_TC(tp, rtm_add_v6_temporal1_success);
1414775dc861SAlexander V. Chernikov 
1415775dc861SAlexander V. Chernikov 	return (atf_no_error());
1416775dc861SAlexander V. Chernikov }
1417775dc861SAlexander V. Chernikov 
1418