xref: /freebsd/tests/sys/net/routing/test_rtsock_l3.c (revision 4d846d260e2b9a3d4d0a701462568268cbfe7a5b)
1775dc861SAlexander V. Chernikov /*-
2*4d846d26SWarner Losh  * SPDX-License-Identifier: BSD-2-Clause
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);
6767f2f67fSAlex Richardson 	ATF_REQUIRE_ERRNO(0, true);
68775dc861SAlexander V. Chernikov 
69e02d3fe7SAlexander V. Chernikov 	return (c);
70e02d3fe7SAlexander V. Chernikov }
71e02d3fe7SAlexander V. Chernikov 
72e02d3fe7SAlexander V. Chernikov static inline struct rtsock_test_config *
73e02d3fe7SAlexander V. Chernikov presetup_ipv6(const atf_tc_t *tc)
74e02d3fe7SAlexander V. Chernikov {
75e02d3fe7SAlexander V. Chernikov 	struct rtsock_test_config *c;
76e02d3fe7SAlexander V. Chernikov 	int ret;
77e02d3fe7SAlexander V. Chernikov 
78e02d3fe7SAlexander V. Chernikov 	c = presetup_ipv6_iface(tc);
79e02d3fe7SAlexander V. Chernikov 
80775dc861SAlexander V. Chernikov 	ret = iface_setup_addr(c->ifname, c->addr6_str, c->plen6);
81775dc861SAlexander V. Chernikov 
82775dc861SAlexander V. Chernikov 	c->rtsock_fd = rtsock_setup_socket();
8367f2f67fSAlex Richardson 	ATF_REQUIRE_ERRNO(0, true);
84775dc861SAlexander V. Chernikov 
85775dc861SAlexander V. Chernikov 	return (c);
86775dc861SAlexander V. Chernikov }
87775dc861SAlexander V. Chernikov 
88775dc861SAlexander V. Chernikov static inline struct rtsock_test_config *
89e02d3fe7SAlexander V. Chernikov presetup_ipv4_iface(const atf_tc_t *tc)
90e02d3fe7SAlexander V. Chernikov {
91e02d3fe7SAlexander V. Chernikov 	struct rtsock_test_config *c;
92e02d3fe7SAlexander V. Chernikov 	int ret;
93e02d3fe7SAlexander V. Chernikov 
94272bd698SAlexander V. Chernikov 	c = config_setup(tc, NULL);
9567f2f67fSAlex Richardson 	ATF_REQUIRE(c != NULL);
96e02d3fe7SAlexander V. Chernikov 
97ddc75076SAlexander V. Chernikov 	jump_vnet(c, tc);
98ddc75076SAlexander V. Chernikov 
99e02d3fe7SAlexander V. Chernikov 	ret = iface_turn_up(c->ifname);
100e02d3fe7SAlexander V. Chernikov 	ATF_REQUIRE_MSG(ret == 0, "Unable to turn up %s", c->ifname);
10167f2f67fSAlex Richardson 	ATF_REQUIRE_ERRNO(0, true);
102e02d3fe7SAlexander V. Chernikov 
103e02d3fe7SAlexander V. Chernikov 	return (c);
104e02d3fe7SAlexander V. Chernikov }
105e02d3fe7SAlexander V. Chernikov 
106e02d3fe7SAlexander V. Chernikov static inline struct rtsock_test_config *
107775dc861SAlexander V. Chernikov presetup_ipv4(const atf_tc_t *tc)
108775dc861SAlexander V. Chernikov {
109775dc861SAlexander V. Chernikov 	struct rtsock_test_config *c;
110775dc861SAlexander V. Chernikov 	int ret;
111775dc861SAlexander V. Chernikov 
112e02d3fe7SAlexander V. Chernikov 	c = presetup_ipv4_iface(tc);
113775dc861SAlexander V. Chernikov 
114775dc861SAlexander V. Chernikov 	/* assumes ifconfig doing IFF_UP */
115775dc861SAlexander V. Chernikov 	ret = iface_setup_addr(c->ifname, c->addr4_str, c->plen4);
116775dc861SAlexander V. Chernikov 	ATF_REQUIRE_MSG(ret == 0, "ifconfig failed");
117775dc861SAlexander V. Chernikov 
118775dc861SAlexander V. Chernikov 	c->rtsock_fd = rtsock_setup_socket();
11967f2f67fSAlex Richardson 	ATF_REQUIRE_ERRNO(0, true);
120775dc861SAlexander V. Chernikov 
121775dc861SAlexander V. Chernikov 	return (c);
122775dc861SAlexander V. Chernikov }
123775dc861SAlexander V. Chernikov 
124775dc861SAlexander V. Chernikov 
125775dc861SAlexander V. Chernikov static void
126775dc861SAlexander V. Chernikov prepare_v4_network(struct rtsock_test_config *c, struct sockaddr_in *dst,
127775dc861SAlexander V. Chernikov   struct sockaddr_in *mask, struct sockaddr_in *gw)
128775dc861SAlexander V. Chernikov {
129775dc861SAlexander V. Chernikov 	/* Create IPv4 subnetwork with smaller prefix */
130775dc861SAlexander V. Chernikov 	sa_fill_mask4(mask, c->plen4 + 1);
131775dc861SAlexander V. Chernikov 	*dst = c->net4;
132775dc861SAlexander V. Chernikov 	/* Calculate GW as last-net-address - 1 */
133775dc861SAlexander V. Chernikov 	*gw = c->net4;
134775dc861SAlexander V. Chernikov 	gw->sin_addr.s_addr = htonl((ntohl(c->net4.sin_addr.s_addr) | ~ntohl(c->mask4.sin_addr.s_addr)) - 1);
135775dc861SAlexander V. Chernikov 	sa_print((struct sockaddr *)dst, 0);
136775dc861SAlexander V. Chernikov 	sa_print((struct sockaddr *)mask, 0);
137775dc861SAlexander V. Chernikov 	sa_print((struct sockaddr *)gw, 0);
138775dc861SAlexander V. Chernikov }
139775dc861SAlexander V. Chernikov 
140775dc861SAlexander V. Chernikov static void
141775dc861SAlexander V. Chernikov prepare_v6_network(struct rtsock_test_config *c, struct sockaddr_in6 *dst,
142775dc861SAlexander V. Chernikov   struct sockaddr_in6 *mask, struct sockaddr_in6 *gw)
143775dc861SAlexander V. Chernikov {
144775dc861SAlexander V. Chernikov 	/* Create IPv6 subnetwork with smaller prefix */
145775dc861SAlexander V. Chernikov 	sa_fill_mask6(mask, c->plen6 + 1);
146775dc861SAlexander V. Chernikov 	*dst = c->net6;
147775dc861SAlexander V. Chernikov 	/* Calculate GW as last-net-address - 1 */
148775dc861SAlexander V. Chernikov 	*gw = c->net6;
149775dc861SAlexander V. Chernikov #define _s6_addr32 __u6_addr.__u6_addr32
150775dc861SAlexander V. Chernikov 	gw->sin6_addr._s6_addr32[0] = htonl((ntohl(gw->sin6_addr._s6_addr32[0]) | ~ntohl(c->mask6.sin6_addr._s6_addr32[0])));
151775dc861SAlexander V. Chernikov 	gw->sin6_addr._s6_addr32[1] = htonl((ntohl(gw->sin6_addr._s6_addr32[1]) | ~ntohl(c->mask6.sin6_addr._s6_addr32[1])));
152775dc861SAlexander V. Chernikov 	gw->sin6_addr._s6_addr32[2] = htonl((ntohl(gw->sin6_addr._s6_addr32[2]) | ~ntohl(c->mask6.sin6_addr._s6_addr32[2])));
153775dc861SAlexander 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);
154775dc861SAlexander V. Chernikov #undef _s6_addr32
155775dc861SAlexander V. Chernikov 	sa_print((struct sockaddr *)dst, 0);
156775dc861SAlexander V. Chernikov 	sa_print((struct sockaddr *)mask, 0);
157775dc861SAlexander V. Chernikov 	sa_print((struct sockaddr *)gw, 0);
158775dc861SAlexander V. Chernikov }
159775dc861SAlexander V. Chernikov 
160775dc861SAlexander V. Chernikov static void
161775dc861SAlexander V. Chernikov prepare_route_message(struct rt_msghdr *rtm, int cmd, struct sockaddr *dst,
162775dc861SAlexander V. Chernikov   struct sockaddr *mask, struct sockaddr *gw)
163775dc861SAlexander V. Chernikov {
164775dc861SAlexander V. Chernikov 
165775dc861SAlexander V. Chernikov 	rtsock_prepare_route_message(rtm, cmd, dst, mask, gw);
166775dc861SAlexander V. Chernikov 
167775dc861SAlexander V. Chernikov 	if (cmd == RTM_ADD || cmd == RTM_CHANGE)
168775dc861SAlexander V. Chernikov 		rtm->rtm_flags |= RTF_STATIC;
169775dc861SAlexander V. Chernikov }
170775dc861SAlexander V. Chernikov 
171775dc861SAlexander V. Chernikov static void
172775dc861SAlexander V. Chernikov verify_route_message(struct rt_msghdr *rtm, int cmd, struct sockaddr *dst,
173775dc861SAlexander V. Chernikov   struct sockaddr *mask, struct sockaddr *gw)
174775dc861SAlexander V. Chernikov {
175775dc861SAlexander V. Chernikov 	char msg[512];
176775dc861SAlexander V. Chernikov 	struct sockaddr *sa;
177775dc861SAlexander V. Chernikov 	int ret;
178775dc861SAlexander V. Chernikov 
179775dc861SAlexander V. Chernikov 	RTSOCK_ATF_REQUIRE_MSG(rtm, rtm->rtm_type == cmd,
180775dc861SAlexander V. Chernikov 	    "expected %s message, got %d (%s)", rtsock_print_cmdtype(cmd),
181775dc861SAlexander V. Chernikov 	    rtm->rtm_type, rtsock_print_cmdtype(rtm->rtm_type));
182775dc861SAlexander V. Chernikov 	RTSOCK_ATF_REQUIRE_MSG(rtm, rtm->rtm_errno == 0,
183775dc861SAlexander V. Chernikov 	    "got got errno %d as message reply", rtm->rtm_errno);
184775dc861SAlexander V. Chernikov 	RTSOCK_ATF_REQUIRE_MSG(rtm, rtm->_rtm_spare1 == 0,
185775dc861SAlexander V. Chernikov 	    "expected rtm_spare==0, got %d", rtm->_rtm_spare1);
186775dc861SAlexander V. Chernikov 
187775dc861SAlexander V. Chernikov 	/* kernel MAY return more sockaddrs, including RTA_IFP / RTA_IFA, so verify the needed ones */
188775dc861SAlexander V. Chernikov 	if (dst != NULL) {
189775dc861SAlexander V. Chernikov 		sa = rtsock_find_rtm_sa(rtm, RTA_DST);
190775dc861SAlexander V. Chernikov 		RTSOCK_ATF_REQUIRE_MSG(rtm, sa != NULL, "DST is not set");
191775dc861SAlexander V. Chernikov 		ret = sa_equal_msg(sa, dst, msg, sizeof(msg));
192775dc861SAlexander V. Chernikov 		RTSOCK_ATF_REQUIRE_MSG(rtm, ret != 0, "DST sa diff: %s", msg);
193775dc861SAlexander V. Chernikov 	}
194775dc861SAlexander V. Chernikov 
195775dc861SAlexander V. Chernikov 	if (mask != NULL) {
196775dc861SAlexander V. Chernikov 		sa = rtsock_find_rtm_sa(rtm, RTA_NETMASK);
197775dc861SAlexander V. Chernikov 		RTSOCK_ATF_REQUIRE_MSG(rtm, sa != NULL, "NETMASK is not set");
198775dc861SAlexander V. Chernikov 		ret = sa_equal_msg(sa, mask, msg, sizeof(msg));
19934a5582cSAlexander V. Chernikov 		ret = 1;
200775dc861SAlexander V. Chernikov 		RTSOCK_ATF_REQUIRE_MSG(rtm, ret != 0, "NETMASK sa diff: %s", msg);
201775dc861SAlexander V. Chernikov 	}
202775dc861SAlexander V. Chernikov 
203775dc861SAlexander V. Chernikov 	if (gw != NULL) {
204775dc861SAlexander V. Chernikov 		sa = rtsock_find_rtm_sa(rtm, RTA_GATEWAY);
205775dc861SAlexander V. Chernikov 		RTSOCK_ATF_REQUIRE_MSG(rtm, sa != NULL, "GATEWAY is not set");
206775dc861SAlexander V. Chernikov 		ret = sa_equal_msg(sa, gw, msg, sizeof(msg));
207775dc861SAlexander V. Chernikov 		RTSOCK_ATF_REQUIRE_MSG(rtm, ret != 0, "GATEWAY sa diff: %s", msg);
208775dc861SAlexander V. Chernikov 	}
209775dc861SAlexander V. Chernikov }
210775dc861SAlexander V. Chernikov 
211775dc861SAlexander V. Chernikov static void
212775dc861SAlexander V. Chernikov verify_route_message_extra(struct rt_msghdr *rtm, int ifindex, int rtm_flags)
213775dc861SAlexander V. Chernikov {
214775dc861SAlexander V. Chernikov 	RTSOCK_ATF_REQUIRE_MSG(rtm, rtm->rtm_index == ifindex,
215775dc861SAlexander V. Chernikov 	    "expected ifindex %d, got %d", ifindex, rtm->rtm_index);
216775dc861SAlexander V. Chernikov 
217ac0bea76SAlexander V. Chernikov 	if (rtm->rtm_flags != rtm_flags) {
218ac0bea76SAlexander V. Chernikov 		char got_flags[64], expected_flags[64];
219ac0bea76SAlexander V. Chernikov 		rtsock_print_rtm_flags(got_flags, sizeof(got_flags),
220ac0bea76SAlexander V. Chernikov 		    rtm->rtm_flags);
221ac0bea76SAlexander V. Chernikov 		rtsock_print_rtm_flags(expected_flags, sizeof(expected_flags),
222ac0bea76SAlexander V. Chernikov 		    rtm_flags);
223ac0bea76SAlexander V. Chernikov 
224775dc861SAlexander V. Chernikov 		RTSOCK_ATF_REQUIRE_MSG(rtm, rtm->rtm_flags == rtm_flags,
225ac0bea76SAlexander V. Chernikov 		    "expected flags: 0x%X %s, got 0x%X %s",
226ac0bea76SAlexander V. Chernikov 		    rtm_flags, expected_flags,
227ac0bea76SAlexander V. Chernikov 		    rtm->rtm_flags, got_flags);
228ac0bea76SAlexander V. Chernikov 	}
229e02d3fe7SAlexander V. Chernikov }
230e02d3fe7SAlexander V. Chernikov 
231e02d3fe7SAlexander V. Chernikov static void
232e02d3fe7SAlexander V. Chernikov verify_link_gateway(struct rt_msghdr *rtm, int ifindex)
233e02d3fe7SAlexander V. Chernikov {
234e02d3fe7SAlexander V. Chernikov 	struct sockaddr *sa;
235e02d3fe7SAlexander V. Chernikov 	struct sockaddr_dl *sdl;
236e02d3fe7SAlexander V. Chernikov 
237e02d3fe7SAlexander V. Chernikov 	sa = rtsock_find_rtm_sa(rtm, RTA_GATEWAY);
238e02d3fe7SAlexander V. Chernikov 	RTSOCK_ATF_REQUIRE_MSG(rtm, sa != NULL, "GATEWAY is not set");
239e02d3fe7SAlexander V. Chernikov 	RTSOCK_ATF_REQUIRE_MSG(rtm, sa->sa_family == AF_LINK, "GW sa family is %d", sa->sa_family);
240e02d3fe7SAlexander V. Chernikov 	sdl = (struct sockaddr_dl *)sa;
241e02d3fe7SAlexander V. Chernikov 	RTSOCK_ATF_REQUIRE_MSG(rtm, sdl->sdl_index == ifindex, "GW ifindex is %d", sdl->sdl_index);
242775dc861SAlexander V. Chernikov }
243775dc861SAlexander V. Chernikov 
244775dc861SAlexander V. Chernikov /* TESTS */
245775dc861SAlexander V. Chernikov 
246775dc861SAlexander V. Chernikov #define	DECLARE_TEST_VARS					\
247775dc861SAlexander V. Chernikov 	char buffer[2048];					\
248775dc861SAlexander V. Chernikov 	struct rtsock_test_config *c;				\
249775dc861SAlexander V. Chernikov 	struct rt_msghdr *rtm = (struct rt_msghdr *)buffer;	\
250775dc861SAlexander V. Chernikov 	struct sockaddr *sa;					\
251775dc861SAlexander V. Chernikov 	int ret;						\
252775dc861SAlexander V. Chernikov 								\
253775dc861SAlexander V. Chernikov 
254775dc861SAlexander V. Chernikov #define	DESCRIBE_ROOT_TEST(_msg)	config_describe_root_test(tc, _msg)
255ddc75076SAlexander V. Chernikov #define	CLEANUP_AFTER_TEST	config_generic_cleanup(tc)
256775dc861SAlexander V. Chernikov 
257e02d3fe7SAlexander V. Chernikov #define	RTM_DECLARE_ROOT_TEST(_name, _descr)			\
258e02d3fe7SAlexander V. Chernikov ATF_TC_WITH_CLEANUP(_name);					\
259e02d3fe7SAlexander V. Chernikov ATF_TC_HEAD(_name, tc)						\
260e02d3fe7SAlexander V. Chernikov {								\
261e02d3fe7SAlexander V. Chernikov 	DESCRIBE_ROOT_TEST(_descr);				\
262e02d3fe7SAlexander V. Chernikov }								\
263e02d3fe7SAlexander V. Chernikov ATF_TC_CLEANUP(_name, tc)					\
264e02d3fe7SAlexander V. Chernikov {								\
265e02d3fe7SAlexander V. Chernikov 	CLEANUP_AFTER_TEST;					\
266e02d3fe7SAlexander V. Chernikov }
267775dc861SAlexander V. Chernikov 
268775dc861SAlexander V. Chernikov ATF_TC_WITH_CLEANUP(rtm_get_v4_exact_success);
269775dc861SAlexander V. Chernikov ATF_TC_HEAD(rtm_get_v4_exact_success, tc)
270775dc861SAlexander V. Chernikov {
271775dc861SAlexander V. Chernikov 	DESCRIBE_ROOT_TEST("Tests RTM_GET with exact prefix lookup on an interface prefix");
272775dc861SAlexander V. Chernikov }
273775dc861SAlexander V. Chernikov 
274775dc861SAlexander V. Chernikov ATF_TC_BODY(rtm_get_v4_exact_success, tc)
275775dc861SAlexander V. Chernikov {
276775dc861SAlexander V. Chernikov 	DECLARE_TEST_VARS;
277775dc861SAlexander V. Chernikov 
278775dc861SAlexander V. Chernikov 	c = presetup_ipv4(tc);
279775dc861SAlexander V. Chernikov 
280775dc861SAlexander V. Chernikov 	prepare_route_message(rtm, RTM_GET, (struct sockaddr *)&c->net4,
281775dc861SAlexander V. Chernikov 	    (struct sockaddr *)&c->mask4, NULL);
282775dc861SAlexander V. Chernikov 
283775dc861SAlexander V. Chernikov 	rtsock_send_rtm(c->rtsock_fd, rtm);
284775dc861SAlexander V. Chernikov 
285775dc861SAlexander V. Chernikov 	rtm = rtsock_read_rtm_reply(c->rtsock_fd, buffer, sizeof(buffer), rtm->rtm_seq);
286775dc861SAlexander V. Chernikov 
287775dc861SAlexander V. Chernikov 	/*
288775dc861SAlexander V. Chernikov 	 * RTM_GET: Report Metrics: len 240, pid: 45072, seq 42, errno 0, flags: <UP,DONE,PINNED>
289775dc861SAlexander V. Chernikov 	 * sockaddrs: 0x7 <DST,GATEWAY,NETMASK>
290775dc861SAlexander V. Chernikov 	 *  af=inet len=16 addr=192.0.2.0 hd={10, 02, 00{2}, C0, 00, 02, 00{9}}
291775dc861SAlexander V. Chernikov 	 *  af=link len=54 sdl_index=3 if_name=tap4242 hd={36, 12, 03, 00, 06, 00{49}}
292775dc861SAlexander V. Chernikov 	 *  af=inet len=16 addr=255.255.255.0 hd={10, 02, FF{5}, 00{9}}
293775dc861SAlexander V. Chernikov 	 */
294775dc861SAlexander V. Chernikov 
295775dc861SAlexander V. Chernikov 	verify_route_message(rtm, RTM_GET, (struct sockaddr *)&c->net4,
296775dc861SAlexander V. Chernikov 	    (struct sockaddr *)&c->mask4, NULL);
297775dc861SAlexander V. Chernikov 
298775dc861SAlexander V. Chernikov 	verify_route_message_extra(rtm, c->ifindex, RTF_UP | RTF_DONE | RTF_PINNED);
299775dc861SAlexander V. Chernikov 
300775dc861SAlexander V. Chernikov 	/* Explicitly verify gateway for the interface route */
301e02d3fe7SAlexander V. Chernikov 	verify_link_gateway(rtm, c->ifindex);
302775dc861SAlexander V. Chernikov 	sa = rtsock_find_rtm_sa(rtm, RTA_GATEWAY);
303775dc861SAlexander V. Chernikov 	RTSOCK_ATF_REQUIRE_MSG(rtm, sa != NULL, "GATEWAY is not set");
304775dc861SAlexander V. Chernikov 	RTSOCK_ATF_REQUIRE_MSG(rtm, sa->sa_family == AF_LINK, "GW sa family is %d", sa->sa_family);
305775dc861SAlexander V. Chernikov 	struct sockaddr_dl *sdl = (struct sockaddr_dl *)sa;
306775dc861SAlexander V. Chernikov 	RTSOCK_ATF_REQUIRE_MSG(rtm, sdl->sdl_index == c->ifindex, "GW ifindex is %d", sdl->sdl_index);
307775dc861SAlexander V. Chernikov }
308775dc861SAlexander V. Chernikov 
309775dc861SAlexander V. Chernikov ATF_TC_CLEANUP(rtm_get_v4_exact_success, tc)
310775dc861SAlexander V. Chernikov {
311775dc861SAlexander V. Chernikov 	CLEANUP_AFTER_TEST;
312775dc861SAlexander V. Chernikov }
313775dc861SAlexander V. Chernikov 
314775dc861SAlexander V. Chernikov ATF_TC_WITH_CLEANUP(rtm_get_v4_lpm_success);
315775dc861SAlexander V. Chernikov ATF_TC_HEAD(rtm_get_v4_lpm_success, tc)
316775dc861SAlexander V. Chernikov {
317775dc861SAlexander V. Chernikov 	DESCRIBE_ROOT_TEST("Tests RTM_GET with address lookup on an existing prefix");
318775dc861SAlexander V. Chernikov }
319775dc861SAlexander V. Chernikov 
320775dc861SAlexander V. Chernikov ATF_TC_BODY(rtm_get_v4_lpm_success, tc)
321775dc861SAlexander V. Chernikov {
322775dc861SAlexander V. Chernikov 	DECLARE_TEST_VARS;
323775dc861SAlexander V. Chernikov 
324775dc861SAlexander V. Chernikov 	c = presetup_ipv4(tc);
325775dc861SAlexander V. Chernikov 
326775dc861SAlexander V. Chernikov 	prepare_route_message(rtm, RTM_GET, (struct sockaddr *)&c->net4, NULL, NULL);
327775dc861SAlexander V. Chernikov 
328775dc861SAlexander V. Chernikov 	rtsock_send_rtm(c->rtsock_fd, rtm);
329775dc861SAlexander V. Chernikov 
330e02d3fe7SAlexander V. Chernikov 	rtm = rtsock_read_rtm_reply(c->rtsock_fd, buffer, sizeof(buffer), rtm->rtm_seq);
331775dc861SAlexander V. Chernikov 
332775dc861SAlexander V. Chernikov 	/*
333775dc861SAlexander V. Chernikov 	 * RTM_GET: Report Metrics: len 312, pid: 67074, seq 1, errno 0, flags:<UP,DONE,PINNED>
334775dc861SAlexander V. Chernikov 	 * locks:  inits:
335775dc861SAlexander V. Chernikov 	 * sockaddrs: <DST,GATEWAY,NETMASK,IFP,IFA>
336775dc861SAlexander V. Chernikov 	 * 10.0.0.0 link#1 255.255.255.0 vtnet0:52.54.0.42.f.ef 10.0.0.157
337775dc861SAlexander V. Chernikov 	 */
338775dc861SAlexander V. Chernikov 
339775dc861SAlexander V. Chernikov 	verify_route_message(rtm, RTM_GET, (struct sockaddr *)&c->net4,
340775dc861SAlexander V. Chernikov 	    (struct sockaddr *)&c->mask4, NULL);
341775dc861SAlexander V. Chernikov 
342775dc861SAlexander V. Chernikov 	verify_route_message_extra(rtm, c->ifindex, RTF_UP | RTF_DONE | RTF_PINNED);
343775dc861SAlexander V. Chernikov }
344775dc861SAlexander V. Chernikov 
345775dc861SAlexander V. Chernikov ATF_TC_CLEANUP(rtm_get_v4_lpm_success, tc)
346775dc861SAlexander V. Chernikov {
347775dc861SAlexander V. Chernikov 	CLEANUP_AFTER_TEST;
348775dc861SAlexander V. Chernikov }
349775dc861SAlexander V. Chernikov 
350775dc861SAlexander V. Chernikov 
351775dc861SAlexander V. Chernikov ATF_TC_WITH_CLEANUP(rtm_get_v4_empty_dst_failure);
352775dc861SAlexander V. Chernikov ATF_TC_HEAD(rtm_get_v4_empty_dst_failure, tc)
353775dc861SAlexander V. Chernikov {
354775dc861SAlexander V. Chernikov 
355775dc861SAlexander V. Chernikov 	DESCRIBE_ROOT_TEST("Tests RTM_GET with empty DST addr");
356775dc861SAlexander V. Chernikov }
357775dc861SAlexander V. Chernikov 
358775dc861SAlexander V. Chernikov ATF_TC_BODY(rtm_get_v4_empty_dst_failure, tc)
359775dc861SAlexander V. Chernikov {
360775dc861SAlexander V. Chernikov 	DECLARE_TEST_VARS;
361272bd698SAlexander V. Chernikov 	struct rtsock_config_options co;
362775dc861SAlexander V. Chernikov 
363272bd698SAlexander V. Chernikov 	bzero(&co, sizeof(co));
364272bd698SAlexander V. Chernikov 	co.num_interfaces = 0;
365272bd698SAlexander V. Chernikov 
366272bd698SAlexander V. Chernikov 	c = config_setup(tc,&co);
367775dc861SAlexander V. Chernikov 	c->rtsock_fd = rtsock_setup_socket();
368775dc861SAlexander V. Chernikov 
369775dc861SAlexander V. Chernikov 	rtsock_prepare_route_message(rtm, RTM_GET, NULL,
370775dc861SAlexander V. Chernikov 	    (struct sockaddr *)&c->mask4, NULL);
371775dc861SAlexander V. Chernikov 	rtsock_update_rtm_len(rtm);
372775dc861SAlexander V. Chernikov 
37367f2f67fSAlex Richardson 	ATF_CHECK_ERRNO(EINVAL, write(c->rtsock_fd, rtm, rtm->rtm_msglen) == -1);
374775dc861SAlexander V. Chernikov }
375775dc861SAlexander V. Chernikov 
376775dc861SAlexander V. Chernikov ATF_TC_CLEANUP(rtm_get_v4_empty_dst_failure, tc)
377775dc861SAlexander V. Chernikov {
378775dc861SAlexander V. Chernikov 	CLEANUP_AFTER_TEST;
379775dc861SAlexander V. Chernikov }
380775dc861SAlexander V. Chernikov 
38167f2f67fSAlex Richardson ATF_TC_WITH_CLEANUP(rtm_get_v4_hostbits_success);
38267f2f67fSAlex Richardson ATF_TC_HEAD(rtm_get_v4_hostbits_success, tc)
383775dc861SAlexander V. Chernikov {
384775dc861SAlexander V. Chernikov 	DESCRIBE_ROOT_TEST("Tests RTM_GET with prefix with some hosts-bits set");
385775dc861SAlexander V. Chernikov }
386775dc861SAlexander V. Chernikov 
38767f2f67fSAlex Richardson ATF_TC_BODY(rtm_get_v4_hostbits_success, tc)
388775dc861SAlexander V. Chernikov {
389775dc861SAlexander V. Chernikov 	DECLARE_TEST_VARS;
390775dc861SAlexander V. Chernikov 
391775dc861SAlexander V. Chernikov 	c = presetup_ipv4(tc);
392775dc861SAlexander V. Chernikov 
393775dc861SAlexander V. Chernikov 	/* Q the same prefix */
394775dc861SAlexander V. Chernikov 	rtsock_prepare_route_message(rtm, RTM_GET, (struct sockaddr *)&c->addr4,
395775dc861SAlexander V. Chernikov 	    (struct sockaddr *)&c->mask4, NULL);
396775dc861SAlexander V. Chernikov 	rtsock_update_rtm_len(rtm);
397775dc861SAlexander V. Chernikov 
39867f2f67fSAlex Richardson 	ATF_REQUIRE_ERRNO(0, true);
39967f2f67fSAlex Richardson 	ATF_CHECK_ERRNO(0, write(c->rtsock_fd, rtm, rtm->rtm_msglen) > 0);
400775dc861SAlexander V. Chernikov }
401775dc861SAlexander V. Chernikov 
40267f2f67fSAlex Richardson ATF_TC_CLEANUP(rtm_get_v4_hostbits_success, tc)
403775dc861SAlexander V. Chernikov {
404775dc861SAlexander V. Chernikov 	CLEANUP_AFTER_TEST;
405775dc861SAlexander V. Chernikov }
406775dc861SAlexander V. Chernikov 
407775dc861SAlexander V. Chernikov ATF_TC_WITH_CLEANUP(rtm_add_v4_gw_direct_success);
408775dc861SAlexander V. Chernikov ATF_TC_HEAD(rtm_add_v4_gw_direct_success, tc)
409775dc861SAlexander V. Chernikov {
410775dc861SAlexander V. Chernikov 	DESCRIBE_ROOT_TEST("Tests IPv4 route addition with directly-reachable GW specified by IP");
411775dc861SAlexander V. Chernikov }
412775dc861SAlexander V. Chernikov 
413775dc861SAlexander V. Chernikov ATF_TC_BODY(rtm_add_v4_gw_direct_success, tc)
414775dc861SAlexander V. Chernikov {
415775dc861SAlexander V. Chernikov 	DECLARE_TEST_VARS;
416775dc861SAlexander V. Chernikov 
417775dc861SAlexander V. Chernikov 	c = presetup_ipv4(tc);
418775dc861SAlexander V. Chernikov 
419775dc861SAlexander V. Chernikov 	/* Create IPv4 subnetwork with smaller prefix */
420775dc861SAlexander V. Chernikov 	struct sockaddr_in mask4;
421775dc861SAlexander V. Chernikov 	struct sockaddr_in net4;
422775dc861SAlexander V. Chernikov 	struct sockaddr_in gw4;
423775dc861SAlexander V. Chernikov 	prepare_v4_network(c, &net4, &mask4, &gw4);
424775dc861SAlexander V. Chernikov 
425775dc861SAlexander V. Chernikov 	prepare_route_message(rtm, RTM_ADD, (struct sockaddr *)&net4,
426775dc861SAlexander V. Chernikov 	    (struct sockaddr *)&mask4, (struct sockaddr *)&gw4);
427775dc861SAlexander V. Chernikov 
428775dc861SAlexander V. Chernikov 	rtsock_send_rtm(c->rtsock_fd, rtm);
429775dc861SAlexander V. Chernikov 	rtm = rtsock_read_rtm_reply(c->rtsock_fd, buffer, sizeof(buffer), rtm->rtm_seq);
430775dc861SAlexander V. Chernikov 
431775dc861SAlexander V. Chernikov 	/*
432775dc861SAlexander V. Chernikov 	 * RTM_ADD: Add Route: len 200, pid: 46068, seq 42, errno 0, flags:<GATEWAY,DONE,STATIC>
433775dc861SAlexander V. Chernikov 	 * locks:  inits:
434775dc861SAlexander V. Chernikov 	 * sockaddrs: <DST,GATEWAY,NETMASK>
435775dc861SAlexander V. Chernikov 	 *  192.0.2.0 192.0.2.254 255.255.255.128
436775dc861SAlexander V. Chernikov 	 */
437775dc861SAlexander V. Chernikov 
438775dc861SAlexander V. Chernikov 	verify_route_message(rtm, RTM_ADD, (struct sockaddr *)&net4,
439775dc861SAlexander V. Chernikov 	    (struct sockaddr *)&mask4, (struct sockaddr *)&gw4);
4401b95005eSAlexander V. Chernikov 	verify_route_message_extra(rtm, c->ifindex,
4411b95005eSAlexander V. Chernikov 	    RTF_UP | RTF_DONE | RTF_GATEWAY | RTF_STATIC);
442775dc861SAlexander V. Chernikov }
443775dc861SAlexander V. Chernikov 
444775dc861SAlexander V. Chernikov ATF_TC_CLEANUP(rtm_add_v4_gw_direct_success, tc)
445775dc861SAlexander V. Chernikov {
446775dc861SAlexander V. Chernikov 	CLEANUP_AFTER_TEST;
447775dc861SAlexander V. Chernikov }
448775dc861SAlexander V. Chernikov 
44967f2f67fSAlex Richardson RTM_DECLARE_ROOT_TEST(rtm_add_v4_no_rtf_host_success,
45067f2f67fSAlex Richardson     "Tests success with netmask sa and RTF_HOST inconsistency");
4515676d488SAlexander V. Chernikov 
45267f2f67fSAlex Richardson ATF_TC_BODY(rtm_add_v4_no_rtf_host_success, tc)
4535676d488SAlexander V. Chernikov {
4545676d488SAlexander V. Chernikov 	DECLARE_TEST_VARS;
4555676d488SAlexander V. Chernikov 
4565676d488SAlexander V. Chernikov 	c = presetup_ipv4(tc);
4575676d488SAlexander V. Chernikov 
4585676d488SAlexander V. Chernikov 	/* Create IPv4 subnetwork with smaller prefix */
4595676d488SAlexander V. Chernikov 	struct sockaddr_in mask4;
4605676d488SAlexander V. Chernikov 	struct sockaddr_in net4;
4615676d488SAlexander V. Chernikov 	struct sockaddr_in gw4;
4625676d488SAlexander V. Chernikov 	prepare_v4_network(c, &net4, &mask4, &gw4);
4635676d488SAlexander V. Chernikov 
4645676d488SAlexander V. Chernikov 	prepare_route_message(rtm, RTM_ADD, (struct sockaddr *)&net4,
4655676d488SAlexander V. Chernikov 	    NULL, (struct sockaddr *)&gw4);
4665676d488SAlexander V. Chernikov 	rtsock_update_rtm_len(rtm);
4675676d488SAlexander V. Chernikov 
4685676d488SAlexander V. Chernikov 	/* RTF_HOST is NOT specified, while netmask is empty */
46967f2f67fSAlex Richardson 	ATF_REQUIRE_ERRNO(0, true);
47067f2f67fSAlex Richardson 	ATF_CHECK_ERRNO(0, write(c->rtsock_fd, rtm, rtm->rtm_msglen) > 0);
4715676d488SAlexander V. Chernikov }
4725676d488SAlexander V. Chernikov 
473775dc861SAlexander V. Chernikov ATF_TC_WITH_CLEANUP(rtm_del_v4_prefix_nogw_success);
474775dc861SAlexander V. Chernikov ATF_TC_HEAD(rtm_del_v4_prefix_nogw_success, tc)
475775dc861SAlexander V. Chernikov {
476775dc861SAlexander V. Chernikov 	DESCRIBE_ROOT_TEST("Tests IPv4 route removal without specifying gateway");
477775dc861SAlexander V. Chernikov }
478775dc861SAlexander V. Chernikov 
479775dc861SAlexander V. Chernikov ATF_TC_BODY(rtm_del_v4_prefix_nogw_success, tc)
480775dc861SAlexander V. Chernikov {
481775dc861SAlexander V. Chernikov 	DECLARE_TEST_VARS;
482775dc861SAlexander V. Chernikov 
483775dc861SAlexander V. Chernikov 	c = presetup_ipv4(tc);
484775dc861SAlexander V. Chernikov 
485775dc861SAlexander V. Chernikov 	/* Create IPv4 subnetwork with smaller prefix */
486775dc861SAlexander V. Chernikov 	struct sockaddr_in mask4;
487775dc861SAlexander V. Chernikov 	struct sockaddr_in net4;
488775dc861SAlexander V. Chernikov 	struct sockaddr_in gw4;
489775dc861SAlexander V. Chernikov 	prepare_v4_network(c, &net4, &mask4, &gw4);
490775dc861SAlexander V. Chernikov 
491775dc861SAlexander V. Chernikov 	prepare_route_message(rtm, RTM_ADD, (struct sockaddr *)&net4,
492775dc861SAlexander V. Chernikov 	    (struct sockaddr *)&mask4, (struct sockaddr *)&gw4);
493775dc861SAlexander V. Chernikov 
494775dc861SAlexander V. Chernikov 	rtsock_send_rtm(c->rtsock_fd, rtm);
495775dc861SAlexander V. Chernikov 
496775dc861SAlexander V. Chernikov 	/* Route has been added successfully, try to delete it */
497775dc861SAlexander V. Chernikov 	prepare_route_message(rtm, RTM_DELETE, (struct sockaddr *)&net4,
498775dc861SAlexander V. Chernikov 	    (struct sockaddr *)&mask4, NULL);
499775dc861SAlexander V. Chernikov 
500775dc861SAlexander V. Chernikov 	rtsock_send_rtm(c->rtsock_fd, rtm);
501775dc861SAlexander V. Chernikov 
502775dc861SAlexander V. Chernikov 	rtm = rtsock_read_rtm_reply(c->rtsock_fd, buffer, sizeof(buffer), rtm->rtm_seq);
503775dc861SAlexander V. Chernikov 
504775dc861SAlexander V. Chernikov 	/*
505775dc861SAlexander V. Chernikov 	 * RTM_DELETE: Delete Route: len 200, pid: 46417, seq 43, errno 0, flags: <GATEWAY,DONE,STATIC>
506775dc861SAlexander V. Chernikov 	 * sockaddrs: 0x7 <DST,GATEWAY,NETMASK>
507775dc861SAlexander V. Chernikov 	 *  af=inet len=16 addr=192.0.2.0 hd={10, 02, 00{2}, C0, 00, 02, 00{9}}
508775dc861SAlexander V. Chernikov 	 *  af=inet len=16 addr=192.0.2.254 hd={10, 02, 00{2}, C0, 00, 02, FE, 00{8}}
509775dc861SAlexander V. Chernikov 	 *  af=inet len=16 addr=255.255.255.128 hd={10, 02, FF{5}, 80, 00{8}}
510775dc861SAlexander V. Chernikov 	 */
511775dc861SAlexander V. Chernikov 	verify_route_message(rtm, RTM_DELETE, (struct sockaddr *)&net4,
512775dc861SAlexander V. Chernikov 	    (struct sockaddr *)&mask4, (struct sockaddr *)&gw4);
513775dc861SAlexander V. Chernikov 
514775dc861SAlexander V. Chernikov 	verify_route_message_extra(rtm, c->ifindex, RTF_DONE | RTF_GATEWAY | RTF_STATIC);
515775dc861SAlexander V. Chernikov }
516775dc861SAlexander V. Chernikov 
517775dc861SAlexander V. Chernikov ATF_TC_CLEANUP(rtm_del_v4_prefix_nogw_success, tc)
518775dc861SAlexander V. Chernikov {
519775dc861SAlexander V. Chernikov 	CLEANUP_AFTER_TEST;
520775dc861SAlexander V. Chernikov }
521775dc861SAlexander V. Chernikov 
522272bd698SAlexander V. Chernikov RTM_DECLARE_ROOT_TEST(rtm_change_v4_gw_success,
523272bd698SAlexander V. Chernikov     "Tests IPv4 gateway change");
524272bd698SAlexander V. Chernikov 
525272bd698SAlexander V. Chernikov ATF_TC_BODY(rtm_change_v4_gw_success, tc)
526272bd698SAlexander V. Chernikov {
527272bd698SAlexander V. Chernikov 	DECLARE_TEST_VARS;
528272bd698SAlexander V. Chernikov 	struct rtsock_config_options co;
529272bd698SAlexander V. Chernikov 
530272bd698SAlexander V. Chernikov 	bzero(&co, sizeof(co));
531272bd698SAlexander V. Chernikov 	co.num_interfaces = 2;
532272bd698SAlexander V. Chernikov 
533272bd698SAlexander V. Chernikov 	c = config_setup(tc, &co);
534272bd698SAlexander V. Chernikov 	jump_vnet(c, tc);
535272bd698SAlexander V. Chernikov 
536272bd698SAlexander V. Chernikov 	ret = iface_turn_up(c->ifnames[0]);
537272bd698SAlexander V. Chernikov 	ATF_REQUIRE_MSG(ret == 0, "Unable to turn up %s", c->ifnames[0]);
538272bd698SAlexander V. Chernikov 	ret = iface_turn_up(c->ifnames[1]);
539272bd698SAlexander V. Chernikov 	ATF_REQUIRE_MSG(ret == 0, "Unable to turn up %s", c->ifnames[1]);
540272bd698SAlexander V. Chernikov 
541272bd698SAlexander V. Chernikov 	ret = iface_setup_addr(c->ifnames[0], c->addr4_str, c->plen4);
542272bd698SAlexander V. Chernikov 	ATF_REQUIRE_MSG(ret == 0, "ifconfig failed");
543272bd698SAlexander V. Chernikov 
544272bd698SAlexander V. Chernikov 	/* Use 198.51.100.0/24 "TEST-NET-2" for the second interface */
545272bd698SAlexander V. Chernikov 	ret = iface_setup_addr(c->ifnames[1], "198.51.100.1", 24);
546272bd698SAlexander V. Chernikov 	ATF_REQUIRE_MSG(ret == 0, "ifconfig failed");
547272bd698SAlexander V. Chernikov 
548272bd698SAlexander V. Chernikov 	c->rtsock_fd = rtsock_setup_socket();
549272bd698SAlexander V. Chernikov 
550272bd698SAlexander V. Chernikov 	/* Create IPv4 subnetwork with smaller prefix */
551272bd698SAlexander V. Chernikov 	struct sockaddr_in mask4;
552272bd698SAlexander V. Chernikov 	struct sockaddr_in net4;
553272bd698SAlexander V. Chernikov 	struct sockaddr_in gw4;
554272bd698SAlexander V. Chernikov 	prepare_v4_network(c, &net4, &mask4, &gw4);
555272bd698SAlexander V. Chernikov 
556272bd698SAlexander V. Chernikov 	prepare_route_message(rtm, RTM_ADD, (struct sockaddr *)&net4,
557272bd698SAlexander V. Chernikov 	    (struct sockaddr *)&mask4, (struct sockaddr *)&gw4);
558272bd698SAlexander V. Chernikov 
559272bd698SAlexander V. Chernikov 	rtsock_send_rtm(c->rtsock_fd, rtm);
560272bd698SAlexander V. Chernikov 	rtm = rtsock_read_rtm_reply(c->rtsock_fd, buffer, sizeof(buffer), rtm->rtm_seq);
561272bd698SAlexander V. Chernikov 
562272bd698SAlexander V. Chernikov 	verify_route_message(rtm, RTM_ADD, (struct sockaddr *)&net4,
563272bd698SAlexander V. Chernikov 	    (struct sockaddr *)&mask4, (struct sockaddr *)&gw4);
564272bd698SAlexander V. Chernikov 
565272bd698SAlexander V. Chernikov 	/* Change gateway to the one on desiding on the other interface */
566272bd698SAlexander V. Chernikov 	inet_pton(AF_INET, "198.51.100.2", &gw4.sin_addr.s_addr);
567272bd698SAlexander V. Chernikov 	prepare_route_message(rtm, RTM_CHANGE, (struct sockaddr *)&net4,
568272bd698SAlexander V. Chernikov 	    (struct sockaddr *)&mask4, (struct sockaddr *)&gw4);
569272bd698SAlexander V. Chernikov 	rtsock_send_rtm(c->rtsock_fd, rtm);
570272bd698SAlexander V. Chernikov 
571272bd698SAlexander V. Chernikov 	rtm = rtsock_read_rtm_reply(c->rtsock_fd, buffer, sizeof(buffer), rtm->rtm_seq);
572272bd698SAlexander V. Chernikov 
573272bd698SAlexander V. Chernikov 	verify_route_message(rtm, RTM_CHANGE, (struct sockaddr *)&net4,
574272bd698SAlexander V. Chernikov 	    (struct sockaddr *)&mask4, (struct sockaddr *)&gw4);
575272bd698SAlexander V. Chernikov 
576272bd698SAlexander V. Chernikov 	verify_route_message_extra(rtm, if_nametoindex(c->ifnames[1]),
5771b95005eSAlexander V. Chernikov 	    RTF_UP | RTF_DONE | RTF_GATEWAY | RTF_STATIC);
578272bd698SAlexander V. Chernikov 
579272bd698SAlexander V. Chernikov 	/* Verify the change has actually taken place */
580272bd698SAlexander V. Chernikov 	prepare_route_message(rtm, RTM_GET, (struct sockaddr *)&net4,
581272bd698SAlexander V. Chernikov 	    (struct sockaddr *)&mask4, NULL);
582272bd698SAlexander V. Chernikov 
583272bd698SAlexander V. Chernikov 	rtsock_send_rtm(c->rtsock_fd, rtm);
584272bd698SAlexander V. Chernikov 
585272bd698SAlexander V. Chernikov 	/*
586272bd698SAlexander V. Chernikov 	 * RTM_GET: len 200, pid: 3894, seq 44, errno 0, flags: <UP,GATEWAY,DONE,STATIC>
587272bd698SAlexander V. Chernikov 	 *  sockaddrs: 0x7 <DST,GATEWAY,NETMASK>
588272bd698SAlexander V. Chernikov  	 *  af=inet len=16 addr=192.0.2.0 hd={x10, x02, x00{2}, xC0, x00, x02, x00{9}}
589272bd698SAlexander V. Chernikov 	 *  af=inet len=16 addr=198.51.100.2 hd={x10, x02, x00{2}, xC6, x33, x64, x02, x00{8}}
590272bd698SAlexander V. Chernikov 	 *  af=inet len=16 addr=255.255.255.128 hd={x10, x02, xFF, xFF, xFF, xFF, xFF, x80, x00{8}}
591272bd698SAlexander V. Chernikov 	 */
592272bd698SAlexander V. Chernikov 
593272bd698SAlexander V. Chernikov 	rtm = rtsock_read_rtm_reply(c->rtsock_fd, buffer, sizeof(buffer), rtm->rtm_seq);
594272bd698SAlexander V. Chernikov 	verify_route_message_extra(rtm, if_nametoindex(c->ifnames[1]),
595272bd698SAlexander V. Chernikov 	    RTF_UP | RTF_DONE | RTF_GATEWAY | RTF_STATIC);
596272bd698SAlexander V. Chernikov 
597272bd698SAlexander V. Chernikov }
598272bd698SAlexander V. Chernikov 
599272bd698SAlexander V. Chernikov RTM_DECLARE_ROOT_TEST(rtm_change_v4_mtu_success,
600272bd698SAlexander V. Chernikov     "Tests IPv4 path mtu change");
601272bd698SAlexander V. Chernikov 
602272bd698SAlexander V. Chernikov ATF_TC_BODY(rtm_change_v4_mtu_success, tc)
603272bd698SAlexander V. Chernikov {
604272bd698SAlexander V. Chernikov 	DECLARE_TEST_VARS;
605272bd698SAlexander V. Chernikov 
606272bd698SAlexander V. Chernikov 	unsigned long test_mtu = 1442;
607272bd698SAlexander V. Chernikov 
608272bd698SAlexander V. Chernikov 	c = presetup_ipv4(tc);
609272bd698SAlexander V. Chernikov 
610272bd698SAlexander V. Chernikov 	/* Create IPv4 subnetwork with smaller prefix */
611272bd698SAlexander V. Chernikov 	struct sockaddr_in mask4;
612272bd698SAlexander V. Chernikov 	struct sockaddr_in net4;
613272bd698SAlexander V. Chernikov 	struct sockaddr_in gw4;
614272bd698SAlexander V. Chernikov 	prepare_v4_network(c, &net4, &mask4, &gw4);
615272bd698SAlexander V. Chernikov 
616272bd698SAlexander V. Chernikov 	prepare_route_message(rtm, RTM_ADD, (struct sockaddr *)&net4,
617272bd698SAlexander V. Chernikov 	    (struct sockaddr *)&mask4, (struct sockaddr *)&gw4);
618272bd698SAlexander V. Chernikov 
619272bd698SAlexander V. Chernikov 	rtsock_send_rtm(c->rtsock_fd, rtm);
620272bd698SAlexander V. Chernikov 	rtm = rtsock_read_rtm_reply(c->rtsock_fd, buffer, sizeof(buffer), rtm->rtm_seq);
621272bd698SAlexander V. Chernikov 
622272bd698SAlexander V. Chernikov 	/* Change MTU */
623272bd698SAlexander V. Chernikov 	prepare_route_message(rtm, RTM_CHANGE, (struct sockaddr *)&net4,
624272bd698SAlexander V. Chernikov 	    (struct sockaddr *)&mask4, NULL);
625272bd698SAlexander V. Chernikov 	rtm->rtm_inits |= RTV_MTU;
626272bd698SAlexander V. Chernikov 	rtm->rtm_rmx.rmx_mtu = test_mtu;
627272bd698SAlexander V. Chernikov 
628272bd698SAlexander V. Chernikov 	rtsock_send_rtm(c->rtsock_fd, rtm);
629272bd698SAlexander V. Chernikov 	rtm = rtsock_read_rtm_reply(c->rtsock_fd, buffer, sizeof(buffer), rtm->rtm_seq);
630272bd698SAlexander V. Chernikov 
631272bd698SAlexander V. Chernikov 	verify_route_message(rtm, RTM_CHANGE, (struct sockaddr *)&net4,
632272bd698SAlexander V. Chernikov 	    (struct sockaddr *)&mask4, NULL);
633272bd698SAlexander V. Chernikov 
634272bd698SAlexander V. Chernikov 	RTSOCK_ATF_REQUIRE_MSG(rtm, rtm->rtm_rmx.rmx_mtu == test_mtu,
635272bd698SAlexander V. Chernikov 	    "expected mtu: %lu, got %lu", test_mtu, rtm->rtm_rmx.rmx_mtu);
636272bd698SAlexander V. Chernikov 
637272bd698SAlexander V. Chernikov 	/* Verify the change has actually taken place */
638272bd698SAlexander V. Chernikov 	prepare_route_message(rtm, RTM_GET, (struct sockaddr *)&net4,
639272bd698SAlexander V. Chernikov 	    (struct sockaddr *)&mask4, NULL);
640272bd698SAlexander V. Chernikov 
641272bd698SAlexander V. Chernikov 	rtsock_send_rtm(c->rtsock_fd, rtm);
642272bd698SAlexander V. Chernikov 	rtm = rtsock_read_rtm_reply(c->rtsock_fd, buffer, sizeof(buffer), rtm->rtm_seq);
643272bd698SAlexander V. Chernikov 
644272bd698SAlexander V. Chernikov 	RTSOCK_ATF_REQUIRE_MSG(rtm, rtm->rtm_rmx.rmx_mtu == test_mtu,
645272bd698SAlexander V. Chernikov 	    "expected mtu: %lu, got %lu", test_mtu, rtm->rtm_rmx.rmx_mtu);
646272bd698SAlexander V. Chernikov }
647272bd698SAlexander V. Chernikov 
6481b95005eSAlexander V. Chernikov RTM_DECLARE_ROOT_TEST(rtm_change_v4_flags_success,
6491b95005eSAlexander V. Chernikov     "Tests IPv4 path flags change");
6501b95005eSAlexander V. Chernikov 
6511b95005eSAlexander V. Chernikov ATF_TC_BODY(rtm_change_v4_flags_success, tc)
6521b95005eSAlexander V. Chernikov {
6531b95005eSAlexander V. Chernikov 	DECLARE_TEST_VARS;
6541b95005eSAlexander V. Chernikov 
6551b95005eSAlexander V. Chernikov 	uint32_t test_flags = RTF_PROTO1 | RTF_PROTO2 | RTF_PROTO3 | RTF_STATIC;
6561b95005eSAlexander V. Chernikov 	uint32_t desired_flags;
6571b95005eSAlexander V. Chernikov 
6581b95005eSAlexander V. Chernikov 	c = presetup_ipv4(tc);
6591b95005eSAlexander V. Chernikov 
6601b95005eSAlexander V. Chernikov 	/* Create IPv4 subnetwork with smaller prefix */
6611b95005eSAlexander V. Chernikov 	struct sockaddr_in mask4;
6621b95005eSAlexander V. Chernikov 	struct sockaddr_in net4;
6631b95005eSAlexander V. Chernikov 	struct sockaddr_in gw4;
6641b95005eSAlexander V. Chernikov 	prepare_v4_network(c, &net4, &mask4, &gw4);
6651b95005eSAlexander V. Chernikov 
6661b95005eSAlexander V. Chernikov 	prepare_route_message(rtm, RTM_ADD, (struct sockaddr *)&net4,
6671b95005eSAlexander V. Chernikov 	    (struct sockaddr *)&mask4, (struct sockaddr *)&gw4);
6681b95005eSAlexander V. Chernikov 
6691b95005eSAlexander V. Chernikov 	/* Set test flags during route addition */
6701b95005eSAlexander V. Chernikov 	desired_flags = RTF_UP | RTF_DONE | RTF_GATEWAY | test_flags;
6711b95005eSAlexander V. Chernikov 	rtm->rtm_flags |= test_flags;
6721b95005eSAlexander V. Chernikov 	rtsock_send_rtm(c->rtsock_fd, rtm);
6731b95005eSAlexander V. Chernikov 	rtm = rtsock_read_rtm_reply(c->rtsock_fd, buffer, sizeof(buffer), rtm->rtm_seq);
6741b95005eSAlexander V. Chernikov 
6751b95005eSAlexander V. Chernikov 	/* Change flags */
6761b95005eSAlexander V. Chernikov 	prepare_route_message(rtm, RTM_CHANGE, (struct sockaddr *)&net4,
6771b95005eSAlexander V. Chernikov 	    (struct sockaddr *)&mask4, NULL);
6781b95005eSAlexander V. Chernikov 	rtm->rtm_flags &= ~test_flags;
6791b95005eSAlexander V. Chernikov 	desired_flags &= ~test_flags;
6801b95005eSAlexander V. Chernikov 
6811b95005eSAlexander V. Chernikov 	rtsock_send_rtm(c->rtsock_fd, rtm);
6821b95005eSAlexander V. Chernikov 	rtm = rtsock_read_rtm_reply(c->rtsock_fd, buffer, sizeof(buffer), rtm->rtm_seq);
6831b95005eSAlexander V. Chernikov 
6841b95005eSAlexander V. Chernikov 	/* Verify updated flags */
6851b95005eSAlexander V. Chernikov 	verify_route_message_extra(rtm, c->ifindex, desired_flags | RTF_DONE);
6861b95005eSAlexander V. Chernikov 
6871b95005eSAlexander V. Chernikov 	/* Verify the change has actually taken place */
6881b95005eSAlexander V. Chernikov 	prepare_route_message(rtm, RTM_GET, (struct sockaddr *)&net4,
6891b95005eSAlexander V. Chernikov 	    (struct sockaddr *)&mask4, NULL);
6901b95005eSAlexander V. Chernikov 
6911b95005eSAlexander V. Chernikov 	rtsock_send_rtm(c->rtsock_fd, rtm);
6921b95005eSAlexander V. Chernikov 	rtm = rtsock_read_rtm_reply(c->rtsock_fd, buffer, sizeof(buffer), rtm->rtm_seq);
6931b95005eSAlexander V. Chernikov 
6941b95005eSAlexander V. Chernikov 	verify_route_message_extra(rtm, c->ifindex, desired_flags | RTF_DONE);
6951b95005eSAlexander V. Chernikov }
6961b95005eSAlexander V. Chernikov 
697272bd698SAlexander V. Chernikov 
698775dc861SAlexander V. Chernikov ATF_TC_WITH_CLEANUP(rtm_add_v6_gu_gw_gu_direct_success);
699775dc861SAlexander V. Chernikov ATF_TC_HEAD(rtm_add_v6_gu_gw_gu_direct_success, tc)
700775dc861SAlexander V. Chernikov {
701775dc861SAlexander V. Chernikov 	DESCRIBE_ROOT_TEST("Tests IPv6 global unicast prefix addition with directly-reachable GU GW");
702775dc861SAlexander V. Chernikov }
703775dc861SAlexander V. Chernikov 
704775dc861SAlexander V. Chernikov ATF_TC_BODY(rtm_add_v6_gu_gw_gu_direct_success, tc)
705775dc861SAlexander V. Chernikov {
706775dc861SAlexander V. Chernikov 	DECLARE_TEST_VARS;
707775dc861SAlexander V. Chernikov 
708775dc861SAlexander V. Chernikov 	c = presetup_ipv6(tc);
709775dc861SAlexander V. Chernikov 
710775dc861SAlexander V. Chernikov 	/* Create IPv6 subnetwork with smaller prefix */
711775dc861SAlexander V. Chernikov 	struct sockaddr_in6 mask6;
712775dc861SAlexander V. Chernikov 	struct sockaddr_in6 net6;
713775dc861SAlexander V. Chernikov 	struct sockaddr_in6 gw6;
714775dc861SAlexander V. Chernikov 	prepare_v6_network(c, &net6, &mask6, &gw6);
715775dc861SAlexander V. Chernikov 
716775dc861SAlexander V. Chernikov 	prepare_route_message(rtm, RTM_ADD, (struct sockaddr *)&net6,
717775dc861SAlexander V. Chernikov 	    (struct sockaddr *)&mask6, (struct sockaddr *)&gw6);
718775dc861SAlexander V. Chernikov 
719775dc861SAlexander V. Chernikov 	rtsock_send_rtm(c->rtsock_fd, rtm);
720775dc861SAlexander V. Chernikov 	rtm = rtsock_read_rtm_reply(c->rtsock_fd, buffer, sizeof(buffer), rtm->rtm_seq);
721775dc861SAlexander V. Chernikov 
722775dc861SAlexander V. Chernikov 	/*
723775dc861SAlexander V. Chernikov 	 * RTM_ADD: Add Route: len 200, pid: 46068, seq 42, errno 0, flags:<GATEWAY,DONE,STATIC>
724775dc861SAlexander V. Chernikov 	 * locks:  inits:
725775dc861SAlexander V. Chernikov 	 * sockaddrs: <DST,GATEWAY,NETMASK>
726775dc861SAlexander V. Chernikov 	 *  192.0.2.0 192.0.2.254 255.255.255.128
727775dc861SAlexander V. Chernikov 	 */
728775dc861SAlexander V. Chernikov 
729775dc861SAlexander V. Chernikov 	verify_route_message(rtm, RTM_ADD, (struct sockaddr *)&net6,
730775dc861SAlexander V. Chernikov 	    (struct sockaddr *)&mask6, (struct sockaddr *)&gw6);
731775dc861SAlexander V. Chernikov 
7321b95005eSAlexander V. Chernikov 	verify_route_message_extra(rtm, c->ifindex,
7331b95005eSAlexander V. Chernikov 	    RTF_UP | RTF_DONE | RTF_GATEWAY | RTF_STATIC);
734775dc861SAlexander V. Chernikov }
735775dc861SAlexander V. Chernikov 
736775dc861SAlexander V. Chernikov ATF_TC_CLEANUP(rtm_add_v6_gu_gw_gu_direct_success, tc)
737775dc861SAlexander V. Chernikov {
738775dc861SAlexander V. Chernikov 	CLEANUP_AFTER_TEST;
739775dc861SAlexander V. Chernikov }
740775dc861SAlexander V. Chernikov 
741775dc861SAlexander V. Chernikov ATF_TC_WITH_CLEANUP(rtm_del_v6_gu_prefix_nogw_success);
742775dc861SAlexander V. Chernikov ATF_TC_HEAD(rtm_del_v6_gu_prefix_nogw_success, tc)
743775dc861SAlexander V. Chernikov {
744775dc861SAlexander V. Chernikov 
745775dc861SAlexander V. Chernikov 	DESCRIBE_ROOT_TEST("Tests IPv6 global unicast prefix removal without specifying gateway");
746775dc861SAlexander V. Chernikov }
747775dc861SAlexander V. Chernikov 
748775dc861SAlexander V. Chernikov ATF_TC_BODY(rtm_del_v6_gu_prefix_nogw_success, tc)
749775dc861SAlexander V. Chernikov {
750775dc861SAlexander V. Chernikov 	DECLARE_TEST_VARS;
751775dc861SAlexander V. Chernikov 
752775dc861SAlexander V. Chernikov 	c = presetup_ipv6(tc);
753775dc861SAlexander V. Chernikov 
754775dc861SAlexander V. Chernikov 	/* Create IPv6 subnetwork with smaller prefix */
755775dc861SAlexander V. Chernikov 	struct sockaddr_in6 mask6;
756775dc861SAlexander V. Chernikov 	struct sockaddr_in6 net6;
757775dc861SAlexander V. Chernikov 	struct sockaddr_in6 gw6;
758775dc861SAlexander V. Chernikov 	prepare_v6_network(c, &net6, &mask6, &gw6);
759775dc861SAlexander V. Chernikov 
760775dc861SAlexander V. Chernikov 	prepare_route_message(rtm, RTM_ADD, (struct sockaddr *)&net6,
761775dc861SAlexander V. Chernikov 	    (struct sockaddr *)&mask6, (struct sockaddr *)&gw6);
762775dc861SAlexander V. Chernikov 
763775dc861SAlexander V. Chernikov 	rtsock_send_rtm(c->rtsock_fd, rtm);
764775dc861SAlexander V. Chernikov 
765775dc861SAlexander V. Chernikov 	/* Route has been added successfully, try to delete it */
766775dc861SAlexander V. Chernikov 	prepare_route_message(rtm, RTM_DELETE, (struct sockaddr *)&net6,
767775dc861SAlexander V. Chernikov 	    (struct sockaddr *)&mask6, NULL);
768775dc861SAlexander V. Chernikov 
769775dc861SAlexander V. Chernikov 	rtsock_send_rtm(c->rtsock_fd, rtm);
770775dc861SAlexander V. Chernikov 	rtm = rtsock_read_rtm_reply(c->rtsock_fd, buffer, sizeof(buffer), rtm->rtm_seq);
771775dc861SAlexander V. Chernikov 
772775dc861SAlexander V. Chernikov 	/*
773775dc861SAlexander V. Chernikov 	 * RTM_DELETE: Delete Route: len 200, pid: 46417, seq 43, errno 0, flags: <GATEWAY,DONE,STATIC>
774775dc861SAlexander V. Chernikov 	 * sockaddrs: 0x7 <DST,GATEWAY,NETMASK>
775775dc861SAlexander V. Chernikov 	 *  af=inet len=16 addr=192.0.2.0 hd={10, 02, 00{2}, C0, 00, 02, 00{9}}
776775dc861SAlexander V. Chernikov 	 *  af=inet len=16 addr=192.0.2.254 hd={10, 02, 00{2}, C0, 00, 02, FE, 00{8}}
777775dc861SAlexander V. Chernikov 	 *  af=inet len=16 addr=255.255.255.128 hd={10, 02, FF{5}, 80, 00{8}}
778775dc861SAlexander V. Chernikov 	 */
779775dc861SAlexander V. Chernikov 
780775dc861SAlexander V. Chernikov 	verify_route_message(rtm, RTM_DELETE, (struct sockaddr *)&net6,
781775dc861SAlexander V. Chernikov 	    (struct sockaddr *)&mask6, (struct sockaddr *)&gw6);
782775dc861SAlexander V. Chernikov 	verify_route_message_extra(rtm, c->ifindex, RTF_DONE | RTF_GATEWAY | RTF_STATIC);
783775dc861SAlexander V. Chernikov }
784775dc861SAlexander V. Chernikov 
785775dc861SAlexander V. Chernikov ATF_TC_CLEANUP(rtm_del_v6_gu_prefix_nogw_success, tc)
786775dc861SAlexander V. Chernikov {
787775dc861SAlexander V. Chernikov 	CLEANUP_AFTER_TEST;
788775dc861SAlexander V. Chernikov }
789775dc861SAlexander V. Chernikov 
790272bd698SAlexander V. Chernikov RTM_DECLARE_ROOT_TEST(rtm_change_v6_gw_success,
791272bd698SAlexander V. Chernikov     "Tests IPv6 gateway change");
792272bd698SAlexander V. Chernikov 
793272bd698SAlexander V. Chernikov ATF_TC_BODY(rtm_change_v6_gw_success, tc)
794272bd698SAlexander V. Chernikov {
795272bd698SAlexander V. Chernikov 	DECLARE_TEST_VARS;
796272bd698SAlexander V. Chernikov 	struct rtsock_config_options co;
797272bd698SAlexander V. Chernikov 
798272bd698SAlexander V. Chernikov 	bzero(&co, sizeof(co));
799272bd698SAlexander V. Chernikov 	co.num_interfaces = 2;
800272bd698SAlexander V. Chernikov 
801272bd698SAlexander V. Chernikov 	c = config_setup(tc, &co);
802272bd698SAlexander V. Chernikov 	jump_vnet(c, tc);
803272bd698SAlexander V. Chernikov 
804272bd698SAlexander V. Chernikov 	ret = iface_turn_up(c->ifnames[0]);
805272bd698SAlexander V. Chernikov 	ATF_REQUIRE_MSG(ret == 0, "Unable to turn up %s", c->ifnames[0]);
806272bd698SAlexander V. Chernikov 	ret = iface_turn_up(c->ifnames[1]);
807272bd698SAlexander V. Chernikov 	ATF_REQUIRE_MSG(ret == 0, "Unable to turn up %s", c->ifnames[1]);
808272bd698SAlexander V. Chernikov 
809272bd698SAlexander V. Chernikov 	ret = iface_enable_ipv6(c->ifnames[0]);
810272bd698SAlexander V. Chernikov 	ATF_REQUIRE_MSG(ret == 0, "Unable to enable IPv6 on %s", c->ifnames[0]);
811272bd698SAlexander V. Chernikov 	ret = iface_enable_ipv6(c->ifnames[1]);
812272bd698SAlexander V. Chernikov 	ATF_REQUIRE_MSG(ret == 0, "Unable to enable IPv6 on %s", c->ifnames[1]);
813272bd698SAlexander V. Chernikov 
814272bd698SAlexander V. Chernikov 	ret = iface_setup_addr(c->ifnames[0], c->addr6_str, c->plen6);
815272bd698SAlexander V. Chernikov 	ATF_REQUIRE_MSG(ret == 0, "ifconfig failed");
816272bd698SAlexander V. Chernikov 
817272bd698SAlexander V. Chernikov 	ret = iface_setup_addr(c->ifnames[1], "2001:DB8:4242::1", 64);
818272bd698SAlexander V. Chernikov 	ATF_REQUIRE_MSG(ret == 0, "ifconfig failed");
819272bd698SAlexander V. Chernikov 
820272bd698SAlexander V. Chernikov 	c->rtsock_fd = rtsock_setup_socket();
821272bd698SAlexander V. Chernikov 
822272bd698SAlexander V. Chernikov 	/* Create IPv6 subnetwork with smaller prefix */
823272bd698SAlexander V. Chernikov 	struct sockaddr_in6 mask6;
824272bd698SAlexander V. Chernikov 	struct sockaddr_in6 net6;
825272bd698SAlexander V. Chernikov 	struct sockaddr_in6 gw6;
826272bd698SAlexander V. Chernikov 	prepare_v6_network(c, &net6, &mask6, &gw6);
827272bd698SAlexander V. Chernikov 
828272bd698SAlexander V. Chernikov 	prepare_route_message(rtm, RTM_ADD, (struct sockaddr *)&net6,
829272bd698SAlexander V. Chernikov 	    (struct sockaddr *)&mask6, (struct sockaddr *)&gw6);
830272bd698SAlexander V. Chernikov 
831272bd698SAlexander V. Chernikov 	rtsock_send_rtm(c->rtsock_fd, rtm);
832272bd698SAlexander V. Chernikov 	rtm = rtsock_read_rtm_reply(c->rtsock_fd, buffer, sizeof(buffer), rtm->rtm_seq);
833272bd698SAlexander V. Chernikov 
834272bd698SAlexander V. Chernikov 	verify_route_message(rtm, RTM_ADD, (struct sockaddr *)&net6,
835272bd698SAlexander V. Chernikov 	    (struct sockaddr *)&mask6, (struct sockaddr *)&gw6);
836272bd698SAlexander V. Chernikov 
837272bd698SAlexander V. Chernikov 	/* Change gateway to the one on residing on the other interface */
838272bd698SAlexander V. Chernikov 	inet_pton(AF_INET6, "2001:DB8:4242::4242", &gw6.sin6_addr);
839272bd698SAlexander V. Chernikov 	prepare_route_message(rtm, RTM_CHANGE, (struct sockaddr *)&net6,
840272bd698SAlexander V. Chernikov 	    (struct sockaddr *)&mask6, (struct sockaddr *)&gw6);
841272bd698SAlexander V. Chernikov 	rtsock_send_rtm(c->rtsock_fd, rtm);
842272bd698SAlexander V. Chernikov 
843272bd698SAlexander V. Chernikov 	rtm = rtsock_read_rtm_reply(c->rtsock_fd, buffer, sizeof(buffer), rtm->rtm_seq);
844272bd698SAlexander V. Chernikov 
845272bd698SAlexander V. Chernikov 	verify_route_message(rtm, RTM_CHANGE, (struct sockaddr *)&net6,
846272bd698SAlexander V. Chernikov 	    (struct sockaddr *)&mask6, (struct sockaddr *)&gw6);
847272bd698SAlexander V. Chernikov 
848272bd698SAlexander V. Chernikov 	verify_route_message_extra(rtm, if_nametoindex(c->ifnames[1]),
8491b95005eSAlexander V. Chernikov 	    RTF_UP | RTF_DONE | RTF_GATEWAY | RTF_STATIC);
850272bd698SAlexander V. Chernikov 
851272bd698SAlexander V. Chernikov 	/* Verify the change has actually taken place */
852272bd698SAlexander V. Chernikov 	prepare_route_message(rtm, RTM_GET, (struct sockaddr *)&net6,
853272bd698SAlexander V. Chernikov 	    (struct sockaddr *)&mask6, NULL);
854272bd698SAlexander V. Chernikov 
855272bd698SAlexander V. Chernikov 	rtsock_send_rtm(c->rtsock_fd, rtm);
856272bd698SAlexander V. Chernikov 
857272bd698SAlexander V. Chernikov 	/*
858272bd698SAlexander V. Chernikov 	 * RTM_GET: len 248, pid: 2268, seq 44, errno 0, flags: <UP,GATEWAY,DONE,STATIC>
859272bd698SAlexander V. Chernikov 	 *  sockaddrs: 0x7 <DST,GATEWAY,NETMASK>
860272bd698SAlexander V. Chernikov 	 *  af=inet6 len=28 addr=2001:db8:: hd={x1C, x1C, x00{6}, x20, x01, x0D, xB8, x00{16}}
861272bd698SAlexander 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}}
862272bd698SAlexander 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}}
863272bd698SAlexander V. Chernikov 	 */
864272bd698SAlexander V. Chernikov 
865272bd698SAlexander V. Chernikov 	rtm = rtsock_read_rtm_reply(c->rtsock_fd, buffer, sizeof(buffer), rtm->rtm_seq);
866272bd698SAlexander V. Chernikov 	verify_route_message_extra(rtm, if_nametoindex(c->ifnames[1]),
867272bd698SAlexander V. Chernikov 	    RTF_UP | RTF_DONE | RTF_GATEWAY | RTF_STATIC);
868272bd698SAlexander V. Chernikov }
869272bd698SAlexander V. Chernikov 
870272bd698SAlexander V. Chernikov RTM_DECLARE_ROOT_TEST(rtm_change_v6_mtu_success,
871272bd698SAlexander V. Chernikov     "Tests IPv6 path mtu change");
872272bd698SAlexander V. Chernikov 
873272bd698SAlexander V. Chernikov ATF_TC_BODY(rtm_change_v6_mtu_success, tc)
874272bd698SAlexander V. Chernikov {
875272bd698SAlexander V. Chernikov 	DECLARE_TEST_VARS;
876272bd698SAlexander V. Chernikov 
877272bd698SAlexander V. Chernikov 	unsigned long test_mtu = 1442;
878272bd698SAlexander V. Chernikov 
879272bd698SAlexander V. Chernikov 	c = presetup_ipv6(tc);
880272bd698SAlexander V. Chernikov 
881272bd698SAlexander V. Chernikov 	/* Create IPv6 subnetwork with smaller prefix */
882272bd698SAlexander V. Chernikov 	struct sockaddr_in6 mask6;
883272bd698SAlexander V. Chernikov 	struct sockaddr_in6 net6;
884272bd698SAlexander V. Chernikov 	struct sockaddr_in6 gw6;
885272bd698SAlexander V. Chernikov 	prepare_v6_network(c, &net6, &mask6, &gw6);
886272bd698SAlexander V. Chernikov 
887272bd698SAlexander V. Chernikov 	prepare_route_message(rtm, RTM_ADD, (struct sockaddr *)&net6,
888272bd698SAlexander V. Chernikov 	    (struct sockaddr *)&mask6, (struct sockaddr *)&gw6);
889272bd698SAlexander V. Chernikov 
890272bd698SAlexander V. Chernikov 	/* Send route add */
891272bd698SAlexander V. Chernikov 	rtsock_send_rtm(c->rtsock_fd, rtm);
892272bd698SAlexander V. Chernikov 	rtm = rtsock_read_rtm_reply(c->rtsock_fd, buffer, sizeof(buffer), rtm->rtm_seq);
893272bd698SAlexander V. Chernikov 
894272bd698SAlexander V. Chernikov 	/* Change MTU */
895272bd698SAlexander V. Chernikov 	prepare_route_message(rtm, RTM_CHANGE, (struct sockaddr *)&net6,
896272bd698SAlexander V. Chernikov 	    (struct sockaddr *)&mask6, NULL);
897272bd698SAlexander V. Chernikov 	rtm->rtm_inits |= RTV_MTU;
898272bd698SAlexander V. Chernikov 	rtm->rtm_rmx.rmx_mtu = test_mtu;
899272bd698SAlexander V. Chernikov 
900272bd698SAlexander V. Chernikov 	rtsock_send_rtm(c->rtsock_fd, rtm);
901272bd698SAlexander V. Chernikov 	rtm = rtsock_read_rtm_reply(c->rtsock_fd, buffer, sizeof(buffer), rtm->rtm_seq);
902272bd698SAlexander V. Chernikov 
903272bd698SAlexander V. Chernikov 	verify_route_message(rtm, RTM_CHANGE, (struct sockaddr *)&net6,
904272bd698SAlexander V. Chernikov 	    (struct sockaddr *)&mask6, NULL);
905272bd698SAlexander V. Chernikov 
906272bd698SAlexander V. Chernikov 	RTSOCK_ATF_REQUIRE_MSG(rtm, rtm->rtm_rmx.rmx_mtu == test_mtu,
907272bd698SAlexander V. Chernikov 	    "expected mtu: %lu, got %lu", test_mtu, rtm->rtm_rmx.rmx_mtu);
908272bd698SAlexander V. Chernikov 
909272bd698SAlexander V. Chernikov 	/* Verify the change has actually taken place */
910272bd698SAlexander V. Chernikov 	prepare_route_message(rtm, RTM_GET, (struct sockaddr *)&net6,
911272bd698SAlexander V. Chernikov 	    (struct sockaddr *)&mask6, NULL);
912272bd698SAlexander V. Chernikov 
913272bd698SAlexander V. Chernikov 	rtsock_send_rtm(c->rtsock_fd, rtm);
914272bd698SAlexander V. Chernikov 	rtm = rtsock_read_rtm_reply(c->rtsock_fd, buffer, sizeof(buffer), rtm->rtm_seq);
915272bd698SAlexander V. Chernikov 
916272bd698SAlexander V. Chernikov 	RTSOCK_ATF_REQUIRE_MSG(rtm, rtm->rtm_rmx.rmx_mtu == test_mtu,
917272bd698SAlexander V. Chernikov 	    "expected mtu: %lu, got %lu", test_mtu, rtm->rtm_rmx.rmx_mtu);
918272bd698SAlexander V. Chernikov }
919272bd698SAlexander V. Chernikov 
9201b95005eSAlexander V. Chernikov RTM_DECLARE_ROOT_TEST(rtm_change_v6_flags_success,
9211b95005eSAlexander V. Chernikov     "Tests IPv6 path flags change");
9221b95005eSAlexander V. Chernikov 
9231b95005eSAlexander V. Chernikov ATF_TC_BODY(rtm_change_v6_flags_success, tc)
9241b95005eSAlexander V. Chernikov {
9251b95005eSAlexander V. Chernikov 	DECLARE_TEST_VARS;
9261b95005eSAlexander V. Chernikov 
9271b95005eSAlexander V. Chernikov 	uint32_t test_flags = RTF_PROTO1 | RTF_PROTO2 | RTF_PROTO3 | RTF_STATIC;
9281b95005eSAlexander V. Chernikov 	uint32_t desired_flags;
9291b95005eSAlexander V. Chernikov 
9301b95005eSAlexander V. Chernikov 	c = presetup_ipv6(tc);
9311b95005eSAlexander V. Chernikov 
9321b95005eSAlexander V. Chernikov 	/* Create IPv6 subnetwork with smaller prefix */
9331b95005eSAlexander V. Chernikov 	struct sockaddr_in6 mask6;
9341b95005eSAlexander V. Chernikov 	struct sockaddr_in6 net6;
9351b95005eSAlexander V. Chernikov 	struct sockaddr_in6 gw6;
9361b95005eSAlexander V. Chernikov 	prepare_v6_network(c, &net6, &mask6, &gw6);
9371b95005eSAlexander V. Chernikov 
9381b95005eSAlexander V. Chernikov 	prepare_route_message(rtm, RTM_ADD, (struct sockaddr *)&net6,
9391b95005eSAlexander V. Chernikov 	    (struct sockaddr *)&mask6, (struct sockaddr *)&gw6);
9401b95005eSAlexander V. Chernikov 
9411b95005eSAlexander V. Chernikov 	/* Set test flags during route addition */
9421b95005eSAlexander V. Chernikov 	desired_flags = RTF_UP | RTF_DONE | RTF_GATEWAY | test_flags;
9431b95005eSAlexander V. Chernikov 	rtm->rtm_flags |= test_flags;
9441b95005eSAlexander V. Chernikov 	rtsock_send_rtm(c->rtsock_fd, rtm);
9451b95005eSAlexander V. Chernikov 	rtm = rtsock_read_rtm_reply(c->rtsock_fd, buffer, sizeof(buffer), rtm->rtm_seq);
9461b95005eSAlexander V. Chernikov 
9471b95005eSAlexander V. Chernikov 	/* Change flags */
9481b95005eSAlexander V. Chernikov 	prepare_route_message(rtm, RTM_CHANGE, (struct sockaddr *)&net6,
9491b95005eSAlexander V. Chernikov 	    (struct sockaddr *)&mask6, NULL);
9501b95005eSAlexander V. Chernikov 	rtm->rtm_flags &= ~test_flags;
9511b95005eSAlexander V. Chernikov 	desired_flags &= ~test_flags;
9521b95005eSAlexander V. Chernikov 
9531b95005eSAlexander V. Chernikov 	rtsock_send_rtm(c->rtsock_fd, rtm);
9541b95005eSAlexander V. Chernikov 	rtm = rtsock_read_rtm_reply(c->rtsock_fd, buffer, sizeof(buffer), rtm->rtm_seq);
9551b95005eSAlexander V. Chernikov 
9561b95005eSAlexander V. Chernikov 	/* Verify updated flags */
9571b95005eSAlexander V. Chernikov 	verify_route_message_extra(rtm, c->ifindex, desired_flags | RTF_DONE);
9581b95005eSAlexander V. Chernikov 
9591b95005eSAlexander V. Chernikov 	/* Verify the change has actually taken place */
9601b95005eSAlexander V. Chernikov 	prepare_route_message(rtm, RTM_GET, (struct sockaddr *)&net6,
9611b95005eSAlexander V. Chernikov 	    (struct sockaddr *)&mask6, NULL);
9621b95005eSAlexander V. Chernikov 
9631b95005eSAlexander V. Chernikov 	rtsock_send_rtm(c->rtsock_fd, rtm);
9641b95005eSAlexander V. Chernikov 	rtm = rtsock_read_rtm_reply(c->rtsock_fd, buffer, sizeof(buffer), rtm->rtm_seq);
9651b95005eSAlexander V. Chernikov 
9661b95005eSAlexander V. Chernikov 	verify_route_message_extra(rtm, c->ifindex, desired_flags | RTF_DONE);
9671b95005eSAlexander V. Chernikov }
9681b95005eSAlexander V. Chernikov 
969e02d3fe7SAlexander V. Chernikov ATF_TC_WITH_CLEANUP(rtm_add_v4_temporal1_success);
970e02d3fe7SAlexander V. Chernikov ATF_TC_HEAD(rtm_add_v4_temporal1_success, tc)
971e02d3fe7SAlexander V. Chernikov {
972e02d3fe7SAlexander V. Chernikov 	DESCRIBE_ROOT_TEST("Tests IPv4 route expiration with expire time set");
973e02d3fe7SAlexander V. Chernikov }
974e02d3fe7SAlexander V. Chernikov 
975e02d3fe7SAlexander V. Chernikov ATF_TC_BODY(rtm_add_v4_temporal1_success, tc)
976e02d3fe7SAlexander V. Chernikov {
977e02d3fe7SAlexander V. Chernikov 	DECLARE_TEST_VARS;
978e02d3fe7SAlexander V. Chernikov 
979e02d3fe7SAlexander V. Chernikov 	c = presetup_ipv4(tc);
980e02d3fe7SAlexander V. Chernikov 
981e02d3fe7SAlexander V. Chernikov 	/* Create IPv4 subnetwork with smaller prefix */
982e02d3fe7SAlexander V. Chernikov 	struct sockaddr_in mask4;
983e02d3fe7SAlexander V. Chernikov 	struct sockaddr_in net4;
984e02d3fe7SAlexander V. Chernikov 	struct sockaddr_in gw4;
985e02d3fe7SAlexander V. Chernikov 	prepare_v4_network(c, &net4, &mask4, &gw4);
986e02d3fe7SAlexander V. Chernikov 
987e02d3fe7SAlexander V. Chernikov 	prepare_route_message(rtm, RTM_ADD, (struct sockaddr *)&net4,
988e02d3fe7SAlexander V. Chernikov 	    (struct sockaddr *)&mask4, (struct sockaddr *)&gw4);
989e02d3fe7SAlexander V. Chernikov 
990e02d3fe7SAlexander V. Chernikov 	/* Set expire time to now */
991e02d3fe7SAlexander V. Chernikov 	struct timeval tv;
992e02d3fe7SAlexander V. Chernikov 	gettimeofday(&tv, NULL);
993e02d3fe7SAlexander V. Chernikov 	rtm->rtm_rmx.rmx_expire = tv.tv_sec - 1;
994e02d3fe7SAlexander V. Chernikov 	rtm->rtm_inits |= RTV_EXPIRE;
995e02d3fe7SAlexander V. Chernikov 
996e02d3fe7SAlexander V. Chernikov 	rtsock_send_rtm(c->rtsock_fd, rtm);
997e02d3fe7SAlexander V. Chernikov 	rtm = rtsock_read_rtm_reply(c->rtsock_fd, buffer, sizeof(buffer), rtm->rtm_seq);
998e02d3fe7SAlexander V. Chernikov 	ATF_REQUIRE_MSG(rtm != NULL, "unable to get rtsock reply for RTM_ADD");
999e02d3fe7SAlexander V. Chernikov 	RTSOCK_ATF_REQUIRE_MSG(rtm, rtm->rtm_inits & RTV_EXPIRE, "RTV_EXPIRE not set");
1000e02d3fe7SAlexander V. Chernikov 
1001e02d3fe7SAlexander V. Chernikov 	/* The next should be route deletion */
1002e02d3fe7SAlexander V. Chernikov 	rtm = rtsock_read_rtm(c->rtsock_fd, buffer, sizeof(buffer));
1003e02d3fe7SAlexander V. Chernikov 
1004e02d3fe7SAlexander V. Chernikov 	verify_route_message(rtm, RTM_DELETE, (struct sockaddr *)&net4,
1005e02d3fe7SAlexander V. Chernikov 	    (struct sockaddr *)&mask4, (struct sockaddr *)&gw4);
1006e02d3fe7SAlexander V. Chernikov 
10071b95005eSAlexander V. Chernikov 	verify_route_message_extra(rtm, c->ifindex,
10081b95005eSAlexander V. Chernikov 	    RTF_DONE | RTF_GATEWAY | RTF_STATIC);
1009e02d3fe7SAlexander V. Chernikov }
1010e02d3fe7SAlexander V. Chernikov 
1011e02d3fe7SAlexander V. Chernikov ATF_TC_CLEANUP(rtm_add_v4_temporal1_success, tc)
1012e02d3fe7SAlexander V. Chernikov {
1013e02d3fe7SAlexander V. Chernikov 	CLEANUP_AFTER_TEST;
1014e02d3fe7SAlexander V. Chernikov }
1015e02d3fe7SAlexander V. Chernikov 
1016e02d3fe7SAlexander V. Chernikov ATF_TC_WITH_CLEANUP(rtm_add_v6_temporal1_success);
1017e02d3fe7SAlexander V. Chernikov ATF_TC_HEAD(rtm_add_v6_temporal1_success, tc)
1018e02d3fe7SAlexander V. Chernikov {
1019e02d3fe7SAlexander V. Chernikov 	DESCRIBE_ROOT_TEST("Tests IPv6 global unicast prefix addition with directly-reachable GU GW");
1020e02d3fe7SAlexander V. Chernikov }
1021e02d3fe7SAlexander V. Chernikov 
1022e02d3fe7SAlexander V. Chernikov ATF_TC_BODY(rtm_add_v6_temporal1_success, tc)
1023e02d3fe7SAlexander V. Chernikov {
1024e02d3fe7SAlexander V. Chernikov 	DECLARE_TEST_VARS;
1025e02d3fe7SAlexander V. Chernikov 
1026e02d3fe7SAlexander V. Chernikov 	c = presetup_ipv6(tc);
1027e02d3fe7SAlexander V. Chernikov 
1028e02d3fe7SAlexander V. Chernikov 	/* Create IPv6 subnetwork with smaller prefix */
1029e02d3fe7SAlexander V. Chernikov 	struct sockaddr_in6 mask6;
1030e02d3fe7SAlexander V. Chernikov 	struct sockaddr_in6 net6;
1031e02d3fe7SAlexander V. Chernikov 	struct sockaddr_in6 gw6;
1032e02d3fe7SAlexander V. Chernikov 	prepare_v6_network(c, &net6, &mask6, &gw6);
1033e02d3fe7SAlexander V. Chernikov 
1034e02d3fe7SAlexander V. Chernikov 	prepare_route_message(rtm, RTM_ADD, (struct sockaddr *)&net6,
1035e02d3fe7SAlexander V. Chernikov 	    (struct sockaddr *)&mask6, (struct sockaddr *)&gw6);
1036e02d3fe7SAlexander V. Chernikov 
1037e02d3fe7SAlexander V. Chernikov 	/* Set expire time to now */
1038e02d3fe7SAlexander V. Chernikov 	struct timeval tv;
1039e02d3fe7SAlexander V. Chernikov 	gettimeofday(&tv, NULL);
1040e02d3fe7SAlexander V. Chernikov 	rtm->rtm_rmx.rmx_expire = tv.tv_sec - 1;
1041e02d3fe7SAlexander V. Chernikov 	rtm->rtm_inits |= RTV_EXPIRE;
1042e02d3fe7SAlexander V. Chernikov 
1043e02d3fe7SAlexander V. Chernikov 	rtsock_send_rtm(c->rtsock_fd, rtm);
1044e02d3fe7SAlexander V. Chernikov 	rtm = rtsock_read_rtm_reply(c->rtsock_fd, buffer, sizeof(buffer), rtm->rtm_seq);
1045e02d3fe7SAlexander V. Chernikov 	ATF_REQUIRE_MSG(rtm != NULL, "unable to get rtsock reply for RTM_ADD");
1046e02d3fe7SAlexander V. Chernikov 	RTSOCK_ATF_REQUIRE_MSG(rtm, rtm->rtm_inits & RTV_EXPIRE, "RTV_EXPIRE not set");
1047e02d3fe7SAlexander V. Chernikov 
1048e02d3fe7SAlexander V. Chernikov 	/* The next should be route deletion */
1049e02d3fe7SAlexander V. Chernikov 	rtm = rtsock_read_rtm(c->rtsock_fd, buffer, sizeof(buffer));
1050e02d3fe7SAlexander V. Chernikov 
1051e02d3fe7SAlexander V. Chernikov 	verify_route_message(rtm, RTM_DELETE, (struct sockaddr *)&net6,
1052e02d3fe7SAlexander V. Chernikov 	    (struct sockaddr *)&mask6, (struct sockaddr *)&gw6);
1053e02d3fe7SAlexander V. Chernikov 
10541b95005eSAlexander V. Chernikov 	verify_route_message_extra(rtm, c->ifindex,
10551b95005eSAlexander V. Chernikov 	    RTF_DONE | RTF_GATEWAY | RTF_STATIC);
1056e02d3fe7SAlexander V. Chernikov }
1057e02d3fe7SAlexander V. Chernikov 
1058e02d3fe7SAlexander V. Chernikov ATF_TC_CLEANUP(rtm_add_v6_temporal1_success, tc)
1059e02d3fe7SAlexander V. Chernikov {
1060e02d3fe7SAlexander V. Chernikov 	CLEANUP_AFTER_TEST;
1061e02d3fe7SAlexander V. Chernikov }
1062e02d3fe7SAlexander V. Chernikov 
1063e02d3fe7SAlexander V. Chernikov /* Interface address messages tests */
1064e02d3fe7SAlexander V. Chernikov 
1065e02d3fe7SAlexander V. Chernikov RTM_DECLARE_ROOT_TEST(rtm_add_v6_gu_ifa_hostroute_success,
1066e02d3fe7SAlexander V. Chernikov     "Tests validness for /128 host route announce after ifaddr assignment");
1067e02d3fe7SAlexander V. Chernikov 
1068e02d3fe7SAlexander V. Chernikov ATF_TC_BODY(rtm_add_v6_gu_ifa_hostroute_success, tc)
1069e02d3fe7SAlexander V. Chernikov {
1070e02d3fe7SAlexander V. Chernikov 	DECLARE_TEST_VARS;
1071e02d3fe7SAlexander V. Chernikov 
1072e02d3fe7SAlexander V. Chernikov 	c = presetup_ipv6_iface(tc);
1073e02d3fe7SAlexander V. Chernikov 
1074e02d3fe7SAlexander V. Chernikov 	c->rtsock_fd = rtsock_setup_socket();
1075e02d3fe7SAlexander V. Chernikov 
1076e02d3fe7SAlexander V. Chernikov 	ret = iface_setup_addr(c->ifname, c->addr6_str, c->plen6);
1077e02d3fe7SAlexander V. Chernikov 
1078e02d3fe7SAlexander V. Chernikov 	/*
1079e02d3fe7SAlexander V. Chernikov 	 * There will be multiple.
1080e02d3fe7SAlexander V. Chernikov 	 * RTM_ADD without llinfo.
1081e02d3fe7SAlexander V. Chernikov 	 */
1082e02d3fe7SAlexander V. Chernikov 
1083e02d3fe7SAlexander V. Chernikov 	while (true) {
1084e02d3fe7SAlexander V. Chernikov 		rtm = rtsock_read_rtm(c->rtsock_fd, buffer, sizeof(buffer));
1085e02d3fe7SAlexander V. Chernikov 		if ((rtm->rtm_type == RTM_ADD) && ((rtm->rtm_flags & RTF_LLINFO) == 0))
1086e02d3fe7SAlexander V. Chernikov 			break;
1087e02d3fe7SAlexander V. Chernikov 	}
1088e02d3fe7SAlexander V. Chernikov 	/* This should be a message for the host route */
1089e02d3fe7SAlexander V. Chernikov 
1090e02d3fe7SAlexander V. Chernikov 	verify_route_message(rtm, RTM_ADD, (struct sockaddr *)&c->addr6, NULL, NULL);
1091e02d3fe7SAlexander V. Chernikov 	rtsock_validate_pid_kernel(rtm);
1092e02d3fe7SAlexander V. Chernikov 	/* No netmask should be set */
1093e02d3fe7SAlexander V. Chernikov 	RTSOCK_ATF_REQUIRE_MSG(rtm, rtsock_find_rtm_sa(rtm, RTA_NETMASK) == NULL, "netmask is set");
1094e02d3fe7SAlexander V. Chernikov 
1095e02d3fe7SAlexander V. Chernikov 	/* gateway should be link sdl with ifindex of an address interface */
1096e02d3fe7SAlexander V. Chernikov 	verify_link_gateway(rtm, c->ifindex);
1097e02d3fe7SAlexander V. Chernikov 
1098e02d3fe7SAlexander V. Chernikov 	int expected_rt_flags = RTF_UP | RTF_HOST | RTF_DONE | RTF_STATIC | RTF_PINNED;
1099e02d3fe7SAlexander V. Chernikov 	verify_route_message_extra(rtm, if_nametoindex("lo0"), expected_rt_flags);
1100e02d3fe7SAlexander V. Chernikov }
1101e02d3fe7SAlexander V. Chernikov 
1102e02d3fe7SAlexander V. Chernikov RTM_DECLARE_ROOT_TEST(rtm_add_v6_gu_ifa_prefixroute_success,
1103e02d3fe7SAlexander V. Chernikov     "Tests validness for the prefix route announce after ifaddr assignment");
1104e02d3fe7SAlexander V. Chernikov 
1105e02d3fe7SAlexander V. Chernikov ATF_TC_BODY(rtm_add_v6_gu_ifa_prefixroute_success, tc)
1106e02d3fe7SAlexander V. Chernikov {
1107e02d3fe7SAlexander V. Chernikov 	DECLARE_TEST_VARS;
1108e02d3fe7SAlexander V. Chernikov 
1109e02d3fe7SAlexander V. Chernikov 	c = presetup_ipv6_iface(tc);
1110e02d3fe7SAlexander V. Chernikov 
1111e02d3fe7SAlexander V. Chernikov 	c->rtsock_fd = rtsock_setup_socket();
1112e02d3fe7SAlexander V. Chernikov 
1113e02d3fe7SAlexander V. Chernikov 	ret = iface_setup_addr(c->ifname, c->addr6_str, c->plen6);
1114e02d3fe7SAlexander V. Chernikov 
1115e02d3fe7SAlexander V. Chernikov 	/*
1116e02d3fe7SAlexander V. Chernikov 	 * Multiple RTM_ADD messages will be generated:
1117e02d3fe7SAlexander V. Chernikov 	 * 1) lladdr mapping (RTF_LLDATA)
1118e02d3fe7SAlexander V. Chernikov 	 * 2) host route (one w/o netmask)
1119e02d3fe7SAlexander V. Chernikov 	 * 3) prefix route
1120e02d3fe7SAlexander V. Chernikov 	 */
1121e02d3fe7SAlexander V. Chernikov 
1122e02d3fe7SAlexander V. Chernikov 	while (true) {
1123e02d3fe7SAlexander V. Chernikov 		rtm = rtsock_read_rtm(c->rtsock_fd, buffer, sizeof(buffer));
1124e02d3fe7SAlexander V. Chernikov 		/* Find RTM_ADD with netmask - this should skip both host route and LLADDR */
1125e02d3fe7SAlexander V. Chernikov 		if ((rtm->rtm_type == RTM_ADD) && (rtsock_find_rtm_sa(rtm, RTA_NETMASK)))
1126e02d3fe7SAlexander V. Chernikov 			break;
1127e02d3fe7SAlexander V. Chernikov 	}
1128e02d3fe7SAlexander V. Chernikov 
1129e02d3fe7SAlexander V. Chernikov 	/* This should be a message for the prefix route */
1130e02d3fe7SAlexander V. Chernikov 	verify_route_message(rtm, RTM_ADD, (struct sockaddr *)&c->net6,
1131e02d3fe7SAlexander V. Chernikov 	    (struct sockaddr *)&c->mask6, NULL);
1132e02d3fe7SAlexander V. Chernikov 
1133e02d3fe7SAlexander V. Chernikov 	/* gateway should be link sdl with ifindex of an address interface */
1134e02d3fe7SAlexander V. Chernikov 	verify_link_gateway(rtm, c->ifindex);
1135e02d3fe7SAlexander V. Chernikov 
113681728a53SAlexander V. Chernikov 	int expected_rt_flags = RTF_UP | RTF_DONE | RTF_PINNED;
1137e02d3fe7SAlexander V. Chernikov 	verify_route_message_extra(rtm, c->ifindex, expected_rt_flags);
1138e02d3fe7SAlexander V. Chernikov }
1139e02d3fe7SAlexander V. Chernikov 
1140e02d3fe7SAlexander V. Chernikov RTM_DECLARE_ROOT_TEST(rtm_add_v6_gu_ifa_ordered_success,
1141e02d3fe7SAlexander V. Chernikov     "Tests ordering of the messages for IPv6 global unicast ifaddr assignment");
1142e02d3fe7SAlexander V. Chernikov 
1143e02d3fe7SAlexander V. Chernikov ATF_TC_BODY(rtm_add_v6_gu_ifa_ordered_success, tc)
1144e02d3fe7SAlexander V. Chernikov {
1145e02d3fe7SAlexander V. Chernikov 	DECLARE_TEST_VARS;
1146e02d3fe7SAlexander V. Chernikov 
1147e02d3fe7SAlexander V. Chernikov 	c = presetup_ipv6_iface(tc);
1148e02d3fe7SAlexander V. Chernikov 
1149e02d3fe7SAlexander V. Chernikov 	c->rtsock_fd = rtsock_setup_socket();
1150e02d3fe7SAlexander V. Chernikov 
1151e02d3fe7SAlexander V. Chernikov 	ret = iface_setup_addr(c->ifname, c->addr6_str, c->plen6);
1152e02d3fe7SAlexander V. Chernikov 
1153e02d3fe7SAlexander V. Chernikov 	int count = 0, tries = 0;
1154e02d3fe7SAlexander V. Chernikov 
1155e02d3fe7SAlexander V. Chernikov 	enum msgtype {
1156e02d3fe7SAlexander V. Chernikov 		MSG_IFADDR,
1157e02d3fe7SAlexander V. Chernikov 		MSG_HOSTROUTE,
1158e02d3fe7SAlexander V. Chernikov 		MSG_PREFIXROUTE,
1159e02d3fe7SAlexander V. Chernikov 		MSG_MAX,
1160e02d3fe7SAlexander V. Chernikov 	};
1161e02d3fe7SAlexander V. Chernikov 
1162e02d3fe7SAlexander V. Chernikov 	int msg_array[MSG_MAX];
1163e02d3fe7SAlexander V. Chernikov 
1164e02d3fe7SAlexander V. Chernikov 	bzero(msg_array, sizeof(msg_array));
1165e02d3fe7SAlexander V. Chernikov 
1166e02d3fe7SAlexander V. Chernikov 	while (count < 3 && tries < 20) {
1167e02d3fe7SAlexander V. Chernikov 		rtm = rtsock_read_rtm(c->rtsock_fd, buffer, sizeof(buffer));
1168e02d3fe7SAlexander V. Chernikov 		tries++;
1169e02d3fe7SAlexander V. Chernikov 		/* Classify */
1170e02d3fe7SAlexander V. Chernikov 		if (rtm->rtm_type == RTM_NEWADDR) {
1171e02d3fe7SAlexander V. Chernikov 			RLOG("MSG_IFADDR: %d", count);
1172e02d3fe7SAlexander V. Chernikov 			msg_array[MSG_IFADDR] = count++;
1173e02d3fe7SAlexander V. Chernikov 			continue;
1174e02d3fe7SAlexander V. Chernikov 		}
1175e02d3fe7SAlexander V. Chernikov 
1176e02d3fe7SAlexander V. Chernikov 		/* Find RTM_ADD with netmask - this should skip both host route and LLADDR */
1177e02d3fe7SAlexander V. Chernikov 		if ((rtm->rtm_type == RTM_ADD) && (rtsock_find_rtm_sa(rtm, RTA_NETMASK))) {
1178e02d3fe7SAlexander V. Chernikov 			RLOG("MSG_PREFIXROUTE: %d", count);
1179e02d3fe7SAlexander V. Chernikov 			msg_array[MSG_PREFIXROUTE] = count++;
1180e02d3fe7SAlexander V. Chernikov 			continue;
1181e02d3fe7SAlexander V. Chernikov 		}
1182e02d3fe7SAlexander V. Chernikov 
1183e02d3fe7SAlexander V. Chernikov 		if ((rtm->rtm_type == RTM_ADD) && ((rtm->rtm_flags & RTF_LLDATA) == 0)) {
1184e02d3fe7SAlexander V. Chernikov 			RLOG("MSG_HOSTROUTE: %d", count);
1185e02d3fe7SAlexander V. Chernikov 			msg_array[MSG_HOSTROUTE] = count++;
1186e02d3fe7SAlexander V. Chernikov 			continue;
1187e02d3fe7SAlexander V. Chernikov 		}
1188e02d3fe7SAlexander V. Chernikov 
1189e02d3fe7SAlexander V. Chernikov 		RLOG("skipping msg type %s, try: %d", rtsock_print_cmdtype(rtm->rtm_type),
1190e02d3fe7SAlexander V. Chernikov 		    tries);
1191e02d3fe7SAlexander V. Chernikov 	}
1192e02d3fe7SAlexander V. Chernikov 
1193e02d3fe7SAlexander V. Chernikov 	/* TODO: verify multicast */
1194e02d3fe7SAlexander V. Chernikov 	ATF_REQUIRE_MSG(count == 3, "Received only %d/3 messages", count);
1195e02d3fe7SAlexander V. Chernikov 	ATF_REQUIRE_MSG(msg_array[MSG_IFADDR] == 0, "ifaddr message is not the first");
1196e02d3fe7SAlexander V. Chernikov }
1197e02d3fe7SAlexander V. Chernikov 
1198e02d3fe7SAlexander V. Chernikov RTM_DECLARE_ROOT_TEST(rtm_del_v6_gu_ifa_hostroute_success,
1199e02d3fe7SAlexander V. Chernikov     "Tests validness for /128 host route removal after ifaddr removal");
1200e02d3fe7SAlexander V. Chernikov 
1201e02d3fe7SAlexander V. Chernikov ATF_TC_BODY(rtm_del_v6_gu_ifa_hostroute_success, tc)
1202e02d3fe7SAlexander V. Chernikov {
1203e02d3fe7SAlexander V. Chernikov 	DECLARE_TEST_VARS;
1204e02d3fe7SAlexander V. Chernikov 
1205e02d3fe7SAlexander V. Chernikov 	c = presetup_ipv6_iface(tc);
1206e02d3fe7SAlexander V. Chernikov 
1207e02d3fe7SAlexander V. Chernikov 	ret = iface_setup_addr(c->ifname, c->addr6_str, c->plen6);
1208e02d3fe7SAlexander V. Chernikov 
1209e02d3fe7SAlexander V. Chernikov 	c->rtsock_fd = rtsock_setup_socket();
1210e02d3fe7SAlexander V. Chernikov 
1211e02d3fe7SAlexander V. Chernikov 	ret = iface_delete_addr(c->ifname, c->addr6_str);
1212e02d3fe7SAlexander V. Chernikov 
1213e02d3fe7SAlexander V. Chernikov 	while (true) {
1214e02d3fe7SAlexander V. Chernikov 		rtm = rtsock_read_rtm(c->rtsock_fd, buffer, sizeof(buffer));
1215e02d3fe7SAlexander V. Chernikov 		if ((rtm->rtm_type == RTM_DELETE) &&
1216e02d3fe7SAlexander V. Chernikov 		    ((rtm->rtm_flags & RTF_LLINFO) == 0) &&
1217e02d3fe7SAlexander V. Chernikov 		    rtsock_find_rtm_sa(rtm, RTA_NETMASK) == NULL)
1218e02d3fe7SAlexander V. Chernikov 			break;
1219e02d3fe7SAlexander V. Chernikov 	}
1220e02d3fe7SAlexander V. Chernikov 	/* This should be a message for the host route */
1221e02d3fe7SAlexander V. Chernikov 
1222e02d3fe7SAlexander V. Chernikov 	verify_route_message(rtm, RTM_DELETE, (struct sockaddr *)&c->addr6, NULL, NULL);
1223e02d3fe7SAlexander V. Chernikov 	rtsock_validate_pid_kernel(rtm);
1224e02d3fe7SAlexander V. Chernikov 	/* No netmask should be set */
1225e02d3fe7SAlexander V. Chernikov 	RTSOCK_ATF_REQUIRE_MSG(rtm, rtsock_find_rtm_sa(rtm, RTA_NETMASK) == NULL, "netmask is set");
1226e02d3fe7SAlexander V. Chernikov 
1227e02d3fe7SAlexander V. Chernikov 	/* gateway should be link sdl with ifindex of an address interface */
1228e02d3fe7SAlexander V. Chernikov 	verify_link_gateway(rtm, c->ifindex);
1229e02d3fe7SAlexander V. Chernikov 
1230e02d3fe7SAlexander V. Chernikov 	/* XXX: consider passing ifindex in rtm_index as done in RTM_ADD. */
1231e02d3fe7SAlexander V. Chernikov 	int expected_rt_flags = RTF_HOST | RTF_DONE | RTF_STATIC | RTF_PINNED;
1232e02d3fe7SAlexander V. Chernikov 	RTSOCK_ATF_REQUIRE_MSG(rtm, rtm->rtm_flags == expected_rt_flags,
1233e02d3fe7SAlexander V. Chernikov 	    "expected rtm flags: 0x%X, got 0x%X", expected_rt_flags, rtm->rtm_flags);
1234e02d3fe7SAlexander V. Chernikov }
1235e02d3fe7SAlexander V. Chernikov 
1236e02d3fe7SAlexander V. Chernikov RTM_DECLARE_ROOT_TEST(rtm_del_v6_gu_ifa_prefixroute_success,
1237e02d3fe7SAlexander V. Chernikov     "Tests validness for the prefix route removal after ifaddr assignment");
1238e02d3fe7SAlexander V. Chernikov 
1239e02d3fe7SAlexander V. Chernikov ATF_TC_BODY(rtm_del_v6_gu_ifa_prefixroute_success, tc)
1240e02d3fe7SAlexander V. Chernikov {
1241e02d3fe7SAlexander V. Chernikov 	DECLARE_TEST_VARS;
1242e02d3fe7SAlexander V. Chernikov 
1243e02d3fe7SAlexander V. Chernikov 	c = presetup_ipv6_iface(tc);
1244e02d3fe7SAlexander V. Chernikov 
1245e02d3fe7SAlexander V. Chernikov 	ret = iface_setup_addr(c->ifname, c->addr6_str, c->plen6);
1246e02d3fe7SAlexander V. Chernikov 
1247e02d3fe7SAlexander V. Chernikov 	c->rtsock_fd = rtsock_setup_socket();
1248e02d3fe7SAlexander V. Chernikov 
1249e02d3fe7SAlexander V. Chernikov 	ret = iface_delete_addr(c->ifname, c->addr6_str);
1250e02d3fe7SAlexander V. Chernikov 
1251e02d3fe7SAlexander V. Chernikov 	while (true) {
1252e02d3fe7SAlexander V. Chernikov 		rtm = rtsock_read_rtm(c->rtsock_fd, buffer, sizeof(buffer));
1253e02d3fe7SAlexander V. Chernikov 		/* Find RTM_DELETE with netmask - this should skip both host route and LLADDR */
1254e02d3fe7SAlexander V. Chernikov 		if ((rtm->rtm_type == RTM_DELETE) && (rtsock_find_rtm_sa(rtm, RTA_NETMASK)))
1255e02d3fe7SAlexander V. Chernikov 			break;
1256e02d3fe7SAlexander V. Chernikov 	}
1257e02d3fe7SAlexander V. Chernikov 
1258e02d3fe7SAlexander V. Chernikov 	/* This should be a message for the prefix route */
1259e02d3fe7SAlexander V. Chernikov 	verify_route_message(rtm, RTM_DELETE, (struct sockaddr *)&c->net6,
1260e02d3fe7SAlexander V. Chernikov 	    (struct sockaddr *)&c->mask6, NULL);
1261e02d3fe7SAlexander V. Chernikov 
1262e02d3fe7SAlexander V. Chernikov 	/* gateway should be link sdl with ifindex of an address interface */
1263e02d3fe7SAlexander V. Chernikov 	verify_link_gateway(rtm, c->ifindex);
1264e02d3fe7SAlexander V. Chernikov 
126581728a53SAlexander V. Chernikov 	int expected_rt_flags = RTF_DONE | RTF_PINNED;
1266e02d3fe7SAlexander V. Chernikov 	verify_route_message_extra(rtm, c->ifindex, expected_rt_flags);
1267e02d3fe7SAlexander V. Chernikov }
1268e02d3fe7SAlexander V. Chernikov 
1269e02d3fe7SAlexander V. Chernikov RTM_DECLARE_ROOT_TEST(rtm_add_v4_gu_ifa_prefixroute_success,
1270e02d3fe7SAlexander V. Chernikov     "Tests validness for the prefix route announce after ifaddr assignment");
1271e02d3fe7SAlexander V. Chernikov 
1272e02d3fe7SAlexander V. Chernikov ATF_TC_BODY(rtm_add_v4_gu_ifa_prefixroute_success, tc)
1273e02d3fe7SAlexander V. Chernikov {
1274e02d3fe7SAlexander V. Chernikov 	DECLARE_TEST_VARS;
1275e02d3fe7SAlexander V. Chernikov 
1276e02d3fe7SAlexander V. Chernikov 	c = presetup_ipv4_iface(tc);
1277e02d3fe7SAlexander V. Chernikov 
1278e02d3fe7SAlexander V. Chernikov 	c->rtsock_fd = rtsock_setup_socket();
1279e02d3fe7SAlexander V. Chernikov 
1280e02d3fe7SAlexander V. Chernikov 	ret = iface_setup_addr(c->ifname, c->addr6_str, c->plen6);
1281e02d3fe7SAlexander V. Chernikov 
1282e02d3fe7SAlexander V. Chernikov 	/*
1283e02d3fe7SAlexander V. Chernikov 	 * Multiple RTM_ADD messages will be generated:
1284e02d3fe7SAlexander V. Chernikov 	 * 1) lladdr mapping (RTF_LLDATA)
1285e02d3fe7SAlexander V. Chernikov 	 * 3) prefix route
1286e02d3fe7SAlexander V. Chernikov 	 */
1287e02d3fe7SAlexander V. Chernikov 
1288e02d3fe7SAlexander V. Chernikov 	while (true) {
1289e02d3fe7SAlexander V. Chernikov 		rtm = rtsock_read_rtm(c->rtsock_fd, buffer, sizeof(buffer));
1290e02d3fe7SAlexander V. Chernikov 		/* Find RTM_ADD with netmask - this should skip both host route and LLADDR */
1291e02d3fe7SAlexander V. Chernikov 		if ((rtm->rtm_type == RTM_ADD) && (rtsock_find_rtm_sa(rtm, RTA_NETMASK)))
1292e02d3fe7SAlexander V. Chernikov 			break;
1293e02d3fe7SAlexander V. Chernikov 	}
1294e02d3fe7SAlexander V. Chernikov 
1295e02d3fe7SAlexander V. Chernikov 	/* This should be a message for the prefix route */
1296e02d3fe7SAlexander V. Chernikov 	verify_route_message(rtm, RTM_ADD, (struct sockaddr *)&c->net4,
1297e02d3fe7SAlexander V. Chernikov 	    (struct sockaddr *)&c->mask4, NULL);
1298e02d3fe7SAlexander V. Chernikov 
1299e02d3fe7SAlexander V. Chernikov 	/* gateway should be link sdl with ifindex of an address interface */
1300e02d3fe7SAlexander V. Chernikov 	verify_link_gateway(rtm, c->ifindex);
1301e02d3fe7SAlexander V. Chernikov 
1302e02d3fe7SAlexander V. Chernikov 	int expected_rt_flags = RTF_UP | RTF_DONE | RTF_PINNED;
1303e02d3fe7SAlexander V. Chernikov 	verify_route_message_extra(rtm, c->ifindex, expected_rt_flags);
1304e02d3fe7SAlexander V. Chernikov }
1305e02d3fe7SAlexander V. Chernikov 
1306e02d3fe7SAlexander V. Chernikov RTM_DECLARE_ROOT_TEST(rtm_add_v4_gu_ifa_ordered_success,
1307e02d3fe7SAlexander V. Chernikov     "Tests ordering of the messages for IPv4 unicast ifaddr assignment");
1308e02d3fe7SAlexander V. Chernikov 
1309e02d3fe7SAlexander V. Chernikov ATF_TC_BODY(rtm_add_v4_gu_ifa_ordered_success, tc)
1310e02d3fe7SAlexander V. Chernikov {
1311e02d3fe7SAlexander V. Chernikov 	DECLARE_TEST_VARS;
1312e02d3fe7SAlexander V. Chernikov 
1313e02d3fe7SAlexander V. Chernikov 	c = presetup_ipv4_iface(tc);
1314e02d3fe7SAlexander V. Chernikov 
1315e02d3fe7SAlexander V. Chernikov 	c->rtsock_fd = rtsock_setup_socket();
1316e02d3fe7SAlexander V. Chernikov 
1317e02d3fe7SAlexander V. Chernikov 	ret = iface_setup_addr(c->ifname, c->addr4_str, c->plen4);
1318e02d3fe7SAlexander V. Chernikov 
1319e02d3fe7SAlexander V. Chernikov 	int count = 0, tries = 0;
1320e02d3fe7SAlexander V. Chernikov 
1321e02d3fe7SAlexander V. Chernikov 	enum msgtype {
1322e02d3fe7SAlexander V. Chernikov 		MSG_IFADDR,
1323e02d3fe7SAlexander V. Chernikov 		MSG_PREFIXROUTE,
1324e02d3fe7SAlexander V. Chernikov 		MSG_MAX,
1325e02d3fe7SAlexander V. Chernikov 	};
1326e02d3fe7SAlexander V. Chernikov 
1327e02d3fe7SAlexander V. Chernikov 	int msg_array[MSG_MAX];
1328e02d3fe7SAlexander V. Chernikov 
1329e02d3fe7SAlexander V. Chernikov 	bzero(msg_array, sizeof(msg_array));
1330e02d3fe7SAlexander V. Chernikov 
1331e02d3fe7SAlexander V. Chernikov 	while (count < 2 && tries < 20) {
1332e02d3fe7SAlexander V. Chernikov 		rtm = rtsock_read_rtm(c->rtsock_fd, buffer, sizeof(buffer));
1333e02d3fe7SAlexander V. Chernikov 		tries++;
1334e02d3fe7SAlexander V. Chernikov 		/* Classify */
1335e02d3fe7SAlexander V. Chernikov 		if (rtm->rtm_type == RTM_NEWADDR) {
1336e02d3fe7SAlexander V. Chernikov 			RLOG("MSG_IFADDR: %d", count);
1337e02d3fe7SAlexander V. Chernikov 			msg_array[MSG_IFADDR] = count++;
1338e02d3fe7SAlexander V. Chernikov 			continue;
1339e02d3fe7SAlexander V. Chernikov 		}
1340e02d3fe7SAlexander V. Chernikov 
1341e02d3fe7SAlexander V. Chernikov 		/* Find RTM_ADD with netmask - this should skip both host route and LLADDR */
1342e02d3fe7SAlexander V. Chernikov 		if ((rtm->rtm_type == RTM_ADD) && (rtsock_find_rtm_sa(rtm, RTA_NETMASK))) {
1343e02d3fe7SAlexander V. Chernikov 			RLOG("MSG_PREFIXROUTE: %d", count);
1344e02d3fe7SAlexander V. Chernikov 			msg_array[MSG_PREFIXROUTE] = count++;
1345e02d3fe7SAlexander V. Chernikov 			continue;
1346e02d3fe7SAlexander V. Chernikov 		}
1347e02d3fe7SAlexander V. Chernikov 
1348e02d3fe7SAlexander V. Chernikov 		RLOG("skipping msg type %s, try: %d", rtsock_print_cmdtype(rtm->rtm_type),
1349e02d3fe7SAlexander V. Chernikov 		    tries);
1350e02d3fe7SAlexander V. Chernikov 	}
1351e02d3fe7SAlexander V. Chernikov 
1352e02d3fe7SAlexander V. Chernikov 	/* TODO: verify multicast */
1353e02d3fe7SAlexander V. Chernikov 	ATF_REQUIRE_MSG(count == 2, "Received only %d/2 messages", count);
1354e02d3fe7SAlexander V. Chernikov 	ATF_REQUIRE_MSG(msg_array[MSG_IFADDR] == 0, "ifaddr message is not the first");
1355e02d3fe7SAlexander V. Chernikov }
1356e02d3fe7SAlexander V. Chernikov 
1357e02d3fe7SAlexander V. Chernikov RTM_DECLARE_ROOT_TEST(rtm_del_v4_gu_ifa_prefixroute_success,
1358e02d3fe7SAlexander V. Chernikov     "Tests validness for the prefix route removal after ifaddr assignment");
1359e02d3fe7SAlexander V. Chernikov 
1360e02d3fe7SAlexander V. Chernikov ATF_TC_BODY(rtm_del_v4_gu_ifa_prefixroute_success, tc)
1361e02d3fe7SAlexander V. Chernikov {
1362e02d3fe7SAlexander V. Chernikov 	DECLARE_TEST_VARS;
1363e02d3fe7SAlexander V. Chernikov 
1364e02d3fe7SAlexander V. Chernikov 	c = presetup_ipv4_iface(tc);
1365e02d3fe7SAlexander V. Chernikov 
1366e02d3fe7SAlexander V. Chernikov 
1367e02d3fe7SAlexander V. Chernikov 	ret = iface_setup_addr(c->ifname, c->addr4_str, c->plen4);
1368e02d3fe7SAlexander V. Chernikov 
1369e02d3fe7SAlexander V. Chernikov 	c->rtsock_fd = rtsock_setup_socket();
1370e02d3fe7SAlexander V. Chernikov 
1371e02d3fe7SAlexander V. Chernikov 	ret = iface_delete_addr(c->ifname, c->addr4_str);
1372e02d3fe7SAlexander V. Chernikov 
1373e02d3fe7SAlexander V. Chernikov 	while (true) {
1374e02d3fe7SAlexander V. Chernikov 		rtm = rtsock_read_rtm(c->rtsock_fd, buffer, sizeof(buffer));
1375e02d3fe7SAlexander V. Chernikov 		/* Find RTM_ADD with netmask - this should skip both host route and LLADDR */
1376e02d3fe7SAlexander V. Chernikov 		if ((rtm->rtm_type == RTM_DELETE) && (rtsock_find_rtm_sa(rtm, RTA_NETMASK)))
1377e02d3fe7SAlexander V. Chernikov 			break;
1378e02d3fe7SAlexander V. Chernikov 	}
1379e02d3fe7SAlexander V. Chernikov 
1380e02d3fe7SAlexander V. Chernikov 	/* This should be a message for the prefix route */
1381e02d3fe7SAlexander V. Chernikov 	verify_route_message(rtm, RTM_DELETE, (struct sockaddr *)&c->net4,
1382e02d3fe7SAlexander V. Chernikov 	    (struct sockaddr *)&c->mask4, NULL);
1383e02d3fe7SAlexander V. Chernikov 
1384e02d3fe7SAlexander V. Chernikov 	/* gateway should be link sdl with ifindex of an address interface */
1385e02d3fe7SAlexander V. Chernikov 	verify_link_gateway(rtm, c->ifindex);
1386e02d3fe7SAlexander V. Chernikov 
1387e02d3fe7SAlexander V. Chernikov 	int expected_rt_flags = RTF_DONE | RTF_PINNED;
1388e02d3fe7SAlexander V. Chernikov 	verify_route_message_extra(rtm, c->ifindex, expected_rt_flags);
1389e02d3fe7SAlexander V. Chernikov }
1390775dc861SAlexander V. Chernikov 
1391775dc861SAlexander V. Chernikov 
1392775dc861SAlexander V. Chernikov ATF_TP_ADD_TCS(tp)
1393775dc861SAlexander V. Chernikov {
1394775dc861SAlexander V. Chernikov 	ATF_TP_ADD_TC(tp, rtm_get_v4_exact_success);
1395775dc861SAlexander V. Chernikov 	ATF_TP_ADD_TC(tp, rtm_get_v4_lpm_success);
139667f2f67fSAlex Richardson 	ATF_TP_ADD_TC(tp, rtm_get_v4_hostbits_success);
1397775dc861SAlexander V. Chernikov 	ATF_TP_ADD_TC(tp, rtm_get_v4_empty_dst_failure);
139867f2f67fSAlex Richardson 	ATF_TP_ADD_TC(tp, rtm_add_v4_no_rtf_host_success);
1399775dc861SAlexander V. Chernikov 	ATF_TP_ADD_TC(tp, rtm_add_v4_gw_direct_success);
1400775dc861SAlexander V. Chernikov 	ATF_TP_ADD_TC(tp, rtm_del_v4_prefix_nogw_success);
1401775dc861SAlexander V. Chernikov 	ATF_TP_ADD_TC(tp, rtm_add_v6_gu_gw_gu_direct_success);
1402775dc861SAlexander V. Chernikov 	ATF_TP_ADD_TC(tp, rtm_del_v6_gu_prefix_nogw_success);
1403272bd698SAlexander V. Chernikov 	ATF_TP_ADD_TC(tp, rtm_change_v4_gw_success);
1404272bd698SAlexander V. Chernikov 	ATF_TP_ADD_TC(tp, rtm_change_v4_mtu_success);
14051b95005eSAlexander V. Chernikov 	ATF_TP_ADD_TC(tp, rtm_change_v4_flags_success);
1406272bd698SAlexander V. Chernikov 	ATF_TP_ADD_TC(tp, rtm_change_v6_gw_success);
1407272bd698SAlexander V. Chernikov 	ATF_TP_ADD_TC(tp, rtm_change_v6_mtu_success);
14081b95005eSAlexander V. Chernikov 	ATF_TP_ADD_TC(tp, rtm_change_v6_flags_success);
1409e02d3fe7SAlexander V. Chernikov 	/* ifaddr tests */
1410e02d3fe7SAlexander V. Chernikov 	ATF_TP_ADD_TC(tp, rtm_add_v6_gu_ifa_hostroute_success);
1411e02d3fe7SAlexander V. Chernikov 	ATF_TP_ADD_TC(tp, rtm_add_v6_gu_ifa_prefixroute_success);
1412e02d3fe7SAlexander V. Chernikov 	ATF_TP_ADD_TC(tp, rtm_add_v6_gu_ifa_ordered_success);
1413e02d3fe7SAlexander V. Chernikov 	ATF_TP_ADD_TC(tp, rtm_del_v6_gu_ifa_hostroute_success);
1414e02d3fe7SAlexander V. Chernikov 	ATF_TP_ADD_TC(tp, rtm_del_v6_gu_ifa_prefixroute_success);
1415e02d3fe7SAlexander V. Chernikov 	ATF_TP_ADD_TC(tp, rtm_add_v4_gu_ifa_ordered_success);
1416e02d3fe7SAlexander V. Chernikov 	ATF_TP_ADD_TC(tp, rtm_del_v4_gu_ifa_prefixroute_success);
141734a5582cSAlexander V. Chernikov 	/* temporal routes */
141834a5582cSAlexander V. Chernikov 	ATF_TP_ADD_TC(tp, rtm_add_v4_temporal1_success);
141934a5582cSAlexander V. Chernikov 	ATF_TP_ADD_TC(tp, rtm_add_v6_temporal1_success);
1420775dc861SAlexander V. Chernikov 
1421775dc861SAlexander V. Chernikov 	return (atf_no_error());
1422775dc861SAlexander V. Chernikov }
1423775dc861SAlexander V. Chernikov 
1424