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