xref: /xnu-8792.81.2/tests/net_bridge.c (revision 19c3b8c28c31cb8130e034cfb5df6bf9ba342d90)
1 /*
2  * Copyright (c) 2019-2022 Apple Inc. All rights reserved.
3  *
4  * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5  *
6  * This file contains Original Code and/or Modifications of Original Code
7  * as defined in and that are subject to the Apple Public Source License
8  * Version 2.0 (the 'License'). You may not use this file except in
9  * compliance with the License. The rights granted to you under the License
10  * may not be used to create, or enable the creation or redistribution of,
11  * unlawful or unlicensed copies of an Apple operating system, or to
12  * circumvent, violate, or enable the circumvention or violation of, any
13  * terms of an Apple operating system software license agreement.
14  *
15  * Please obtain a copy of the License at
16  * http://www.opensource.apple.com/apsl/ and read it before using this file.
17  *
18  * The Original Code and all software distributed under the License are
19  * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22  * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23  * Please see the License for the specific language governing rights and
24  * limitations under the License.
25  *
26  * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27  */
28 
29 /*
30  * net_bridge.c
31  * - test if_bridge.c functionality
32  */
33 
34 #include <darwintest.h>
35 #include <stdio.h>
36 #include <unistd.h>
37 #include <stddef.h>
38 #include <stdlib.h>
39 #include <string.h>
40 #include <sys/socket.h>
41 #include <arpa/inet.h>
42 #include <sys/event.h>
43 #include <net/if.h>
44 #include <netinet/in.h>
45 #include <netinet6/in6_var.h>
46 #include <netinet6/nd6.h>
47 #include <netinet/in.h>
48 #include <netinet/ip.h>
49 #include <netinet/udp.h>
50 #include <netinet/bootp.h>
51 #include <netinet/tcp.h>
52 #include <netinet/if_ether.h>
53 #include <netinet/ip6.h>
54 #include <netinet/icmp6.h>
55 #include <net/if_arp.h>
56 #include <net/bpf.h>
57 #include <net/if_bridgevar.h>
58 #include <net/if_fake_var.h>
59 #include <sys/ioctl.h>
60 #include <sys/types.h>
61 #include <sys/stat.h>
62 #include <errno.h>
63 #include <pthread.h>
64 #include <stdbool.h>
65 #include <TargetConditionals.h>
66 #include <darwintest_utils.h>
67 #include "inet_transfer.h"
68 #include "bpflib.h"
69 #include "in_cksum.h"
70 
71 static bool S_debug;
72 static bool S_cleaning_up;
73 
74 #define ALL_ADDRS (uint32_t)(-1)
75 
76 #define DHCP_PAYLOAD_MIN        sizeof(struct bootp)
77 #define DHCP_FLAGS_BROADCAST    ((u_short)0x8000)
78 
79 typedef union {
80 	char            bytes[DHCP_PAYLOAD_MIN];
81 	/* force 4-byte alignment */
82 	uint32_t        words[DHCP_PAYLOAD_MIN / sizeof(uint32_t)];
83 } dhcp_min_payload, *dhcp_min_payload_t;
84 
85 #define ETHER_PKT_LEN           (ETHER_HDR_LEN + ETHERMTU)
86 typedef union {
87 	char            bytes[ETHER_PKT_LEN];
88 	/* force 4-byte aligment */
89 	uint32_t        words[ETHER_PKT_LEN / sizeof(uint32_t)];
90 } ether_packet, *ether_packet_t;
91 
92 typedef struct {
93 	struct ip       ip;
94 	struct udphdr   udp;
95 } ip_udp_header_t;
96 
97 typedef struct {
98 	struct in_addr  src_ip;
99 	struct in_addr  dst_ip;
100 	char            zero;
101 	char            proto;
102 	unsigned short  length;
103 } udp_pseudo_hdr_t;
104 
105 typedef struct {
106 	struct ip       ip;
107 	struct tcphdr   tcp;
108 } ip_tcp_header_t;
109 
110 typedef union {
111 	ip_udp_header_t udp;
112 	ip_tcp_header_t tcp;
113 } ip_udp_tcp_header_u;
114 
115 typedef struct {
116 	struct in_addr  src_ip;
117 	struct in_addr  dst_ip;
118 	char            zero;
119 	char            proto;
120 	unsigned short  length;
121 } tcp_pseudo_hdr_t;
122 
123 typedef struct {
124 	struct ip6_hdr  ip6;
125 	struct udphdr   udp;
126 } ip6_udp_header_t;
127 
128 typedef struct {
129 	struct in6_addr src_ip;
130 	struct in6_addr dst_ip;
131 	char            zero;
132 	char            proto;
133 	unsigned short  length;
134 } udp6_pseudo_hdr_t;
135 
136 typedef struct {
137 	char            ifname[IFNAMSIZ];       /* port we do I/O on */
138 	ether_addr_t    mac;
139 	char            member_ifname[IFNAMSIZ]; /* member of bridge */
140 	ether_addr_t    member_mac;
141 	int             fd;
142 	u_int           unit;
143 	u_int           num_addrs;
144 	void *          rx_buf;
145 	int             rx_buf_size;
146 	bool            mac_nat;
147 	struct in_addr  ip;
148 	struct in6_addr ip6;
149 	u_short         if_index;
150 
151 	u_int           test_count;
152 	u_int           test_address_count;
153 	uint64_t        test_address_present;
154 } switch_port, *switch_port_t;
155 
156 typedef struct {
157 	u_int           size;
158 	u_int           count;
159 	bool            mac_nat;
160 	switch_port     list[1];
161 } switch_port_list, * switch_port_list_t;
162 
163 static struct in_addr   bridge_ip_addr;
164 static struct in6_addr  bridge_ipv6_addr;
165 static u_short          bridge_if_index;
166 
167 static struct ifbareq *
168 bridge_rt_table_copy(u_int * ret_count);
169 
170 static void
171 bridge_rt_table_log(struct ifbareq *rt_table, u_int count);
172 
173 static struct ifbrmne *
174 bridge_mac_nat_entries_copy(u_int * ret_count);
175 
176 static void
177 bridge_mac_nat_entries_log(struct ifbrmne * entries, u_int count);
178 
179 static void
180 ifnet_get_lladdr(int s, const char * ifname, ether_addr_t * eaddr);
181 
182 #define SETUP_FLAGS_MAC_NAT             0x1
183 #define SETUP_FLAGS_CHECKSUM_OFFLOAD    0x2
184 #define SETUP_FLAGS_ATTACH_STACK        0x4
185 #define SETUP_FLAGS_TRAILERS            0x8
186 
187 #define s6_addr16 __u6_addr.__u6_addr16
188 
189 static int
inet_dgram_socket(void)190 inet_dgram_socket(void)
191 {
192 	int     s;
193 
194 	s = socket(AF_INET, SOCK_DGRAM, 0);
195 	T_QUIET;
196 	T_ASSERT_POSIX_SUCCESS(s, "socket(AF_INET, SOCK_DGRAM, 0)");
197 	return s;
198 }
199 
200 static int
inet6_dgram_socket(void)201 inet6_dgram_socket(void)
202 {
203 	int     s;
204 
205 	s = socket(AF_INET6, SOCK_DGRAM, 0);
206 	T_QUIET;
207 	T_ASSERT_POSIX_SUCCESS(s, "socket(AF_INET6, SOCK_DGRAM, 0)");
208 	return s;
209 }
210 
211 static int
routing_socket(void)212 routing_socket(void)
213 {
214 	int     s;
215 
216 	s = socket(PF_ROUTE, SOCK_RAW, PF_ROUTE);
217 	T_QUIET;
218 	T_ASSERT_POSIX_SUCCESS(s, "socket(PF_ROUTE, SOCK_RAW, PF_ROUTE)");
219 	return s;
220 }
221 
222 
223 /**
224 ** Packet creation/display
225 **/
226 #define BOOTP_SERVER_PORT       67
227 #define BOOTP_CLIENT_PORT       68
228 
229 #define TEST_SOURCE_PORT        14
230 #define TEST_DEST_PORT          15
231 
232 #define EA_UNIT_INDEX           4
233 #define EA_ADDR_INDEX           5
234 
235 static void
set_ethernet_address(ether_addr_t * eaddr,u_int unit,u_int addr_index)236 set_ethernet_address(ether_addr_t *eaddr, u_int unit, u_int addr_index)
237 {
238 	u_char  *a = eaddr->octet;
239 
240 	a[0] = 0x02;
241 	a[2] = 0x00;
242 	a[3] = 0x00;
243 	a[1] = 0x00;
244 	a[EA_UNIT_INDEX] = (u_char)unit;
245 	a[EA_ADDR_INDEX] = (u_char)addr_index;
246 }
247 
248 #define TEN_NET                 0x0a000000
249 #define TEN_1_NET               (TEN_NET | 0x010000)
250 
251 static void
get_ipv4_address(u_int unit,u_int addr_index,struct in_addr * ip)252 get_ipv4_address(u_int unit, u_int addr_index, struct in_addr *ip)
253 {
254 	/* up to 255 units, 255 addresses */
255 	ip->s_addr = htonl(TEN_1_NET | (unit << 8) | addr_index);
256 	return;
257 }
258 
259 #define IN6ADDR_ULA_INIT \
260 	{{{ 0xfd, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
261 	    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }}}
262 
263 static struct in6_addr ula_address = IN6ADDR_ULA_INIT;
264 
265 #define ULA_UNIT_INDEX  14
266 #define ULA_ADDR_INDEX  15
267 
268 static void
get_ipv6_ula_address(u_int unit,u_int addr_index,struct in6_addr * ip)269 get_ipv6_ula_address(u_int unit, u_int addr_index, struct in6_addr *ip)
270 {
271 	*ip = ula_address;
272 	/* up to 255 units, 255 addresses */
273 	ip->s6_addr[ULA_UNIT_INDEX] = (uint8_t)unit;
274 	ip->s6_addr[ULA_ADDR_INDEX] = (uint8_t)addr_index;
275 }
276 
277 #define ND6_EUI64_GBIT  0x01
278 #define ND6_EUI64_UBIT  0x02
279 
280 #define ND6_EUI64_TO_IFID(in6) \
281 	do {(in6)->s6_addr[8] ^= ND6_EUI64_UBIT; } while (0)
282 static void
get_ipv6_ll_address(const ether_addr_t * mac,struct in6_addr * in6)283 get_ipv6_ll_address(const ether_addr_t *mac, struct in6_addr * in6)
284 {
285 	const u_char *  addr = mac->octet;
286 
287 	bzero(in6, sizeof(*in6));
288 	in6->s6_addr16[0] = htons(0xfe80);
289 	in6->s6_addr[8] = addr[0];
290 	in6->s6_addr[9] = addr[1];
291 	in6->s6_addr[10] = addr[2];
292 	in6->s6_addr[11] = 0xff;
293 	in6->s6_addr[12] = 0xfe;
294 	in6->s6_addr[13] = addr[3];
295 	in6->s6_addr[14] = addr[4];
296 	in6->s6_addr[15] = addr[5];
297 	ND6_EUI64_TO_IFID(in6);
298 	return;
299 }
300 
301 static void
get_ip_address(uint8_t af,u_int unit,u_int addr_index,union ifbrip * ip)302 get_ip_address(uint8_t af, u_int unit, u_int addr_index, union ifbrip *ip)
303 {
304 	switch (af) {
305 	case AF_INET:
306 		get_ipv4_address(unit, addr_index, &ip->ifbrip_addr);
307 		break;
308 	case AF_INET6:
309 		get_ipv6_ula_address(unit, addr_index, &ip->ifbrip_addr6);
310 		break;
311 	default:
312 		T_FAIL("unrecognized address family %u", af);
313 		break;
314 	}
315 }
316 
317 static bool
ip_addresses_are_equal(uint8_t af,union ifbrip * ip1,union ifbrip * ip2)318 ip_addresses_are_equal(uint8_t af, union ifbrip * ip1, union ifbrip * ip2)
319 {
320 	bool    equal;
321 
322 	switch (af) {
323 	case AF_INET:
324 		equal = (ip1->ifbrip_addr.s_addr == ip2->ifbrip_addr.s_addr);
325 		break;
326 	case AF_INET6:
327 		equal = IN6_ARE_ADDR_EQUAL(&ip1->ifbrip_addr6,
328 		    &ip2->ifbrip_addr6);
329 		break;
330 	default:
331 		T_FAIL("unrecognized address family %u", af);
332 		equal = false;
333 		break;
334 	}
335 	return equal;
336 }
337 
338 static ether_addr_t ether_broadcast = {
339 	{ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }
340 };
341 
342 static ether_addr_t ether_external = {
343 	{ 0x80, 0x00, 0x00, 0x00, 0x00, 0x01 }
344 };
345 
346 static inline struct in_addr
get_external_ipv4_address(void)347 get_external_ipv4_address(void)
348 {
349 	struct in_addr  ip;
350 
351 	/* IP 10.1.255.1 */
352 	ip.s_addr = htonl(TEN_1_NET | 0xff01);
353 	return ip;
354 }
355 
356 static inline void
get_external_ip_address(uint8_t af,union ifbrip * ip)357 get_external_ip_address(uint8_t af, union ifbrip * ip)
358 {
359 	switch (af) {
360 	case AF_INET:
361 		/* IP 10.1.255.1 */
362 		ip->ifbrip_addr = get_external_ipv4_address();
363 		break;
364 	case AF_INET6:
365 		/* fd80::1 */
366 		ip->ifbrip_addr6 = ula_address;
367 		ip->ifbrip_addr6.s6_addr[1] = 0x80;
368 		ip->ifbrip_addr6.s6_addr[15] = 0x01;
369 		break;
370 	default:
371 		T_FAIL("unrecognized address family %u", af);
372 		break;
373 	}
374 }
375 
376 static inline void
get_broadcast_ip_address(uint8_t af,union ifbrip * ip)377 get_broadcast_ip_address(uint8_t af, union ifbrip * ip)
378 {
379 	switch (af) {
380 	case AF_INET:
381 		ip->ifbrip_addr.s_addr = INADDR_BROADCAST;
382 		break;
383 	case AF_INET6:
384 		/* 0xff0e::0 linklocal scope multicast */
385 		ip->ifbrip_addr6 = in6addr_any;
386 		ip->ifbrip_addr6.s6_addr[0] = 0xff;
387 		ip->ifbrip_addr6.s6_addr[1] = __IPV6_ADDR_SCOPE_LINKLOCAL;
388 		break;
389 	default:
390 		T_FAIL("unrecognized address family %u", af);
391 		break;
392 	}
393 }
394 static void
siocaifaddr(int s,char * ifname,struct in_addr addr)395 siocaifaddr(int s, char *ifname, struct in_addr addr)
396 {
397 	struct ifaliasreq       ifra;
398 	char                    ntopbuf_ip[INET_ADDRSTRLEN];
399 	char                    ntopbuf_mask[INET_ADDRSTRLEN];
400 	int                     ret;
401 	struct sockaddr_in *    sin;
402 
403 	bzero(&ifra, sizeof(ifra));
404 	strncpy(ifra.ifra_name, ifname, sizeof(ifra.ifra_name));
405 
406 	sin = (struct sockaddr_in *)(void *)&ifra.ifra_addr;
407 	sin->sin_len = sizeof(*sin);
408 	sin->sin_family = AF_INET;
409 	sin->sin_addr = addr;
410 
411 	sin = (struct sockaddr_in *)(void *)&ifra.ifra_mask;
412 	sin->sin_len = sizeof(*sin);
413 	sin->sin_family = AF_INET;
414 	sin->sin_addr.s_addr = htonl(IN_CLASSC_NET);
415 
416 	ret = ioctl(s, SIOCAIFADDR, &ifra);
417 	inet_ntop(AF_INET, &addr, ntopbuf_ip, sizeof(ntopbuf_ip));
418 	inet_ntop(AF_INET, &sin->sin_addr, ntopbuf_mask, sizeof(ntopbuf_mask));
419 	T_ASSERT_POSIX_SUCCESS(ret, "SIOCAIFADDR %s %s %s",
420 	    ifname, ntopbuf_ip, ntopbuf_mask);
421 	return;
422 }
423 
424 #if 0
425 static void
426 in6_len2mask(struct in6_addr * mask, int len)
427 {
428 	int i;
429 
430 	bzero(mask, sizeof(*mask));
431 	for (i = 0; i < len / 8; i++) {
432 		mask->s6_addr[i] = 0xff;
433 	}
434 	if (len % 8) {
435 		mask->s6_addr[i] = (0xff00 >> (len % 8)) & 0xff;
436 	}
437 }
438 
439 static void
440 siocaifaddr_in6(int s, char *ifname, struct in6_addr *addr)
441 {
442 	struct in6_aliasreq     ifra;
443 	char                    ntopbuf_ip[INET6_ADDRSTRLEN];
444 	int                     result;
445 	struct sockaddr_in6 *   sin;
446 
447 	bzero(&ifra, sizeof(ifra));
448 	(void) strncpy(ifra.ifra_name, ifname, sizeof(ifra.ifra_name));
449 
450 	sin = (struct sockaddr_in6 *)(&ifra.ifra_addr);
451 	sin->sin6_family = AF_INET6;
452 	sin->sin6_len = sizeof(*sin);
453 	sin->sin6_addr = *addr;
454 #define _PREFIX_LEN_64          64
455 	sin = (struct sockaddr_in6 *)&ifra.ifra_prefixmask;
456 	sin->sin6_family = AF_INET6;
457 	sin->sin6_len = sizeof(*sin);
458 	in6_len2mask(&sin->sin6_addr, _PREFIX_LEN_64);
459 	ifra.ifra_lifetime.ia6t_vltime = ND6_INFINITE_LIFETIME;
460 	ifra.ifra_lifetime.ia6t_pltime = ND6_INFINITE_LIFETIME;
461 
462 	result = ioctl(s, SIOCAIFADDR_IN6, &ifra);
463 	inet_ntop(AF_INET6, addr, ntopbuf_ip, sizeof(ntopbuf_ip));
464 	T_ASSERT_POSIX_SUCCESS(result, "SIOCAIFADDR_IN6 %s %s/64",
465 	    ifname, ntopbuf_ip);
466 	return;
467 }
468 #endif
469 
470 static void
siocll_start(int s,const char * ifname)471 siocll_start(int s, const char * ifname)
472 {
473 	struct in6_aliasreq     ifra_in6;
474 	int                     result;
475 
476 	bzero(&ifra_in6, sizeof(ifra_in6));
477 	strncpy(ifra_in6.ifra_name, ifname, sizeof(ifra_in6.ifra_name));
478 	result = ioctl(s, SIOCLL_START, &ifra_in6);
479 	T_QUIET;
480 	T_ASSERT_POSIX_SUCCESS(result, "SIOCLL_START %s", ifname);
481 	return;
482 }
483 
484 static void
nd_flags_set(int s,const char * if_name,uint32_t set_flags,uint32_t clear_flags)485 nd_flags_set(int s, const char * if_name,
486     uint32_t set_flags, uint32_t clear_flags)
487 {
488 	uint32_t                new_flags;
489 	struct in6_ndireq       nd;
490 	int                     result;
491 
492 	bzero(&nd, sizeof(nd));
493 	strncpy(nd.ifname, if_name, sizeof(nd.ifname));
494 	result = ioctl(s, SIOCGIFINFO_IN6, &nd);
495 	T_ASSERT_POSIX_SUCCESS(result, "SIOCGIFINFO_IN6(%s)", if_name);
496 	new_flags = nd.ndi.flags;
497 	if (set_flags) {
498 		new_flags |= set_flags;
499 	}
500 	if (clear_flags) {
501 		new_flags &= ~clear_flags;
502 	}
503 	if (new_flags != nd.ndi.flags) {
504 		nd.ndi.flags = new_flags;
505 		result = ioctl(s, SIOCSIFINFO_FLAGS, (caddr_t)&nd);
506 		T_ASSERT_POSIX_SUCCESS(result,
507 		    "SIOCSIFINFO_FLAGS(%s) 0x%x",
508 		    if_name, nd.ndi.flags);
509 	}
510 	return;
511 }
512 
513 
514 static void
siocprotoattach_in6(int s,const char * name)515 siocprotoattach_in6(int s, const char * name)
516 {
517 	struct in6_aliasreq ifra;
518 	int                 result;
519 
520 	bzero(&ifra, sizeof(ifra));
521 	strncpy(ifra.ifra_name, name, sizeof(ifra.ifra_name));
522 	result = ioctl(s, SIOCPROTOATTACH_IN6, &ifra);
523 	T_ASSERT_POSIX_SUCCESS(result, "SIOCPROTOATTACH_IN6(%s)", name);
524 	return;
525 }
526 
527 
528 static void
start_ipv6(int s,const char * ifname)529 start_ipv6(int s, const char * ifname)
530 {
531 	/* attach IPv6 */
532 	siocprotoattach_in6(s, ifname);
533 
534 	/* disable DAD to avoid 1 second delay (rdar://problem/73270401) */
535 	nd_flags_set(s, ifname, 0, ND6_IFF_DAD);
536 
537 	/* start IPv6LL */
538 	siocll_start(s, ifname);
539 
540 	return;
541 }
542 
543 /*
544  * Stolen/modified from IPMonitor/ip_plugin.c
545  */
546 /*
547  * Define: ROUTE_MSG_ADDRS_SPACE
548  * Purpose:
549  *   Since sizeof(sockaddr_dl) > sizeof(sockaddr_in), we need space for
550  *   3 sockaddr_in's and 2 sockaddr_dl's, but pad it just in case
551  *   someone changes the code and doesn't think to modify this.
552  */
553 #define ROUTE_MSG_ADDRS_SPACE   (3 * sizeof(struct sockaddr_in) \
554 	                         + 2 * sizeof(struct sockaddr_dl) \
555 	                         + 128)
556 typedef struct {
557 	struct rt_msghdr    hdr;
558 	char                addrs[ROUTE_MSG_ADDRS_SPACE];
559 } route_msg;
560 
561 typedef unsigned short  IFIndex;
562 
563 typedef enum {
564 	kRouteFlagsIsScoped         = 0x0001,
565 	kRouteFlagsHasGateway       = 0x0002,
566 	kRouteFlagsIsHost           = 0x0004,
567 } RouteFlags;
568 
569 typedef struct {
570 	IFIndex         ifindex;
571 	RouteFlags      flags;
572 	struct in_addr  dest;
573 	struct in_addr  mask;
574 	struct in_addr  gateway;
575 	struct in_addr  ifa;
576 } IPv4Route, * IPv4RouteRef;
577 
578 /*
579  * Function: IPv4RouteApply
580  * Purpose:
581  *   Add or remove the specified route to/from the kernel routing table.
582  */
583 static int
IPv4RouteApply(IPv4RouteRef route,uint8_t cmd,int s)584 IPv4RouteApply(IPv4RouteRef route, uint8_t cmd, int s)
585 {
586 	size_t          len;
587 	int             ret = 0;
588 	route_msg       rtmsg;
589 	union {
590 		struct sockaddr_in *    in_p;
591 		struct sockaddr_dl *    dl_p;
592 		char *                  ptr;
593 	} rtaddr;
594 	static int      rtm_seq;
595 	static bool     rtm_seq_inited;
596 
597 	if (!rtm_seq_inited) {
598 		rtm_seq_inited = true;
599 		rtm_seq = (int)arc4random();
600 	}
601 	if (route->ifindex == 0) {
602 		T_LOG("no interface specified, ignoring %s",
603 		    inet_ntoa(route->dest));
604 		return ENXIO;
605 	}
606 	if (s < 0) {
607 		T_LOG("invalid routing socket");
608 		return EBADF;
609 	}
610 	memset(&rtmsg, 0, sizeof(rtmsg));
611 	rtmsg.hdr.rtm_type = cmd;
612 	rtmsg.hdr.rtm_version = RTM_VERSION;
613 	rtmsg.hdr.rtm_seq = rtm_seq++;
614 	rtmsg.hdr.rtm_addrs = RTA_DST | RTA_GATEWAY | RTA_IFP;
615 	if (route->ifa.s_addr != 0) {
616 		rtmsg.hdr.rtm_addrs |= RTA_IFA;
617 	}
618 	rtmsg.hdr.rtm_flags = RTF_UP | RTF_STATIC;
619 	if ((route->flags & kRouteFlagsIsHost) != 0) {
620 		rtmsg.hdr.rtm_flags |= RTF_HOST;
621 	} else {
622 		rtmsg.hdr.rtm_addrs |= RTA_NETMASK;
623 		if ((route->flags & kRouteFlagsHasGateway) == 0) {
624 			rtmsg.hdr.rtm_flags |= RTF_CLONING;
625 		}
626 	}
627 	if ((route->flags & kRouteFlagsHasGateway) != 0) {
628 		rtmsg.hdr.rtm_flags |= RTF_GATEWAY;
629 	}
630 	if ((route->flags & kRouteFlagsIsScoped) != 0) {
631 		rtmsg.hdr.rtm_index = route->ifindex;
632 		rtmsg.hdr.rtm_flags |= RTF_IFSCOPE;
633 	}
634 
635 	rtaddr.ptr = rtmsg.addrs;
636 
637 	/* dest */
638 	rtaddr.in_p->sin_len = sizeof(*rtaddr.in_p);
639 	rtaddr.in_p->sin_family = AF_INET;
640 	rtaddr.in_p->sin_addr = route->dest;
641 	rtaddr.ptr += sizeof(*rtaddr.in_p);
642 
643 	/* gateway */
644 	if ((rtmsg.hdr.rtm_flags & RTF_GATEWAY) != 0) {
645 		/* gateway is an IP address */
646 		rtaddr.in_p->sin_len = sizeof(*rtaddr.in_p);
647 		rtaddr.in_p->sin_family = AF_INET;
648 		rtaddr.in_p->sin_addr = route->gateway;
649 		rtaddr.ptr += sizeof(*rtaddr.in_p);
650 	} else {
651 		/* gateway is the interface itself */
652 		rtaddr.dl_p->sdl_len = sizeof(*rtaddr.dl_p);
653 		rtaddr.dl_p->sdl_family = AF_LINK;
654 		rtaddr.dl_p->sdl_index = route->ifindex;
655 		rtaddr.ptr += sizeof(*rtaddr.dl_p);
656 	}
657 
658 	/* mask */
659 	if ((rtmsg.hdr.rtm_addrs & RTA_NETMASK) != 0) {
660 		rtaddr.in_p->sin_len = sizeof(*rtaddr.in_p);
661 		rtaddr.in_p->sin_family = AF_INET;
662 		rtaddr.in_p->sin_addr = route->mask;
663 		rtaddr.ptr += sizeof(*rtaddr.in_p);
664 	}
665 
666 	/* interface */
667 	if ((rtmsg.hdr.rtm_addrs & RTA_IFP) != 0) {
668 		rtaddr.dl_p->sdl_len = sizeof(*rtaddr.dl_p);
669 		rtaddr.dl_p->sdl_family = AF_LINK;
670 		rtaddr.dl_p->sdl_index = route->ifindex;
671 		rtaddr.ptr += sizeof(*rtaddr.dl_p);
672 	}
673 	/* interface address */
674 	if ((rtmsg.hdr.rtm_addrs & RTA_IFA) != 0) {
675 		rtaddr.in_p->sin_len = sizeof(*rtaddr.in_p);
676 		rtaddr.in_p->sin_family = AF_INET;
677 		rtaddr.in_p->sin_addr = route->ifa;
678 		rtaddr.ptr += sizeof(*rtaddr.in_p);
679 	}
680 
681 	/* apply the route */
682 	len = (sizeof(rtmsg.hdr)
683 	    + (unsigned long)(rtaddr.ptr - (char *)rtmsg.addrs));
684 	rtmsg.hdr.rtm_msglen = (u_short)len;
685 	if (write(s, &rtmsg, len) == -1) {
686 		ret = errno;
687 		T_LOG("write routing socket failed, (%d) %s",
688 		    errno, strerror(errno));
689 	}
690 	return ret;
691 }
692 
693 static void
add_scoped_subnet_route(int s,char * ifname,u_short if_index,struct in_addr ifa)694 add_scoped_subnet_route(int s, char * ifname, u_short if_index,
695     struct in_addr ifa)
696 {
697 	int             error;
698 	IPv4Route       route;
699 
700 	bzero(&route, sizeof(route));
701 	route.flags |= kRouteFlagsIsScoped;
702 	route.ifa = ifa;
703 	route.ifindex = if_index;
704 	route.mask.s_addr = htonl(IN_CLASSC_NET);
705 	route.dest.s_addr = route.ifa.s_addr & route.mask.s_addr;
706 	T_QUIET;
707 	T_ASSERT_NE((int)route.ifindex, 0, "if_nametoindex(%s)", ifname);
708 	error = IPv4RouteApply(&route, RTM_ADD, s);
709 	T_QUIET;
710 	T_ASSERT_EQ(error, 0, "add scoped subnet route %s %s/24", ifname,
711 	    inet_ntoa(route.dest));
712 	return;
713 }
714 
715 #define ETHER_NTOA_BUFSIZE      (ETHER_ADDR_LEN * 3)
716 static const char *
ether_ntoa_buf(const ether_addr_t * n,char * buf,int buf_size)717 ether_ntoa_buf(const ether_addr_t *n, char * buf, int buf_size)
718 {
719 	char *  str;
720 
721 	str = ether_ntoa(n);
722 	strlcpy(buf, str, buf_size);
723 	return buf;
724 }
725 
726 static const char *
inet_ptrtop(int af,const void * ptr,char * buf,socklen_t buf_size)727 inet_ptrtop(int af, const void * ptr, char * buf, socklen_t buf_size)
728 {
729 	union {
730 		struct in_addr  ip;
731 		struct in6_addr ip6;
732 	} u;
733 
734 	switch (af) {
735 	case AF_INET:
736 		bcopy(ptr, &u.ip, sizeof(u.ip));
737 		break;
738 	case AF_INET6:
739 		bcopy(ptr, &u.ip6, sizeof(u.ip6));
740 		break;
741 	default:
742 		return NULL;
743 	}
744 	return inet_ntop(af, &u, buf, buf_size);
745 }
746 
747 static __inline__ char *
arpop_name(u_int16_t op)748 arpop_name(u_int16_t op)
749 {
750 	switch (op) {
751 	case ARPOP_REQUEST:
752 		return "ARP REQUEST";
753 	case ARPOP_REPLY:
754 		return "ARP REPLY";
755 	case ARPOP_REVREQUEST:
756 		return "REVARP REQUEST";
757 	case ARPOP_REVREPLY:
758 		return "REVARP REPLY";
759 	default:
760 		break;
761 	}
762 	return "<unknown>";
763 }
764 
765 static void
arp_frame_validate(const struct ether_arp * earp,u_int len,bool dump)766 arp_frame_validate(const struct ether_arp * earp, u_int len, bool dump)
767 {
768 	const struct arphdr *   arp_p;
769 	int                     arphrd;
770 	char                    buf_sender_ether[ETHER_NTOA_BUFSIZE];
771 	char                    buf_sender_ip[INET_ADDRSTRLEN];
772 	char                    buf_target_ether[ETHER_NTOA_BUFSIZE];
773 	char                    buf_target_ip[INET_ADDRSTRLEN];
774 
775 	T_QUIET;
776 	T_ASSERT_GE(len, (u_int)sizeof(*earp),
777 	    "%s ARP packet size %u need %u",
778 	    __func__, len, (u_int)sizeof(*earp));
779 	if (!dump) {
780 		return;
781 	}
782 	arp_p = &earp->ea_hdr;
783 	arphrd = ntohs(arp_p->ar_hrd);
784 	T_LOG("%s type=0x%x proto=0x%x", arpop_name(ntohs(arp_p->ar_op)),
785 	    arphrd, ntohs(arp_p->ar_pro));
786 	if (arp_p->ar_hln == sizeof(earp->arp_sha)) {
787 		ether_ntoa_buf((const ether_addr_t *)earp->arp_sha,
788 		    buf_sender_ether,
789 		    sizeof(buf_sender_ether));
790 		ether_ntoa_buf((const ether_addr_t *)earp->arp_tha,
791 		    buf_target_ether,
792 		    sizeof(buf_target_ether));
793 		T_LOG("Sender H/W\t%s", buf_sender_ether);
794 		T_LOG("Target H/W\t%s", buf_target_ether);
795 	}
796 	inet_ptrtop(AF_INET, earp->arp_spa,
797 	    buf_sender_ip, sizeof(buf_sender_ip));
798 	inet_ptrtop(AF_INET, earp->arp_tpa,
799 	    buf_target_ip, sizeof(buf_target_ip));
800 	T_LOG("Sender IP\t%s", buf_sender_ip);
801 	T_LOG("Target IP\t%s", buf_target_ip);
802 	return;
803 }
804 
805 static void
ip_frame_validate(const void * buf,u_int buf_len,bool dump)806 ip_frame_validate(const void * buf, u_int buf_len, bool dump)
807 {
808 	char                    buf_dst[INET_ADDRSTRLEN];
809 	char                    buf_src[INET_ADDRSTRLEN];
810 	const ip_udp_header_t * ip_udp;
811 	u_int                   ip_len;
812 
813 	T_QUIET;
814 	T_ASSERT_GE(buf_len, (u_int)sizeof(struct ip), NULL);
815 	ip_udp = (const ip_udp_header_t *)buf;
816 	ip_len = ntohs(ip_udp->ip.ip_len);
817 	inet_ptrtop(AF_INET, &ip_udp->ip.ip_src,
818 	    buf_src, sizeof(buf_src));
819 	inet_ptrtop(AF_INET, &ip_udp->ip.ip_dst,
820 	    buf_dst, sizeof(buf_dst));
821 	if (dump) {
822 		T_LOG("ip src %s dst %s len %u id %d",
823 		    buf_src, buf_dst, ip_len,
824 		    ntohs(ip_udp->ip.ip_id));
825 	}
826 	T_QUIET;
827 	T_ASSERT_GE(buf_len, ip_len, NULL);
828 	T_QUIET;
829 	T_ASSERT_EQ(ip_udp->ip.ip_v, IPVERSION, NULL);
830 	T_QUIET;
831 	T_ASSERT_EQ((u_int)(ip_udp->ip.ip_hl << 2),
832 	    (u_int)sizeof(struct ip), NULL);
833 	if (ip_udp->ip.ip_p == IPPROTO_UDP) {
834 		u_int   udp_len;
835 		u_int   data_len;
836 
837 		T_QUIET;
838 		T_ASSERT_GE(buf_len, (u_int)sizeof(*ip_udp), NULL);
839 		udp_len = ntohs(ip_udp->udp.uh_ulen);
840 		T_QUIET;
841 		T_ASSERT_GE(udp_len, (u_int)sizeof(ip_udp->udp), NULL);
842 		data_len = udp_len - (u_int)sizeof(ip_udp->udp);
843 		if (dump) {
844 			T_LOG("udp src 0x%x dst 0x%x len %u"
845 			    " csum 0x%x datalen %u",
846 			    ntohs(ip_udp->udp.uh_sport),
847 			    ntohs(ip_udp->udp.uh_dport),
848 			    udp_len,
849 			    ntohs(ip_udp->udp.uh_sum),
850 			    data_len);
851 		}
852 	}
853 }
854 
855 static void
ip6_frame_validate(const void * buf,u_int buf_len,bool dump)856 ip6_frame_validate(const void * buf, u_int buf_len, bool dump)
857 {
858 	char                    buf_dst[INET6_ADDRSTRLEN];
859 	char                    buf_src[INET6_ADDRSTRLEN];
860 	const struct ip6_hdr *  ip6;
861 	u_int                   ip6_len;
862 
863 	T_QUIET;
864 	T_ASSERT_GE(buf_len, (u_int)sizeof(struct ip6_hdr), NULL);
865 	ip6 = (const struct ip6_hdr *)buf;
866 	ip6_len = ntohs(ip6->ip6_plen);
867 	inet_ptrtop(AF_INET6, &ip6->ip6_src, buf_src, sizeof(buf_src));
868 	inet_ptrtop(AF_INET6, &ip6->ip6_dst, buf_dst, sizeof(buf_dst));
869 	if (dump) {
870 		T_LOG("ip6 src %s dst %s len %u", buf_src, buf_dst, ip6_len);
871 	}
872 	T_QUIET;
873 	T_ASSERT_GE(buf_len, ip6_len + (u_int)sizeof(struct ip6_hdr), NULL);
874 	T_QUIET;
875 	T_ASSERT_EQ((ip6->ip6_vfc & IPV6_VERSION_MASK),
876 	    IPV6_VERSION, NULL);
877 	T_QUIET;
878 	switch (ip6->ip6_nxt) {
879 	case IPPROTO_UDP: {
880 		u_int                   data_len;
881 		const ip6_udp_header_t *ip6_udp;
882 		u_int                   udp_len;
883 
884 		ip6_udp = (const ip6_udp_header_t *)buf;
885 		T_QUIET;
886 		T_ASSERT_GE(buf_len, (u_int)sizeof(*ip6_udp), NULL);
887 		udp_len = ntohs(ip6_udp->udp.uh_ulen);
888 		T_QUIET;
889 		T_ASSERT_GE(udp_len, (u_int)sizeof(ip6_udp->udp), NULL);
890 		data_len = udp_len - (u_int)sizeof(ip6_udp->udp);
891 		if (dump) {
892 			T_LOG("udp src 0x%x dst 0x%x len %u"
893 			    " csum 0x%x datalen %u",
894 			    ntohs(ip6_udp->udp.uh_sport),
895 			    ntohs(ip6_udp->udp.uh_dport),
896 			    udp_len,
897 			    ntohs(ip6_udp->udp.uh_sum),
898 			    data_len);
899 		}
900 		break;
901 	}
902 	case IPPROTO_ICMPV6: {
903 		const struct icmp6_hdr *icmp6;
904 		u_int                   icmp6_len;
905 
906 		icmp6_len = buf_len - sizeof(*ip6);
907 		T_QUIET;
908 		T_ASSERT_GE(buf_len, icmp6_len, NULL);
909 		icmp6 = (const struct icmp6_hdr *)(ip6 + 1);
910 		switch (icmp6->icmp6_type) {
911 		case ND_NEIGHBOR_SOLICIT:
912 			if (dump) {
913 				T_LOG("neighbor solicit");
914 			}
915 			break;
916 		case ND_NEIGHBOR_ADVERT:
917 			if (dump) {
918 				T_LOG("neighbor advert");
919 			}
920 			break;
921 		case ND_ROUTER_SOLICIT:
922 			if (dump) {
923 				T_LOG("router solicit");
924 			}
925 			break;
926 		default:
927 			if (dump) {
928 				T_LOG("icmp6 code 0x%x", icmp6->icmp6_type);
929 			}
930 			break;
931 		}
932 		break;
933 	}
934 	default:
935 		break;
936 	}
937 }
938 
939 static void
ethernet_frame_validate(const void * buf,u_int buf_len,bool dump)940 ethernet_frame_validate(const void * buf, u_int buf_len, bool dump)
941 {
942 	char                    ether_dst[ETHER_NTOA_BUFSIZE];
943 	char                    ether_src[ETHER_NTOA_BUFSIZE];
944 	uint16_t                ether_type;
945 	const ether_header_t *  eh_p;
946 
947 	T_QUIET;
948 	T_ASSERT_GE(buf_len, (u_int)sizeof(*eh_p), NULL);
949 	eh_p = (const ether_header_t *)buf;
950 	ether_type = ntohs(eh_p->ether_type);
951 	ether_ntoa_buf((const ether_addr_t *)&eh_p->ether_dhost,
952 	    ether_dst, sizeof(ether_dst));
953 	ether_ntoa_buf((const ether_addr_t *)&eh_p->ether_shost,
954 	    ether_src, sizeof(ether_src));
955 	if (dump) {
956 		T_LOG("ether dst %s src %s type 0x%x",
957 		    ether_dst, ether_src, ether_type);
958 	}
959 	switch (ether_type) {
960 	case ETHERTYPE_IP:
961 		ip_frame_validate(eh_p + 1, (u_int)(buf_len - sizeof(*eh_p)),
962 		    dump);
963 		break;
964 	case ETHERTYPE_ARP:
965 		arp_frame_validate((const struct ether_arp *)(eh_p + 1),
966 		    (u_int)(buf_len - sizeof(*eh_p)),
967 		    dump);
968 		break;
969 	case ETHERTYPE_IPV6:
970 		ip6_frame_validate(eh_p + 1, (u_int)(buf_len - sizeof(*eh_p)),
971 		    dump);
972 		break;
973 	default:
974 		T_FAIL("unrecognized ethertype 0x%x", ether_type);
975 		break;
976 	}
977 }
978 
979 static u_int
ethernet_udp4_frame_populate(void * buf,size_t buf_len,const ether_addr_t * src,struct in_addr src_ip,uint16_t src_port,const ether_addr_t * dst,struct in_addr dst_ip,uint16_t dst_port,const void * data,u_int data_len)980 ethernet_udp4_frame_populate(void * buf, size_t buf_len,
981     const ether_addr_t * src,
982     struct in_addr src_ip,
983     uint16_t src_port,
984     const ether_addr_t * dst,
985     struct in_addr dst_ip,
986     uint16_t dst_port,
987     const void * data, u_int data_len)
988 {
989 	ether_header_t *        eh_p;
990 	u_int                   frame_length;
991 	static int              ip_id;
992 	ip_udp_header_t *       ip_udp;
993 	char *                  payload;
994 	udp_pseudo_hdr_t *      udp_pseudo;
995 
996 	frame_length = (u_int)(sizeof(*eh_p) + sizeof(*ip_udp)) + data_len;
997 	if (buf_len < frame_length) {
998 		return 0;
999 	}
1000 
1001 	/* determine frame offsets */
1002 	eh_p = (ether_header_t *)buf;
1003 	ip_udp = (ip_udp_header_t *)(void *)(eh_p + 1);
1004 	udp_pseudo = (udp_pseudo_hdr_t *)(void *)
1005 	    (((char *)&ip_udp->udp) - sizeof(*udp_pseudo));
1006 	payload = (char *)(eh_p + 1) + sizeof(*ip_udp);
1007 
1008 	/* ethernet_header */
1009 	bcopy(src, eh_p->ether_shost, ETHER_ADDR_LEN);
1010 	bcopy(dst, eh_p->ether_dhost, ETHER_ADDR_LEN);
1011 	eh_p->ether_type = htons(ETHERTYPE_IP);
1012 
1013 	/* copy the data */
1014 	bcopy(data, payload, data_len);
1015 
1016 	/* fill in UDP pseudo header (gets overwritten by IP header below) */
1017 	bcopy(&src_ip, &udp_pseudo->src_ip, sizeof(src_ip));
1018 	bcopy(&dst_ip, &udp_pseudo->dst_ip, sizeof(dst_ip));
1019 	udp_pseudo->zero = 0;
1020 	udp_pseudo->proto = IPPROTO_UDP;
1021 	udp_pseudo->length = htons(sizeof(ip_udp->udp) + data_len);
1022 
1023 	/* fill in UDP header */
1024 	ip_udp->udp.uh_sport = htons(src_port);
1025 	ip_udp->udp.uh_dport = htons(dst_port);
1026 	ip_udp->udp.uh_ulen = htons(sizeof(ip_udp->udp) + data_len);
1027 	ip_udp->udp.uh_sum = 0;
1028 	ip_udp->udp.uh_sum = in_cksum(udp_pseudo, (int)(sizeof(*udp_pseudo)
1029 	    + sizeof(ip_udp->udp) + data_len));
1030 
1031 	/* fill in IP header */
1032 	bzero(ip_udp, sizeof(ip_udp->ip));
1033 	ip_udp->ip.ip_v = IPVERSION;
1034 	ip_udp->ip.ip_hl = sizeof(struct ip) >> 2;
1035 	ip_udp->ip.ip_ttl = MAXTTL;
1036 	ip_udp->ip.ip_p = IPPROTO_UDP;
1037 	bcopy(&src_ip, &ip_udp->ip.ip_src, sizeof(src_ip));
1038 	bcopy(&dst_ip, &ip_udp->ip.ip_dst, sizeof(dst_ip));
1039 	ip_udp->ip.ip_len = htons(sizeof(*ip_udp) + data_len);
1040 	ip_udp->ip.ip_id = htons(ip_id++);
1041 
1042 	/* compute the IP checksum */
1043 	ip_udp->ip.ip_sum = 0; /* needs to be zero for checksum */
1044 	ip_udp->ip.ip_sum = in_cksum(&ip_udp->ip, sizeof(ip_udp->ip));
1045 
1046 	return frame_length;
1047 }
1048 
1049 static u_int
ethernet_udp6_frame_populate(void * buf,size_t buf_len,const ether_addr_t * src,struct in6_addr * src_ip,uint16_t src_port,const ether_addr_t * dst,struct in6_addr * dst_ip,uint16_t dst_port,const void * data,u_int data_len)1050 ethernet_udp6_frame_populate(void * buf, size_t buf_len,
1051     const ether_addr_t * src,
1052     struct in6_addr *src_ip,
1053     uint16_t src_port,
1054     const ether_addr_t * dst,
1055     struct in6_addr * dst_ip,
1056     uint16_t dst_port,
1057     const void * data, u_int data_len)
1058 {
1059 	ether_header_t *        eh_p;
1060 	u_int                   frame_length;
1061 	ip6_udp_header_t *      ip6_udp;
1062 	char *                  payload;
1063 	udp6_pseudo_hdr_t *     udp6_pseudo;
1064 
1065 	frame_length = (u_int)(sizeof(*eh_p) + sizeof(*ip6_udp)) + data_len;
1066 	if (buf_len < frame_length) {
1067 		return 0;
1068 	}
1069 
1070 	/* determine frame offsets */
1071 	eh_p = (ether_header_t *)buf;
1072 	ip6_udp = (ip6_udp_header_t *)(void *)(eh_p + 1);
1073 	udp6_pseudo = (udp6_pseudo_hdr_t *)(void *)
1074 	    (((char *)&ip6_udp->udp) - sizeof(*udp6_pseudo));
1075 	payload = (char *)(eh_p + 1) + sizeof(*ip6_udp);
1076 
1077 	/* ethernet_header */
1078 	bcopy(src, eh_p->ether_shost, ETHER_ADDR_LEN);
1079 	bcopy(dst, eh_p->ether_dhost, ETHER_ADDR_LEN);
1080 	eh_p->ether_type = htons(ETHERTYPE_IPV6);
1081 
1082 	/* copy the data */
1083 	bcopy(data, payload, data_len);
1084 
1085 	/* fill in UDP pseudo header (gets overwritten by IP header below) */
1086 	bcopy(src_ip, &udp6_pseudo->src_ip, sizeof(*src_ip));
1087 	bcopy(dst_ip, &udp6_pseudo->dst_ip, sizeof(*dst_ip));
1088 	udp6_pseudo->zero = 0;
1089 	udp6_pseudo->proto = IPPROTO_UDP;
1090 	udp6_pseudo->length = htons(sizeof(ip6_udp->udp) + data_len);
1091 
1092 	/* fill in UDP header */
1093 	ip6_udp->udp.uh_sport = htons(src_port);
1094 	ip6_udp->udp.uh_dport = htons(dst_port);
1095 	ip6_udp->udp.uh_ulen = htons(sizeof(ip6_udp->udp) + data_len);
1096 	ip6_udp->udp.uh_sum = 0;
1097 	ip6_udp->udp.uh_sum = in_cksum(udp6_pseudo, (int)(sizeof(*udp6_pseudo)
1098 	    + sizeof(ip6_udp->udp) + data_len));
1099 
1100 	/* fill in IP header */
1101 	bzero(&ip6_udp->ip6, sizeof(ip6_udp->ip6));
1102 	ip6_udp->ip6.ip6_vfc = IPV6_VERSION;
1103 	ip6_udp->ip6.ip6_nxt = IPPROTO_UDP;
1104 	bcopy(src_ip, &ip6_udp->ip6.ip6_src, sizeof(*src_ip));
1105 	bcopy(dst_ip, &ip6_udp->ip6.ip6_dst, sizeof(*dst_ip));
1106 	ip6_udp->ip6.ip6_plen = htons(sizeof(struct udphdr) + data_len);
1107 	/* ip6_udp->ip6.ip6_flow = ? */
1108 	return frame_length;
1109 }
1110 
1111 static u_int
ethernet_udp_frame_populate(void * buf,size_t buf_len,uint8_t af,const ether_addr_t * src,union ifbrip * src_ip,uint16_t src_port,const ether_addr_t * dst,union ifbrip * dst_ip,uint16_t dst_port,const void * data,u_int data_len)1112 ethernet_udp_frame_populate(void * buf, size_t buf_len,
1113     uint8_t af,
1114     const ether_addr_t * src,
1115     union ifbrip * src_ip,
1116     uint16_t src_port,
1117     const ether_addr_t * dst,
1118     union ifbrip * dst_ip,
1119     uint16_t dst_port,
1120     const void * data, u_int data_len)
1121 {
1122 	u_int   len;
1123 
1124 	switch (af) {
1125 	case AF_INET:
1126 		len = ethernet_udp4_frame_populate(buf, buf_len,
1127 		    src,
1128 		    src_ip->ifbrip_addr,
1129 		    src_port,
1130 		    dst,
1131 		    dst_ip->ifbrip_addr,
1132 		    dst_port,
1133 		    data, data_len);
1134 		break;
1135 	case AF_INET6:
1136 		len = ethernet_udp6_frame_populate(buf, buf_len,
1137 		    src,
1138 		    &src_ip->ifbrip_addr6,
1139 		    src_port,
1140 		    dst,
1141 		    &dst_ip->ifbrip_addr6,
1142 		    dst_port,
1143 		    data, data_len);
1144 		break;
1145 	default:
1146 		T_FAIL("unrecognized address family %u", af);
1147 		len = 0;
1148 		break;
1149 	}
1150 	return len;
1151 }
1152 
1153 static u_int
ethernet_arp_frame_populate(void * buf,u_int buf_len,uint16_t op,const ether_addr_t * sender_hw,struct in_addr sender_ip,const ether_addr_t * target_hw,struct in_addr target_ip)1154 ethernet_arp_frame_populate(void * buf, u_int buf_len,
1155     uint16_t op,
1156     const ether_addr_t * sender_hw,
1157     struct in_addr sender_ip,
1158     const ether_addr_t * target_hw,
1159     struct in_addr target_ip)
1160 {
1161 	ether_header_t *        eh_p;
1162 	struct ether_arp *      earp;
1163 	struct arphdr *         arp_p;
1164 	u_int                   frame_length;
1165 
1166 	frame_length = sizeof(*earp) + sizeof(*eh_p);
1167 	T_QUIET;
1168 	T_ASSERT_GE(buf_len, frame_length,
1169 	    "%s buffer size %u needed %u",
1170 	    __func__, buf_len, frame_length);
1171 
1172 	/* ethernet_header */
1173 	eh_p = (ether_header_t *)buf;
1174 	bcopy(sender_hw, eh_p->ether_shost, ETHER_ADDR_LEN);
1175 	if (target_hw != NULL) {
1176 		bcopy(target_hw, eh_p->ether_dhost,
1177 		    sizeof(eh_p->ether_dhost));
1178 	} else {
1179 		bcopy(&ether_broadcast, eh_p->ether_dhost,
1180 		    sizeof(eh_p->ether_dhost));
1181 	}
1182 	eh_p->ether_type = htons(ETHERTYPE_ARP);
1183 
1184 	/* ARP payload */
1185 	earp = (struct ether_arp *)(void *)(eh_p + 1);
1186 	arp_p = &earp->ea_hdr;
1187 	arp_p->ar_hrd = htons(ARPHRD_ETHER);
1188 	arp_p->ar_pro = htons(ETHERTYPE_IP);
1189 	arp_p->ar_hln = sizeof(earp->arp_sha);
1190 	arp_p->ar_pln = sizeof(struct in_addr);
1191 	arp_p->ar_op = htons(op);
1192 	bcopy(sender_hw, earp->arp_sha, sizeof(earp->arp_sha));
1193 	bcopy(&sender_ip, earp->arp_spa, sizeof(earp->arp_spa));
1194 	if (target_hw != NULL) {
1195 		bcopy(target_hw, earp->arp_tha, sizeof(earp->arp_tha));
1196 	} else {
1197 		bzero(earp->arp_tha, sizeof(earp->arp_tha));
1198 	}
1199 	bcopy(&target_ip, earp->arp_tpa, sizeof(earp->arp_tpa));
1200 	return frame_length;
1201 }
1202 
1203 static uint32_t G_generation;
1204 
1205 static uint32_t
next_generation(void)1206 next_generation(void)
1207 {
1208 	return G_generation++;
1209 }
1210 
1211 static const void *
ethernet_frame_get_udp4_payload(void * buf,u_int buf_len,u_int * ret_payload_length)1212 ethernet_frame_get_udp4_payload(void * buf, u_int buf_len,
1213     u_int * ret_payload_length)
1214 {
1215 	ether_header_t *        eh_p;
1216 	uint16_t                ether_type;
1217 	ip_udp_header_t *       ip_udp;
1218 	u_int                   ip_len;
1219 	u_int                   left;
1220 	const void *            payload = NULL;
1221 	u_int                   payload_length = 0;
1222 	u_int                   udp_len;
1223 
1224 	T_QUIET;
1225 	T_ASSERT_GE(buf_len, (u_int)(sizeof(*eh_p) + sizeof(*ip_udp)), NULL);
1226 	left = buf_len;
1227 	eh_p = (ether_header_t *)buf;
1228 	ether_type = ntohs(eh_p->ether_type);
1229 	T_QUIET;
1230 	T_ASSERT_EQ((int)ether_type, ETHERTYPE_IP, NULL);
1231 	ip_udp = (ip_udp_header_t *)(void *)(eh_p + 1);
1232 	left -= sizeof(*eh_p);
1233 	ip_len = ntohs(ip_udp->ip.ip_len);
1234 	T_QUIET;
1235 	T_ASSERT_GE(left, ip_len, NULL);
1236 	T_QUIET;
1237 	T_ASSERT_EQ((int)ip_udp->ip.ip_v, IPVERSION, NULL);
1238 	T_QUIET;
1239 	T_ASSERT_EQ((u_int)ip_udp->ip.ip_hl << 2, (u_int)sizeof(struct ip),
1240 	        NULL);
1241 	T_QUIET;
1242 	T_ASSERT_EQ((int)ip_udp->ip.ip_p, IPPROTO_UDP, NULL);
1243 	T_QUIET;
1244 	T_ASSERT_GE(buf_len, (u_int)sizeof(*ip_udp), NULL);
1245 	udp_len = ntohs(ip_udp->udp.uh_ulen);
1246 	T_QUIET;
1247 	T_ASSERT_GE(udp_len, (u_int)sizeof(ip_udp->udp), NULL);
1248 	payload_length = udp_len - (int)sizeof(ip_udp->udp);
1249 	if (payload_length > 0) {
1250 		payload = (ip_udp + 1);
1251 	}
1252 	if (payload == NULL) {
1253 		payload_length = 0;
1254 	}
1255 	*ret_payload_length = payload_length;
1256 	return payload;
1257 }
1258 
1259 static const void *
ethernet_frame_get_udp6_payload(void * buf,u_int buf_len,u_int * ret_payload_length)1260 ethernet_frame_get_udp6_payload(void * buf, u_int buf_len,
1261     u_int * ret_payload_length)
1262 {
1263 	ether_header_t *        eh_p;
1264 	uint16_t                ether_type;
1265 	ip6_udp_header_t *      ip6_udp;
1266 	u_int                   ip6_len;
1267 	u_int                   left;
1268 	const void *            payload = NULL;
1269 	u_int                   payload_length = 0;
1270 	u_int                   udp_len;
1271 
1272 	T_QUIET;
1273 	T_ASSERT_GE(buf_len, (u_int)(sizeof(*eh_p) + sizeof(*ip6_udp)), NULL);
1274 	left = buf_len;
1275 	eh_p = (ether_header_t *)buf;
1276 	ether_type = ntohs(eh_p->ether_type);
1277 	T_QUIET;
1278 	T_ASSERT_EQ((int)ether_type, ETHERTYPE_IPV6, NULL);
1279 	ip6_udp = (ip6_udp_header_t *)(void *)(eh_p + 1);
1280 	left -= sizeof(*eh_p);
1281 	ip6_len = ntohs(ip6_udp->ip6.ip6_plen);
1282 	T_QUIET;
1283 	T_ASSERT_GE(left, ip6_len + (u_int)sizeof(struct ip6_hdr), NULL);
1284 	T_QUIET;
1285 	T_ASSERT_EQ((int)(ip6_udp->ip6.ip6_vfc & IPV6_VERSION_MASK),
1286 	    IPV6_VERSION, NULL);
1287 	T_QUIET;
1288 	T_ASSERT_EQ((int)ip6_udp->ip6.ip6_nxt, IPPROTO_UDP, NULL);
1289 	T_QUIET;
1290 	T_ASSERT_GE(buf_len, (u_int)sizeof(*ip6_udp), NULL);
1291 	udp_len = ntohs(ip6_udp->udp.uh_ulen);
1292 	T_QUIET;
1293 	T_ASSERT_GE(udp_len, (u_int)sizeof(ip6_udp->udp), NULL);
1294 	payload_length = udp_len - (int)sizeof(ip6_udp->udp);
1295 	if (payload_length > 0) {
1296 		payload = (ip6_udp + 1);
1297 	}
1298 	if (payload == NULL) {
1299 		payload_length = 0;
1300 	}
1301 	*ret_payload_length = payload_length;
1302 	return payload;
1303 }
1304 
1305 static const void *
ethernet_frame_get_udp_payload(uint8_t af,void * buf,u_int buf_len,u_int * ret_payload_length)1306 ethernet_frame_get_udp_payload(uint8_t af, void * buf, u_int buf_len,
1307     u_int * ret_payload_length)
1308 {
1309 	const void *    payload;
1310 
1311 	switch (af) {
1312 	case AF_INET:
1313 		payload = ethernet_frame_get_udp4_payload(buf, buf_len,
1314 		    ret_payload_length);
1315 		break;
1316 	case AF_INET6:
1317 		payload = ethernet_frame_get_udp6_payload(buf, buf_len,
1318 		    ret_payload_length);
1319 		break;
1320 	default:
1321 		T_FAIL("unrecognized address family %u", af);
1322 		payload = NULL;
1323 		break;
1324 	}
1325 	return payload;
1326 }
1327 
1328 #define MIN_ICMP6_LEN           ((u_int)(sizeof(ether_header_t) +       \
1329 	                                 sizeof(struct ip6_hdr) +       \
1330 	                                 sizeof(struct icmp6_hdr)))
1331 #define ALIGNED_ND_OPT_LEN      8
1332 #define SET_ND_OPT_LEN(a)       (u_int)((a) >> 3)
1333 #define GET_ND_OPT_LEN(a)       (u_int)((a) << 3)
1334 #define ALIGN_ND_OPT(a)         (u_int)roundup(a, ALIGNED_ND_OPT_LEN)
1335 #define LINKADDR_OPT_LEN        (ALIGN_ND_OPT(sizeof(struct nd_opt_hdr) + \
1336 	                                      sizeof(ether_addr_t)))
1337 #define ETHER_IPV6_LEN  (sizeof(*eh_p) + sizeof(*ip6))
1338 
1339 
1340 
1341 static u_int
ethernet_nd6_frame_populate(void * buf,u_int buf_len,uint8_t type,const ether_addr_t * sender_hw,struct in6_addr * sender_ip,const ether_addr_t * dest_ether,const ether_addr_t * target_hw,struct in6_addr * target_ip)1342 ethernet_nd6_frame_populate(void * buf, u_int buf_len,
1343     uint8_t type,
1344     const ether_addr_t * sender_hw,
1345     struct in6_addr * sender_ip,
1346     const ether_addr_t * dest_ether,
1347     const ether_addr_t * target_hw,
1348     struct in6_addr * target_ip)
1349 {
1350 	u_int                           data_len = 0;
1351 	ether_header_t *                eh_p;
1352 	u_int                           frame_length;
1353 	struct icmp6_hdr *              icmp6;
1354 	struct ip6_hdr *                ip6;
1355 	struct nd_opt_hdr *             nd_opt;
1356 
1357 	switch (type) {
1358 	case ND_ROUTER_SOLICIT:
1359 	case ND_NEIGHBOR_ADVERT:
1360 	case ND_NEIGHBOR_SOLICIT:
1361 		break;
1362 	default:
1363 		T_FAIL("%s: unsupported type %u", __func__, type);
1364 		return 0;
1365 	}
1366 
1367 	T_QUIET;
1368 	T_ASSERT_GE(buf_len, MIN_ICMP6_LEN, NULL);
1369 
1370 	eh_p = (ether_header_t *)buf;
1371 	ip6 = (struct ip6_hdr *)(void *)(eh_p + 1);
1372 	icmp6 = (struct icmp6_hdr *)(void *)(ip6 + 1);
1373 	frame_length = sizeof(*eh_p) + sizeof(*ip6);
1374 	switch (type) {
1375 	case ND_NEIGHBOR_SOLICIT: {
1376 		struct nd_neighbor_solicit *    nd_ns;
1377 		bool                            sender_is_specified;
1378 
1379 		sender_is_specified = !IN6_IS_ADDR_UNSPECIFIED(sender_ip);
1380 		data_len = sizeof(*nd_ns);
1381 		if (sender_is_specified) {
1382 			data_len += LINKADDR_OPT_LEN;
1383 		}
1384 		frame_length += data_len;
1385 		T_QUIET;
1386 		T_ASSERT_GE(buf_len, frame_length, NULL);
1387 		nd_ns = (struct nd_neighbor_solicit *)(void *)icmp6;
1388 		if (sender_is_specified) {
1389 			/* add the source lladdr option */
1390 			nd_opt = (struct nd_opt_hdr *)(nd_ns + 1);
1391 			nd_opt->nd_opt_type = ND_OPT_SOURCE_LINKADDR;
1392 			nd_opt->nd_opt_len = SET_ND_OPT_LEN(LINKADDR_OPT_LEN);
1393 			bcopy(sender_hw, (nd_opt + 1), sizeof(*sender_hw));
1394 		}
1395 		bcopy(target_ip, &nd_ns->nd_ns_target,
1396 		    sizeof(nd_ns->nd_ns_target));
1397 		break;
1398 	}
1399 	case ND_NEIGHBOR_ADVERT: {
1400 		struct nd_neighbor_advert *     nd_na;
1401 
1402 		data_len = sizeof(*nd_na) + LINKADDR_OPT_LEN;
1403 		frame_length += data_len;
1404 		T_QUIET;
1405 		T_ASSERT_GE(buf_len, frame_length, NULL);
1406 
1407 		nd_na = (struct nd_neighbor_advert *)(void *)icmp6;
1408 		bcopy(target_ip, &nd_na->nd_na_target,
1409 		    sizeof(nd_na->nd_na_target));
1410 		/* add the target lladdr option */
1411 		nd_opt = (struct nd_opt_hdr *)(nd_na + 1);
1412 		nd_opt->nd_opt_type = ND_OPT_TARGET_LINKADDR;
1413 		nd_opt->nd_opt_len = SET_ND_OPT_LEN(LINKADDR_OPT_LEN);
1414 		bcopy(target_hw, (nd_opt + 1), sizeof(*target_hw));
1415 		break;
1416 	}
1417 	case ND_ROUTER_SOLICIT: {
1418 		struct nd_router_solicit *      nd_rs;
1419 
1420 		data_len = sizeof(*nd_rs) + LINKADDR_OPT_LEN;
1421 		frame_length += data_len;
1422 		T_QUIET;
1423 		T_ASSERT_GE(buf_len, frame_length, NULL);
1424 
1425 		nd_rs = (struct nd_router_solicit *)(void *)icmp6;
1426 
1427 		/* add the source lladdr option */
1428 		nd_opt = (struct nd_opt_hdr *)(nd_rs + 1);
1429 		nd_opt->nd_opt_type = ND_OPT_SOURCE_LINKADDR;
1430 		nd_opt->nd_opt_len = SET_ND_OPT_LEN(LINKADDR_OPT_LEN);
1431 		bcopy(sender_hw, (nd_opt + 1), sizeof(*sender_hw));
1432 		break;
1433 	}
1434 	default:
1435 		T_FAIL("%s: unsupported type %u", __func__, type);
1436 		return 0;
1437 	}
1438 	/* icmp6 header */
1439 	icmp6->icmp6_type = type;
1440 	icmp6->icmp6_code = 0;
1441 	icmp6->icmp6_cksum = 0;
1442 	icmp6->icmp6_data32[0] = 0;
1443 
1444 	/* ethernet_header */
1445 	bcopy(sender_hw, eh_p->ether_shost, ETHER_ADDR_LEN);
1446 	if (dest_ether != NULL) {
1447 		bcopy(dest_ether, eh_p->ether_dhost,
1448 		    sizeof(eh_p->ether_dhost));
1449 	} else {
1450 		/* XXX ether_dhost should be multicast */
1451 		bcopy(&ether_broadcast, eh_p->ether_dhost,
1452 		    sizeof(eh_p->ether_dhost));
1453 	}
1454 	eh_p->ether_type = htons(ETHERTYPE_IPV6);
1455 
1456 	/* IPv6 header */
1457 	bzero(ip6, sizeof(*ip6));
1458 	ip6->ip6_nxt = IPPROTO_ICMPV6;
1459 	ip6->ip6_vfc = IPV6_VERSION;
1460 	bcopy(sender_ip, &ip6->ip6_src, sizeof(ip6->ip6_src));
1461 	/* XXX ip6_dst should be specific multicast */
1462 	bcopy(&in6addr_linklocal_allnodes, &ip6->ip6_dst, sizeof(ip6->ip6_dst));
1463 	ip6->ip6_plen = htons(data_len);
1464 
1465 	return frame_length;
1466 }
1467 
1468 /**
1469 ** Switch port
1470 **/
1471 static void
switch_port_check_tx(switch_port_t port)1472 switch_port_check_tx(switch_port_t port)
1473 {
1474 	int             error;
1475 	struct kevent   kev;
1476 	int             kq;
1477 	struct timespec ts = { .tv_sec = 0, .tv_nsec = 1000 * 1000};
1478 
1479 	kq = kqueue();
1480 	T_QUIET;
1481 	T_ASSERT_POSIX_SUCCESS(kq, "kqueue check_tx");
1482 	EV_SET(&kev, port->fd, EVFILT_WRITE, EV_ADD | EV_ENABLE, 0, 0, NULL);
1483 	error = kevent(kq, &kev, 1, &kev, 1, &ts);
1484 	T_QUIET;
1485 	T_ASSERT_EQ(error, 1, "kevent");
1486 	T_QUIET;
1487 	T_ASSERT_EQ((int)kev.filter, EVFILT_WRITE, NULL);
1488 	T_QUIET;
1489 	T_ASSERT_EQ((int)kev.ident, port->fd, NULL);
1490 	T_QUIET;
1491 	T_ASSERT_NULL(kev.udata, NULL);
1492 	close(kq);
1493 	return;
1494 }
1495 
1496 static void
switch_port_send_arp(switch_port_t port,uint16_t op,const ether_addr_t * sender_hw,struct in_addr sender_ip,const ether_addr_t * target_hw,struct in_addr target_ip)1497 switch_port_send_arp(switch_port_t port,
1498     uint16_t op,
1499     const ether_addr_t * sender_hw,
1500     struct in_addr sender_ip,
1501     const ether_addr_t * target_hw,
1502     struct in_addr target_ip)
1503 {
1504 	u_int           frame_length;
1505 	ether_packet    pkt;
1506 	ssize_t         n;
1507 
1508 	/* make sure we can send */
1509 	switch_port_check_tx(port);
1510 	frame_length = ethernet_arp_frame_populate(&pkt, sizeof(pkt),
1511 	    op,
1512 	    sender_hw,
1513 	    sender_ip,
1514 	    target_hw,
1515 	    target_ip);
1516 	T_QUIET;
1517 	T_ASSERT_GT(frame_length, 0, "%s: frame_length %u",
1518 	    __func__, frame_length);
1519 	if (S_debug) {
1520 		T_LOG("Port %s -> %s transmitting %u bytes",
1521 		    port->ifname, port->member_ifname, frame_length);
1522 	}
1523 	ethernet_frame_validate(&pkt, frame_length, S_debug);
1524 	n = write(port->fd, &pkt, frame_length);
1525 	if (n < 0) {
1526 		T_ASSERT_POSIX_SUCCESS(n, "%s write fd %d failed %ld",
1527 		    port->ifname, port->fd, n);
1528 	}
1529 	T_QUIET;
1530 	T_ASSERT_EQ((u_int)n, frame_length,
1531 	    "%s fd %d wrote %ld",
1532 	    port->ifname, port->fd, n);
1533 }
1534 
1535 
1536 static void
switch_port_send_nd6(switch_port_t port,uint8_t type,const ether_addr_t * sender_hw,struct in6_addr * sender_ip,const ether_addr_t * dest_ether,const ether_addr_t * target_hw,struct in6_addr * target_ip)1537 switch_port_send_nd6(switch_port_t port,
1538     uint8_t type,
1539     const ether_addr_t * sender_hw,
1540     struct in6_addr * sender_ip,
1541     const ether_addr_t * dest_ether,
1542     const ether_addr_t * target_hw,
1543     struct in6_addr * target_ip)
1544 {
1545 	u_int           frame_length;
1546 	ether_packet    pkt;
1547 	ssize_t         n;
1548 
1549 	/* make sure we can send */
1550 	switch_port_check_tx(port);
1551 	frame_length = ethernet_nd6_frame_populate(&pkt, sizeof(pkt),
1552 	    type,
1553 	    sender_hw,
1554 	    sender_ip,
1555 	    dest_ether,
1556 	    target_hw,
1557 	    target_ip);
1558 	T_QUIET;
1559 	T_ASSERT_GT(frame_length, 0, "%s: frame_length %u",
1560 	    __func__, frame_length);
1561 	if (S_debug) {
1562 		T_LOG("Port %s -> %s transmitting %u bytes",
1563 		    port->ifname, port->member_ifname, frame_length);
1564 	}
1565 	ethernet_frame_validate(&pkt, frame_length, S_debug);
1566 	n = write(port->fd, &pkt, frame_length);
1567 	if (n < 0) {
1568 		T_ASSERT_POSIX_SUCCESS(n, "%s write fd %d failed %ld",
1569 		    port->ifname, port->fd, n);
1570 	}
1571 	T_QUIET;
1572 	T_ASSERT_EQ((u_int)n, frame_length,
1573 	    "%s fd %d wrote %ld",
1574 	    port->ifname, port->fd, n);
1575 }
1576 
1577 
1578 static void
switch_port_send_udp(switch_port_t port,uint8_t af,const ether_addr_t * src_eaddr,union ifbrip * src_ip,uint16_t src_port,const ether_addr_t * dst_eaddr,union ifbrip * dst_ip,uint16_t dst_port,const void * payload,u_int payload_length)1579 switch_port_send_udp(switch_port_t port,
1580     uint8_t af,
1581     const ether_addr_t * src_eaddr,
1582     union ifbrip * src_ip,
1583     uint16_t src_port,
1584     const ether_addr_t * dst_eaddr,
1585     union ifbrip * dst_ip,
1586     uint16_t dst_port,
1587     const void * payload, u_int payload_length)
1588 {
1589 	u_int                   frame_length;
1590 	ether_packet            pkt;
1591 	ssize_t                 n;
1592 
1593 	/* make sure we can send */
1594 	switch_port_check_tx(port);
1595 
1596 	/* generate the packet */
1597 	frame_length
1598 	        = ethernet_udp_frame_populate((void *)&pkt,
1599 	    (u_int)sizeof(pkt),
1600 	    af,
1601 	    src_eaddr,
1602 	    src_ip,
1603 	    src_port,
1604 	    dst_eaddr,
1605 	    dst_ip,
1606 	    dst_port,
1607 	    payload,
1608 	    payload_length);
1609 	T_QUIET;
1610 	T_ASSERT_GT(frame_length, 0, NULL);
1611 	if (S_debug) {
1612 		T_LOG("Port %s transmitting %u bytes",
1613 		    port->ifname, frame_length);
1614 	}
1615 	ethernet_frame_validate(&pkt, frame_length, S_debug);
1616 	n = write(port->fd, &pkt, frame_length);
1617 	if (n < 0) {
1618 		T_ASSERT_POSIX_SUCCESS(n, "%s write fd %d failed %ld",
1619 		    port->ifname, port->fd, n);
1620 	}
1621 	T_QUIET;
1622 	T_ASSERT_EQ((u_int)n, frame_length,
1623 	    "%s fd %d wrote %ld",
1624 	    port->ifname, port->fd, n);
1625 }
1626 
1627 
1628 
1629 static void
switch_port_send_udp_addr_index(switch_port_t port,uint8_t af,u_int addr_index,const ether_addr_t * dst_eaddr,union ifbrip * dst_ip,const void * payload,u_int payload_length)1630 switch_port_send_udp_addr_index(switch_port_t port,
1631     uint8_t af,
1632     u_int addr_index,
1633     const ether_addr_t * dst_eaddr,
1634     union ifbrip * dst_ip,
1635     const void * payload, u_int payload_length)
1636 {
1637 	ether_addr_t    eaddr;
1638 	union ifbrip    ip;
1639 
1640 	/* generate traffic for the unit and address */
1641 	set_ethernet_address(&eaddr, port->unit, addr_index);
1642 	get_ip_address(af, port->unit, addr_index, &ip);
1643 	switch_port_send_udp(port, af,
1644 	    &eaddr, &ip, TEST_SOURCE_PORT,
1645 	    dst_eaddr, dst_ip, TEST_DEST_PORT,
1646 	    payload, payload_length);
1647 }
1648 
1649 typedef void
1650 (packet_validator)(switch_port_t port, const ether_header_t * eh_p,
1651     u_int pkt_len, void * context);
1652 typedef packet_validator * packet_validator_t;
1653 
1654 static void
switch_port_receive(switch_port_t port,uint8_t af,const void * payload,u_int payload_length,packet_validator_t validator,void * context)1655 switch_port_receive(switch_port_t port,
1656     uint8_t af,
1657     const void * payload, u_int payload_length,
1658     packet_validator_t validator,
1659     void * context)
1660 {
1661 	ether_header_t *        eh_p;
1662 	ssize_t                 n;
1663 	char *                  offset;
1664 
1665 	n = read(port->fd, port->rx_buf, (unsigned)port->rx_buf_size);
1666 	if (n < 0) {
1667 		if (errno == EAGAIN) {
1668 			return;
1669 		}
1670 		T_QUIET;
1671 		T_ASSERT_POSIX_SUCCESS(n, "read %s port %d fd %d",
1672 		    port->ifname, port->unit, port->fd);
1673 		return;
1674 	}
1675 	for (offset = port->rx_buf; n > 0;) {
1676 		struct bpf_hdr *        bpf = (struct bpf_hdr *)(void *)offset;
1677 		u_int                   pkt_len;
1678 		char *                  pkt;
1679 		u_int                   skip;
1680 
1681 		pkt = offset + bpf->bh_hdrlen;
1682 		pkt_len = bpf->bh_caplen;
1683 
1684 		eh_p = (ether_header_t *)(void *)pkt;
1685 		T_QUIET;
1686 		T_ASSERT_GE(pkt_len, (u_int)sizeof(*eh_p),
1687 		    "short packet %ld", n);
1688 
1689 		/* source shouldn't be broadcast/multicast */
1690 		T_QUIET;
1691 		T_ASSERT_EQ(eh_p->ether_shost[0] & 0x01, 0,
1692 		    "broadcast/multicast source");
1693 
1694 		if (S_debug) {
1695 			T_LOG("Port %s [unit %d] [fd %d] Received %u bytes",
1696 			    port->ifname, port->unit, port->fd, pkt_len);
1697 		}
1698 		ethernet_frame_validate(pkt, pkt_len, S_debug);
1699 
1700 		/* call the validation function */
1701 		(*validator)(port, eh_p, pkt_len, context);
1702 
1703 		if (payload != NULL) {
1704 			const void *    p;
1705 			u_int           p_len;
1706 
1707 			p = ethernet_frame_get_udp_payload(af, pkt, pkt_len,
1708 			    &p_len);
1709 			T_QUIET;
1710 			T_ASSERT_NOTNULL(p, "ethernet_frame_get_udp_payload");
1711 			T_QUIET;
1712 			T_ASSERT_EQ(p_len, payload_length,
1713 			    "payload length %u < expected %u",
1714 			    p_len, payload_length);
1715 			T_QUIET;
1716 			T_ASSERT_EQ(bcmp(payload, p, payload_length), 0,
1717 			    "unexpected payload");
1718 		}
1719 		skip = BPF_WORDALIGN(pkt_len + bpf->bh_hdrlen);
1720 		if (skip == 0) {
1721 			break;
1722 		}
1723 		offset += skip;
1724 		n -= skip;
1725 	}
1726 	return;
1727 }
1728 
1729 static void
switch_port_log(switch_port_t port)1730 switch_port_log(switch_port_t port)
1731 {
1732 	T_LOG("%s [unit %d] [member %s]%s bpf fd %d bufsize %d\n",
1733 	    port->ifname, port->unit,
1734 	    port->member_ifname,
1735 	    port->mac_nat ? " [mac-nat]" : "",
1736 	    port->fd, port->rx_buf_size);
1737 }
1738 
1739 #define switch_port_list_size(port_count)               \
1740 	offsetof(switch_port_list, list[port_count])
1741 
1742 static switch_port_list_t
switch_port_list_alloc(u_int port_count,bool mac_nat)1743 switch_port_list_alloc(u_int port_count, bool mac_nat)
1744 {
1745 	switch_port_list_t      list;
1746 
1747 	list = (switch_port_list_t)
1748 	    calloc(1, switch_port_list_size(port_count));;
1749 	list->size = port_count;
1750 	list->mac_nat = mac_nat;
1751 	return list;
1752 }
1753 
1754 static void
switch_port_list_dealloc(switch_port_list_t list)1755 switch_port_list_dealloc(switch_port_list_t list)
1756 {
1757 	u_int           i;
1758 	switch_port_t   port;
1759 
1760 	for (i = 0, port = list->list; i < list->count; i++, port++) {
1761 		close(port->fd);
1762 		free(port->rx_buf);
1763 	}
1764 	free(list);
1765 	return;
1766 }
1767 
1768 static errno_t
switch_port_list_add_port(int s,switch_port_list_t port_list,u_int unit,const char * ifname,u_short if_index,const char * member_ifname,u_int num_addrs,bool mac_nat,struct in_addr * ip)1769 switch_port_list_add_port(int s, switch_port_list_t port_list, u_int unit,
1770     const char * ifname, u_short if_index, const char * member_ifname,
1771     u_int num_addrs, bool mac_nat, struct in_addr * ip)
1772 {
1773 	int             buf_size;
1774 	errno_t         err = EINVAL;
1775 	int             fd = -1;
1776 	char            ntopbuf_ip[INET6_ADDRSTRLEN];
1777 	int             opt;
1778 	switch_port_t   p;
1779 
1780 	if (port_list->count >= port_list->size) {
1781 		T_LOG("Internal error: port_list count %u >= size %u\n",
1782 		    port_list->count, port_list->size);
1783 		goto failed;
1784 	}
1785 	fd = bpf_new();
1786 	if (fd < 0) {
1787 		err = errno;
1788 		T_LOG("bpf_new");
1789 		goto failed;
1790 	}
1791 	opt = 1;
1792 	T_QUIET;
1793 	T_ASSERT_POSIX_SUCCESS(ioctl(fd, FIONBIO, &opt), NULL);
1794 	T_QUIET;
1795 	T_ASSERT_POSIX_SUCCESS(bpf_set_immediate(fd, 1), NULL);
1796 	T_QUIET;
1797 	T_ASSERT_POSIX_SUCCESS(bpf_setif(fd, ifname), "bpf set if %s",
1798 	    ifname);
1799 	T_QUIET;
1800 	T_ASSERT_POSIX_SUCCESS(bpf_set_see_sent(fd, 0), NULL);
1801 	T_QUIET;
1802 	T_ASSERT_POSIX_SUCCESS(bpf_set_header_complete(fd, 1), NULL);
1803 	T_QUIET;
1804 	T_ASSERT_POSIX_SUCCESS(bpf_get_blen(fd, &buf_size), NULL);
1805 	if (S_debug) {
1806 		T_LOG("%s [unit %d] [member %s] bpf fd %d bufsize %d\n",
1807 		    ifname, unit,
1808 		    member_ifname, fd, buf_size);
1809 	}
1810 	p = port_list->list + port_list->count++;
1811 	p->fd = fd;
1812 	p->unit = unit;
1813 	strlcpy(p->ifname, ifname, sizeof(p->ifname));
1814 	strlcpy(p->member_ifname, member_ifname, sizeof(p->member_ifname));
1815 	p->num_addrs = num_addrs;
1816 	p->rx_buf_size = buf_size;
1817 	p->rx_buf = malloc((unsigned)buf_size);
1818 	p->mac_nat = mac_nat;
1819 	ifnet_get_lladdr(s, ifname, &p->mac);
1820 	ifnet_get_lladdr(s, member_ifname, &p->member_mac);
1821 	p->ip = *ip;
1822 	p->if_index = if_index;
1823 	get_ipv6_ll_address(&p->mac, &p->ip6);
1824 	inet_ntop(AF_INET6, &p->ip6, ntopbuf_ip, sizeof(ntopbuf_ip));
1825 	T_LOG("%s %s", ifname, ntopbuf_ip);
1826 	return 0;
1827 
1828 failed:
1829 	if (fd >= 0) {
1830 		close(fd);
1831 	}
1832 	return err;
1833 }
1834 
1835 static switch_port_t
switch_port_list_find_fd(switch_port_list_t ports,int fd)1836 switch_port_list_find_fd(switch_port_list_t ports, int fd)
1837 {
1838 	u_int           i;
1839 	switch_port_t   port;
1840 
1841 	for (i = 0, port = ports->list; i < ports->count; i++, port++) {
1842 		if (port->fd == fd) {
1843 			return port;
1844 		}
1845 	}
1846 	return NULL;
1847 }
1848 
1849 static void
switch_port_list_log(switch_port_list_t port_list)1850 switch_port_list_log(switch_port_list_t port_list)
1851 {
1852 	u_int           i;
1853 	switch_port_t   port;
1854 
1855 	for (i = 0, port = port_list->list; i < port_list->count; i++, port++) {
1856 		switch_port_log(port);
1857 	}
1858 	return;
1859 }
1860 
1861 static switch_port_t
switch_port_list_find_member(switch_port_list_t ports,const char * member_ifname)1862 switch_port_list_find_member(switch_port_list_t ports, const char * member_ifname)
1863 {
1864 	u_int           i;
1865 	switch_port_t   port;
1866 
1867 	for (i = 0, port = ports->list; i < ports->count; i++, port++) {
1868 		if (strcmp(port->member_ifname, member_ifname) == 0) {
1869 			return port;
1870 		}
1871 	}
1872 	return NULL;
1873 }
1874 
1875 static void
switch_port_list_check_receive(switch_port_list_t ports,uint8_t af,const void * payload,u_int payload_length,packet_validator_t validator,void * context)1876 switch_port_list_check_receive(switch_port_list_t ports, uint8_t af,
1877     const void * payload, u_int payload_length,
1878     packet_validator_t validator,
1879     void * context)
1880 {
1881 	int             i;
1882 	int             n_events;
1883 	struct kevent   kev[ports->count];
1884 	int             kq;
1885 	switch_port_t   port;
1886 	struct timespec ts = { .tv_sec = 0, .tv_nsec = 10 * 1000 * 1000};
1887 	u_int           u;
1888 
1889 	kq = kqueue();
1890 	T_QUIET;
1891 	T_ASSERT_POSIX_SUCCESS(kq, "kqueue check_receive");
1892 	for (u = 0, port = ports->list; u < ports->count; u++, port++) {
1893 		port->test_count = 0;
1894 		EV_SET(kev + u, port->fd,
1895 		    EVFILT_READ, EV_ADD | EV_ENABLE, 0, 0, NULL);
1896 	}
1897 
1898 	do {
1899 		n_events = kevent(kq, kev, (int)ports->count, kev,
1900 		    (int)ports->count, &ts);
1901 		T_QUIET;
1902 		T_ASSERT_POSIX_SUCCESS(n_events, "kevent receive %d", n_events);
1903 		for (i = 0; i < n_events; i++) {
1904 			T_QUIET;
1905 			T_ASSERT_EQ((int)kev[i].filter, EVFILT_READ, NULL);
1906 			T_QUIET;
1907 			T_ASSERT_NULL(kev[i].udata, NULL);
1908 			port = switch_port_list_find_fd(ports,
1909 			    (int)kev[i].ident);
1910 			T_QUIET;
1911 			T_ASSERT_NE(port, NULL,
1912 			    "port %p fd %d", (void *)port,
1913 			    (int)kev[i].ident);
1914 			switch_port_receive(port, af, payload, payload_length,
1915 			    validator, context);
1916 		}
1917 	} while (n_events != 0);
1918 	close(kq);
1919 }
1920 
1921 static bool
switch_port_list_verify_rt_table(switch_port_list_t port_list,bool log)1922 switch_port_list_verify_rt_table(switch_port_list_t port_list, bool log)
1923 {
1924 	bool            all_present = true;
1925 	u_int           i;
1926 	u_int           count;
1927 	struct ifbareq *ifba;
1928 	struct ifbareq *rt_table;
1929 	switch_port_t   port;
1930 
1931 	/* clear out current notion of how many addresses are present */
1932 	for (i = 0, port = port_list->list; i < port_list->count; i++, port++) {
1933 		port->test_address_count = 0;
1934 		port->test_address_present = 0;
1935 	}
1936 	rt_table = bridge_rt_table_copy(&count);
1937 	if (rt_table == NULL) {
1938 		return false;
1939 	}
1940 	if (log) {
1941 		bridge_rt_table_log(rt_table, count);
1942 	}
1943 	for (i = 0, ifba = rt_table; i < count; i++, ifba++) {
1944 		uint64_t        addr_bit;
1945 		u_int           addr_index;
1946 		u_int           unit_index;
1947 		u_char *        ea;
1948 		ether_addr_t *  eaddr;
1949 
1950 		eaddr = (ether_addr_t *)&ifba->ifba_dst;
1951 		ea = eaddr->octet;
1952 		addr_index = ea[EA_ADDR_INDEX];
1953 		unit_index = ea[EA_UNIT_INDEX];
1954 		port = switch_port_list_find_member(port_list,
1955 		    ifba->ifba_ifsname);
1956 		T_QUIET;
1957 		T_ASSERT_NOTNULL(port, "switch_port_list_find_member %s",
1958 		    ifba->ifba_ifsname);
1959 		if (!S_cleaning_up) {
1960 			T_QUIET;
1961 			T_ASSERT_EQ(unit_index, port->unit, NULL);
1962 			addr_bit = 1 << addr_index;
1963 			T_QUIET;
1964 			T_ASSERT_BITS_NOTSET(port->test_address_present,
1965 			    addr_bit, "%s address %u",
1966 			    ifba->ifba_ifsname, addr_index);
1967 			port->test_address_present |= addr_bit;
1968 			port->test_address_count++;
1969 		}
1970 	}
1971 	for (i = 0, port = port_list->list; i < port_list->count; i++, port++) {
1972 		if (S_debug) {
1973 			T_LOG("%s unit %d [member %s] %u expect %u",
1974 			    port->ifname, port->unit, port->member_ifname,
1975 			    port->test_address_count, port->num_addrs);
1976 		}
1977 		if (port->test_address_count != port->num_addrs) {
1978 			all_present = false;
1979 		}
1980 	}
1981 
1982 	free(rt_table);
1983 	return all_present;
1984 }
1985 
1986 static bool
switch_port_list_verify_mac_nat(switch_port_list_t port_list,bool log)1987 switch_port_list_verify_mac_nat(switch_port_list_t port_list, bool log)
1988 {
1989 	bool                    all_present = true;
1990 	u_int                   i;
1991 	u_int                   count;
1992 	static struct ifbrmne * entries;
1993 	switch_port_t           port;
1994 	struct ifbrmne *        scan;
1995 
1996 
1997 	/* clear out current notion of how many addresses are present */
1998 	for (i = 0, port = port_list->list; i < port_list->count; i++, port++) {
1999 		port->test_address_count = 0;
2000 		port->test_address_present = 0;
2001 	}
2002 	entries = bridge_mac_nat_entries_copy(&count);
2003 	if (entries == NULL) {
2004 		return false;
2005 	}
2006 	if (log) {
2007 		bridge_mac_nat_entries_log(entries, count);
2008 	}
2009 	for (i = 0, scan = entries; i < count; i++, scan++) {
2010 		uint8_t         af;
2011 		uint64_t        addr_bit;
2012 		u_int           addr_index;
2013 		char            buf_ip1[INET6_ADDRSTRLEN];
2014 		char            buf_ip2[INET6_ADDRSTRLEN];
2015 		u_char *        ea;
2016 		ether_addr_t *  eaddr;
2017 		union ifbrip    ip;
2018 		u_int           unit_index;
2019 
2020 		eaddr = (ether_addr_t *)&scan->ifbmne_mac;
2021 		ea = eaddr->octet;
2022 		addr_index = ea[EA_ADDR_INDEX];
2023 		unit_index = ea[EA_UNIT_INDEX];
2024 		port = switch_port_list_find_member(port_list,
2025 		    scan->ifbmne_ifname);
2026 		T_QUIET;
2027 		T_ASSERT_NOTNULL(port,
2028 		    "switch_port_list_find_member %s",
2029 		    scan->ifbmne_ifname);
2030 		T_QUIET;
2031 		T_ASSERT_EQ(unit_index, port->unit, NULL);
2032 		af = scan->ifbmne_af;
2033 		get_ip_address(af, port->unit, addr_index, &ip);
2034 		addr_bit = 1 << addr_index;
2035 		T_QUIET;
2036 		T_ASSERT_TRUE(ip_addresses_are_equal(af, &ip, &scan->ifbmne_ip),
2037 		    "mac nat entry IP address %s expected %s",
2038 		    inet_ntop(af, &scan->ifbmne_ip_addr,
2039 		    buf_ip1, sizeof(buf_ip1)),
2040 		    inet_ntop(af, &ip,
2041 		    buf_ip2, sizeof(buf_ip2)));
2042 		T_QUIET;
2043 		T_ASSERT_BITS_NOTSET(port->test_address_present,
2044 		    addr_bit, "%s address %u",
2045 		    scan->ifbmne_ifname, addr_index);
2046 		port->test_address_present |= addr_bit;
2047 		port->test_address_count++;
2048 	}
2049 	for (i = 0, port = port_list->list; i < port_list->count; i++, port++) {
2050 		if (port->mac_nat) {
2051 			/* MAC-NAT interface should have no entries */
2052 			T_QUIET;
2053 			T_ASSERT_EQ(port->test_address_count, 0,
2054 			    "mac nat interface %s has %u entries",
2055 			    port->member_ifname,
2056 			    port->test_address_count);
2057 		} else {
2058 			if (S_debug) {
2059 				T_LOG("%s unit %d [member %s] %u expect %u",
2060 				    port->ifname, port->unit,
2061 				    port->member_ifname,
2062 				    port->test_address_count, port->num_addrs);
2063 			}
2064 			if (port->test_address_count != port->num_addrs) {
2065 				all_present = false;
2066 			}
2067 		}
2068 	}
2069 
2070 	free(entries);
2071 
2072 	return all_present;
2073 }
2074 
2075 /**
2076 ** Basic Bridge Tests
2077 **/
2078 static void
send_generation(switch_port_t port,uint8_t af,u_int addr_index,const ether_addr_t * dst_eaddr,union ifbrip * dst_ip,uint32_t generation)2079 send_generation(switch_port_t port, uint8_t af, u_int addr_index,
2080     const ether_addr_t * dst_eaddr, union ifbrip * dst_ip,
2081     uint32_t generation)
2082 {
2083 	uint32_t        payload;
2084 
2085 	payload = htonl(generation);
2086 	switch_port_send_udp_addr_index(port, af, addr_index, dst_eaddr, dst_ip,
2087 	    &payload, sizeof(payload));
2088 }
2089 
2090 static void
check_receive_generation(switch_port_list_t ports,uint8_t af,uint32_t generation,packet_validator_t validator,__unused void * context)2091 check_receive_generation(switch_port_list_t ports, uint8_t af,
2092     uint32_t generation, packet_validator_t validator,
2093     __unused void * context)
2094 {
2095 	uint32_t        payload;
2096 
2097 	payload = htonl(generation);
2098 	switch_port_list_check_receive(ports, af, &payload, sizeof(payload),
2099 	    validator, context);
2100 }
2101 
2102 static void
validate_source_ether_mismatch(switch_port_t port,const ether_header_t * eh_p)2103 validate_source_ether_mismatch(switch_port_t port, const ether_header_t * eh_p)
2104 {
2105 	/* source shouldn't be our own MAC addresses */
2106 	T_QUIET;
2107 	T_ASSERT_NE(eh_p->ether_shost[EA_UNIT_INDEX], port->unit,
2108 	    "ether source matches unit %d", port->unit);
2109 }
2110 
2111 static void
validate_not_present_dhost(switch_port_t port,const ether_header_t * eh_p,__unused u_int pkt_len,__unused void * context)2112 validate_not_present_dhost(switch_port_t port, const ether_header_t * eh_p,
2113     __unused u_int pkt_len,
2114     __unused void * context)
2115 {
2116 	validate_source_ether_mismatch(port, eh_p);
2117 	T_QUIET;
2118 	T_ASSERT_EQ(bcmp(eh_p->ether_dhost, &ether_external,
2119 	    sizeof(eh_p->ether_dhost)), 0,
2120 	    "%s", __func__);
2121 	port->test_count++;
2122 }
2123 
2124 static void
validate_broadcast_dhost(switch_port_t port,const ether_header_t * eh_p,__unused u_int pkt_len,__unused void * context)2125 validate_broadcast_dhost(switch_port_t port, const ether_header_t * eh_p,
2126     __unused u_int pkt_len,
2127     __unused void * context)
2128 {
2129 	validate_source_ether_mismatch(port, eh_p);
2130 	T_QUIET;
2131 	T_ASSERT_NE((eh_p->ether_dhost[0] & 0x01), 0,
2132 	    "%s", __func__);
2133 	port->test_count++;
2134 }
2135 
2136 static void
validate_port_dhost(switch_port_t port,const ether_header_t * eh_p,__unused u_int pkt_len,__unused void * context)2137 validate_port_dhost(switch_port_t port, const ether_header_t * eh_p,
2138     __unused u_int pkt_len,
2139     __unused void * context)
2140 {
2141 	validate_source_ether_mismatch(port, eh_p);
2142 	T_QUIET;
2143 	T_ASSERT_EQ(eh_p->ether_dhost[EA_UNIT_INDEX], port->unit,
2144 	    "wrong dhost unit %d != %d",
2145 	    eh_p->ether_dhost[EA_UNIT_INDEX], port->unit);
2146 	port->test_count++;
2147 }
2148 
2149 
2150 static void
check_received_count(switch_port_list_t port_list,switch_port_t port,uint32_t expected_packets)2151 check_received_count(switch_port_list_t port_list,
2152     switch_port_t port, uint32_t expected_packets)
2153 {
2154 	u_int           i;
2155 	switch_port_t   scan;
2156 
2157 	for (i = 0, scan = port_list->list; i < port_list->count; i++, scan++) {
2158 		if (scan == port) {
2159 			T_QUIET;
2160 			T_ASSERT_EQ(port->test_count, 0,
2161 			    "unexpected receive on port %d",
2162 			    port->unit);
2163 		} else if (expected_packets == ALL_ADDRS) {
2164 			T_QUIET;
2165 			T_ASSERT_EQ(scan->test_count, scan->num_addrs,
2166 			    "didn't receive on all addrs");
2167 		} else {
2168 			T_QUIET;
2169 			T_ASSERT_EQ(scan->test_count, expected_packets,
2170 			    "wrong receive count on port %s", scan->member_ifname);
2171 		}
2172 	}
2173 }
2174 
2175 static void
unicast_send_all(switch_port_list_t port_list,uint8_t af,switch_port_t port)2176 unicast_send_all(switch_port_list_t port_list, uint8_t af, switch_port_t port)
2177 {
2178 	u_int           i;
2179 	switch_port_t   scan;
2180 
2181 	for (i = 0, scan = port_list->list; i < port_list->count; i++, scan++) {
2182 		if (S_debug) {
2183 			T_LOG("Unicast send on %s", port->ifname);
2184 		}
2185 		for (u_int j = 0; j < scan->num_addrs; j++) {
2186 			ether_addr_t    eaddr;
2187 			union ifbrip    ip;
2188 
2189 			set_ethernet_address(&eaddr, scan->unit, j);
2190 			get_ip_address(af, scan->unit, j, &ip);
2191 			switch_port_send_udp_addr_index(port, af, 0, &eaddr, &ip,
2192 			    NULL, 0);
2193 		}
2194 	}
2195 }
2196 
2197 
2198 static void
bridge_learning_test_once(switch_port_list_t port_list,uint8_t af,packet_validator_t validator,void * context,const ether_addr_t * dst_eaddr,bool retry)2199 bridge_learning_test_once(switch_port_list_t port_list,
2200     uint8_t af,
2201     packet_validator_t validator,
2202     void * context,
2203     const ether_addr_t * dst_eaddr,
2204     bool retry)
2205 {
2206 	u_int           i;
2207 	union ifbrip    dst_ip;
2208 	switch_port_t   port;
2209 
2210 	get_broadcast_ip_address(af, &dst_ip);
2211 	for (i = 0, port = port_list->list; i < port_list->count; i++, port++) {
2212 		if (port->test_address_count == port->num_addrs) {
2213 			/* already populated */
2214 			continue;
2215 		}
2216 		if (S_debug) {
2217 			T_LOG("Sending on %s", port->ifname);
2218 		}
2219 		for (u_int j = 0; j < port->num_addrs; j++) {
2220 			uint32_t        generation;
2221 
2222 			if (retry) {
2223 				uint64_t        addr_bit;
2224 
2225 				addr_bit = 1 << j;
2226 				if ((port->test_address_present & addr_bit)
2227 				    != 0) {
2228 					/* already present */
2229 					continue;
2230 				}
2231 				T_LOG("Retry port %s unit %u address %u",
2232 				    port->ifname, port->unit, j);
2233 			}
2234 			generation = next_generation();
2235 			send_generation(port,
2236 			    af,
2237 			    j,
2238 			    dst_eaddr,
2239 			    &dst_ip,
2240 			    generation);
2241 
2242 			/* receive across all ports */
2243 			check_receive_generation(port_list,
2244 			    af,
2245 			    generation,
2246 			    validator,
2247 			    context);
2248 
2249 			/* ensure that every port saw the packet */
2250 			check_received_count(port_list, port, 1);
2251 		}
2252 	}
2253 	return;
2254 }
2255 
2256 static inline const char *
af_get_str(uint8_t af)2257 af_get_str(uint8_t af)
2258 {
2259 	return (af == AF_INET) ? "IPv4" : "IPv6";
2260 }
2261 
2262 static void
bridge_learning_test(switch_port_list_t port_list,uint8_t af,packet_validator_t validator,void * context,const ether_addr_t * dst_eaddr)2263 bridge_learning_test(switch_port_list_t port_list,
2264     uint8_t af,
2265     packet_validator_t validator,
2266     void * context,
2267     const ether_addr_t * dst_eaddr)
2268 {
2269 	char            ntoabuf[ETHER_NTOA_BUFSIZE];
2270 	u_int           i;
2271 	switch_port_t   port;
2272 	bool            verified = false;
2273 
2274 	ether_ntoa_buf(dst_eaddr, ntoabuf, sizeof(ntoabuf));
2275 
2276 	/*
2277 	 * Send a broadcast frame from every port in the list so that the bridge
2278 	 * learns our MAC address.
2279 	 */
2280 #define BROADCAST_MAX_TRIES             20
2281 	for (int try = 1; try < BROADCAST_MAX_TRIES; try++) {
2282 		bool    retry = (try > 1);
2283 
2284 		if (!retry) {
2285 			T_LOG("%s: %s #ports %u #addrs %u dest %s",
2286 			    __func__,
2287 			    af_get_str(af),
2288 			    port_list->count, port_list->list->num_addrs,
2289 			    ntoabuf);
2290 		} else {
2291 			T_LOG("%s: %s #ports %u #addrs %u dest %s (TRY=%d)",
2292 			    __func__,
2293 			    af_get_str(af),
2294 			    port_list->count, port_list->list->num_addrs,
2295 			    ntoabuf, try);
2296 		}
2297 		bridge_learning_test_once(port_list, af, validator, context,
2298 		    dst_eaddr, retry);
2299 		/*
2300 		 * In the event of a memory allocation failure, it's possible
2301 		 * that the address was not learned. Figure out whether
2302 		 * all addresses are present, and if not, we'll retry on
2303 		 * those that are not present.
2304 		 */
2305 		verified = switch_port_list_verify_rt_table(port_list, false);
2306 		if (verified) {
2307 			break;
2308 		}
2309 		/* wait a short time to allow the system to recover */
2310 		usleep(100 * 1000);
2311 	}
2312 	T_QUIET;
2313 	T_ASSERT_TRUE(verified, "All addresses present");
2314 
2315 	/*
2316 	 * Since we just broadcast on every port in the switch, the bridge knows
2317 	 * the port's MAC addresses. The bridge should not need to broadcast the
2318 	 * packet to learn, which means the unicast traffic should only arrive
2319 	 * on the intended port.
2320 	 */
2321 	for (i = 0, port = port_list->list; i < port_list->count; i++, port++) {
2322 		/* send unicast packets to every other port's MAC addresses */
2323 		unicast_send_all(port_list, af, port);
2324 
2325 		/* receive all of that generated traffic */
2326 		switch_port_list_check_receive(port_list, af, NULL, 0,
2327 		    validate_port_dhost, NULL);
2328 		/* check that we saw all of the unicast packets */
2329 		check_received_count(port_list, port, ALL_ADDRS);
2330 	}
2331 	T_PASS("%s", __func__);
2332 }
2333 
2334 /**
2335 ** MAC-NAT tests
2336 **/
2337 static void
mac_nat_check_received_count(switch_port_list_t port_list,switch_port_t port)2338 mac_nat_check_received_count(switch_port_list_t port_list, switch_port_t port)
2339 {
2340 	u_int           i;
2341 	switch_port_t   scan;
2342 
2343 	for (i = 0, scan = port_list->list; i < port_list->count; i++, scan++) {
2344 		u_int   expected = 0;
2345 
2346 		if (scan == port) {
2347 			expected = scan->num_addrs;
2348 		}
2349 		T_QUIET;
2350 		T_ASSERT_EQ(scan->test_count, expected,
2351 		    "%s [member %s]%s expected %u actual %u",
2352 		    scan->ifname, scan->member_ifname,
2353 		    scan->mac_nat ? " [mac-nat]" : "",
2354 		    expected, scan->test_count);
2355 	}
2356 }
2357 
2358 static void
validate_mac_nat(switch_port_t port,const ether_header_t * eh_p,__unused u_int pkt_len,__unused void * context)2359 validate_mac_nat(switch_port_t port, const ether_header_t * eh_p,
2360     __unused u_int pkt_len,
2361     __unused void * context)
2362 {
2363 	if (port->mac_nat) {
2364 		bool    equal;
2365 
2366 		/* source must match MAC-NAT interface */
2367 		equal = (bcmp(eh_p->ether_shost, &port->member_mac,
2368 		    sizeof(port->member_mac)) == 0);
2369 		if (!equal) {
2370 			ethernet_frame_validate(eh_p, pkt_len, true);
2371 		}
2372 		T_QUIET;
2373 		T_ASSERT_TRUE(equal, "source address match");
2374 		port->test_count++;
2375 	} else {
2376 		validate_not_present_dhost(port, eh_p, pkt_len, NULL);
2377 	}
2378 }
2379 
2380 static void
validate_mac_nat_in(switch_port_t port,const ether_header_t * eh_p,u_int pkt_len,__unused void * context)2381 validate_mac_nat_in(switch_port_t port, const ether_header_t * eh_p,
2382     u_int pkt_len, __unused void * context)
2383 {
2384 	if (S_debug) {
2385 		T_LOG("%s received %u bytes", port->member_ifname, pkt_len);
2386 		ethernet_frame_validate(eh_p, pkt_len, true);
2387 	}
2388 	T_QUIET;
2389 	T_ASSERT_EQ(eh_p->ether_dhost[EA_UNIT_INDEX], port->unit,
2390 	    "dhost unit %u expected %u",
2391 	    eh_p->ether_dhost[EA_UNIT_INDEX], port->unit);
2392 	port->test_count++;
2393 }
2394 
2395 static void
validate_mac_nat_arp_out(switch_port_t port,const ether_header_t * eh_p,u_int pkt_len,void * context)2396 validate_mac_nat_arp_out(switch_port_t port, const ether_header_t * eh_p,
2397     u_int pkt_len, void * context)
2398 {
2399 	const struct ether_arp *        earp;
2400 	switch_port_t                   send_port = (switch_port_t)context;
2401 
2402 	if (S_debug) {
2403 		T_LOG("%s received %u bytes", port->member_ifname, pkt_len);
2404 		ethernet_frame_validate(eh_p, pkt_len, true);
2405 	}
2406 	T_QUIET;
2407 	T_ASSERT_EQ((int)ntohs(eh_p->ether_type), (int)ETHERTYPE_ARP, NULL);
2408 	earp = (const struct ether_arp *)(const void *)(eh_p + 1);
2409 	T_QUIET;
2410 	T_ASSERT_GE(pkt_len, (u_int)(sizeof(*eh_p) + sizeof(*earp)), NULL);
2411 	if (port->mac_nat) {
2412 		bool            equal;
2413 
2414 		/* source ethernet must match MAC-NAT interface */
2415 		equal = (bcmp(eh_p->ether_shost, &port->member_mac,
2416 		    sizeof(port->member_mac)) == 0);
2417 		if (!equal) {
2418 			ethernet_frame_validate(eh_p, pkt_len, true);
2419 		}
2420 		T_QUIET;
2421 		T_ASSERT_TRUE(equal, "%s -> %s source address translated",
2422 		    send_port->member_ifname,
2423 		    port->member_ifname);
2424 		/* sender hw must match MAC-NAT interface */
2425 		equal = (bcmp(earp->arp_sha, &port->member_mac,
2426 		    sizeof(port->member_mac)) == 0);
2427 		if (!equal) {
2428 			ethernet_frame_validate(eh_p, pkt_len, true);
2429 		}
2430 		T_QUIET;
2431 		T_ASSERT_TRUE(equal, "%s -> %s sender hardware translated",
2432 		    send_port->member_ifname,
2433 		    port->member_ifname);
2434 	} else {
2435 		/* source ethernet must match the sender */
2436 		T_QUIET;
2437 		T_ASSERT_EQ(eh_p->ether_shost[EA_UNIT_INDEX], send_port->unit,
2438 		    "%s -> %s unit %u expected %u",
2439 		    send_port->member_ifname,
2440 		    port->member_ifname,
2441 		    eh_p->ether_shost[EA_UNIT_INDEX], send_port->unit);
2442 		/* source hw must match the sender */
2443 		T_QUIET;
2444 		T_ASSERT_EQ(earp->arp_sha[EA_UNIT_INDEX], send_port->unit,
2445 		    "%s -> %s unit %u expected %u",
2446 		    send_port->member_ifname,
2447 		    port->member_ifname,
2448 		    earp->arp_sha[EA_UNIT_INDEX], send_port->unit);
2449 	}
2450 	port->test_count++;
2451 }
2452 
2453 static void
validate_mac_nat_arp_in(switch_port_t port,const ether_header_t * eh_p,u_int pkt_len,void * context)2454 validate_mac_nat_arp_in(switch_port_t port, const ether_header_t * eh_p,
2455     u_int pkt_len, void * context)
2456 {
2457 	const struct ether_arp *        earp;
2458 	switch_port_t                   send_port = (switch_port_t)context;
2459 
2460 	if (S_debug) {
2461 		T_LOG("%s received %u bytes", port->member_ifname, pkt_len);
2462 		ethernet_frame_validate(eh_p, pkt_len, true);
2463 	}
2464 	earp = (const struct ether_arp *)(const void *)(eh_p + 1);
2465 	T_QUIET;
2466 	T_ASSERT_EQ((int)ntohs(eh_p->ether_type), (int)ETHERTYPE_ARP, NULL);
2467 	T_QUIET;
2468 	T_ASSERT_GE(pkt_len, (u_int)(sizeof(*eh_p) + sizeof(*earp)), NULL);
2469 	T_QUIET;
2470 	T_ASSERT_FALSE(port->mac_nat, NULL);
2471 
2472 	/* destination ethernet must match the unit */
2473 	T_QUIET;
2474 	T_ASSERT_EQ(eh_p->ether_dhost[EA_UNIT_INDEX], port->unit,
2475 	    "%s -> %s unit %u expected %u",
2476 	    send_port->member_ifname,
2477 	    port->member_ifname,
2478 	    eh_p->ether_dhost[EA_UNIT_INDEX], port->unit);
2479 	/* source hw must match the sender */
2480 	T_QUIET;
2481 	T_ASSERT_EQ(earp->arp_tha[EA_UNIT_INDEX], port->unit,
2482 	    "%s -> %s unit %u expected %u",
2483 	    send_port->member_ifname,
2484 	    port->member_ifname,
2485 	    earp->arp_tha[EA_UNIT_INDEX], port->unit);
2486 	port->test_count++;
2487 }
2488 
2489 static void
mac_nat_test_arp_out(switch_port_list_t port_list)2490 mac_nat_test_arp_out(switch_port_list_t port_list)
2491 {
2492 	u_int           i;
2493 	struct in_addr  ip_dst;
2494 	switch_port_t   port;
2495 
2496 	ip_dst = get_external_ipv4_address();
2497 	for (i = 0, port = port_list->list; i < port_list->count; i++, port++) {
2498 		if (port->mac_nat) {
2499 			continue;
2500 		}
2501 		for (u_int j = 0; j < port->num_addrs; j++) {
2502 			ether_addr_t    eaddr;
2503 			struct in_addr  ip_src;
2504 
2505 			set_ethernet_address(&eaddr, port->unit, j);
2506 			get_ipv4_address(port->unit, j, &ip_src);
2507 			switch_port_send_arp(port,
2508 			    ARPOP_REQUEST,
2509 			    &eaddr,
2510 			    ip_src,
2511 			    NULL,
2512 			    ip_dst);
2513 			switch_port_list_check_receive(port_list, AF_INET,
2514 			    NULL, 0,
2515 			    validate_mac_nat_arp_out,
2516 			    port);
2517 			check_received_count(port_list, port, 1);
2518 		}
2519 	}
2520 	T_PASS("%s", __func__);
2521 }
2522 
2523 static void
mac_nat_send_arp_response(switch_port_t ext_port,switch_port_t port)2524 mac_nat_send_arp_response(switch_port_t ext_port, switch_port_t port)
2525 {
2526 	struct in_addr  ip_src;
2527 
2528 	T_QUIET;
2529 	T_ASSERT_TRUE(ext_port->mac_nat, "%s is MAC-NAT interface",
2530 	    ext_port->member_ifname);
2531 	ip_src = get_external_ipv4_address();
2532 	for (u_int j = 0; j < port->num_addrs; j++) {
2533 		struct in_addr  ip_dst;
2534 
2535 		get_ipv4_address(port->unit, j, &ip_dst);
2536 		if (S_debug) {
2537 			T_LOG("Generating ARP destined to %s %s",
2538 			    port->ifname, inet_ntoa(ip_dst));
2539 		}
2540 		switch_port_send_arp(ext_port,
2541 		    ARPOP_REPLY,
2542 		    &ether_external,
2543 		    ip_src,
2544 		    &ext_port->member_mac,
2545 		    ip_dst);
2546 	}
2547 }
2548 
2549 static void
mac_nat_test_arp_in(switch_port_list_t port_list)2550 mac_nat_test_arp_in(switch_port_list_t port_list)
2551 {
2552 	u_int           i;
2553 	struct in_addr  ip_src;
2554 	switch_port_t   port;
2555 
2556 	ip_src = get_external_ipv4_address();
2557 	for (i = 0, port = port_list->list; i < port_list->count; i++, port++) {
2558 		if (port->mac_nat) {
2559 			continue;
2560 		}
2561 		mac_nat_send_arp_response(port_list->list, port);
2562 
2563 		/* receive the generated traffic */
2564 		switch_port_list_check_receive(port_list, AF_INET, NULL, 0,
2565 		    validate_mac_nat_arp_in,
2566 		    port_list->list);
2567 
2568 		/* verify that only the single port got the packet */
2569 		mac_nat_check_received_count(port_list, port);
2570 	}
2571 	T_PASS("%s", __func__);
2572 }
2573 
2574 static void
validate_mac_nat_dhcp(switch_port_t port,const ether_header_t * eh_p,u_int pkt_len,void * context)2575 validate_mac_nat_dhcp(switch_port_t port, const ether_header_t * eh_p,
2576     u_int pkt_len, void * context)
2577 {
2578 	u_int                           dp_flags;
2579 	const struct bootp_packet *     pkt;
2580 	switch_port_t                   send_port = (switch_port_t)context;
2581 
2582 
2583 	T_QUIET;
2584 	T_ASSERT_GE(pkt_len, (u_int)sizeof(*pkt), NULL);
2585 	T_QUIET;
2586 	T_ASSERT_EQ((int)ntohs(eh_p->ether_type), (int)ETHERTYPE_IP, NULL);
2587 	pkt = (const struct bootp_packet *)(const void *)(eh_p + 1);
2588 
2589 	dp_flags = ntohs(pkt->bp_bootp.bp_unused);
2590 	if (port->mac_nat) {
2591 		bool            equal;
2592 
2593 		/* Broadcast bit must be set */
2594 		T_QUIET;
2595 		T_ASSERT_BITS_SET(dp_flags, (u_int)DHCP_FLAGS_BROADCAST,
2596 		    "%s -> %s: flags 0x%x must have 0x%x",
2597 		    send_port->member_ifname,
2598 		    port->member_ifname,
2599 		    dp_flags, DHCP_FLAGS_BROADCAST);
2600 
2601 		/* source must match MAC-NAT interface */
2602 		equal = (bcmp(eh_p->ether_shost, &port->member_mac,
2603 		    sizeof(port->member_mac)) == 0);
2604 		if (!equal) {
2605 			ethernet_frame_validate(eh_p, pkt_len, true);
2606 		}
2607 		T_QUIET;
2608 		T_ASSERT_TRUE(equal, "%s -> %s source address translated",
2609 		    send_port->member_ifname,
2610 		    port->member_ifname);
2611 	} else {
2612 		/* Broadcast bit must not be set */
2613 		T_QUIET;
2614 		T_ASSERT_BITS_NOTSET(dp_flags, DHCP_FLAGS_BROADCAST,
2615 		    "%s -> %s flags 0x%x must not have 0x%x",
2616 		    send_port->member_ifname,
2617 		    port->member_ifname,
2618 		    dp_flags, DHCP_FLAGS_BROADCAST);
2619 		T_QUIET;
2620 		T_ASSERT_EQ(eh_p->ether_shost[EA_UNIT_INDEX], send_port->unit,
2621 		    "%s -> %s unit %u expected %u",
2622 		    send_port->member_ifname,
2623 		    port->member_ifname,
2624 		    eh_p->ether_shost[EA_UNIT_INDEX], send_port->unit);
2625 	}
2626 	port->test_count++;
2627 }
2628 
2629 static u_int
make_dhcp_payload(dhcp_min_payload_t payload,ether_addr_t * eaddr)2630 make_dhcp_payload(dhcp_min_payload_t payload, ether_addr_t *eaddr)
2631 {
2632 	struct bootp *  dhcp;
2633 	u_int           payload_length;
2634 
2635 	/* create a minimal BOOTP packet */
2636 	payload_length = sizeof(*payload);
2637 	dhcp = (struct bootp *)payload;
2638 	bzero(dhcp, payload_length);
2639 	dhcp->bp_op = BOOTREQUEST;
2640 	dhcp->bp_htype = ARPHRD_ETHER;
2641 	dhcp->bp_hlen = sizeof(*eaddr);
2642 	bcopy(eaddr->octet, dhcp->bp_chaddr, sizeof(eaddr->octet));
2643 	return payload_length;
2644 }
2645 
2646 static void
mac_nat_test_dhcp(switch_port_list_t port_list,bool link_layer_unicast)2647 mac_nat_test_dhcp(switch_port_list_t port_list, bool link_layer_unicast)
2648 {
2649 	u_int           i;
2650 	struct in_addr  ip_dst = { INADDR_BROADCAST };
2651 	struct in_addr  ip_src = { INADDR_ANY };
2652 	switch_port_t   port;
2653 	ether_addr_t *  ether_dst;
2654 
2655 	if (link_layer_unicast) {
2656 		/* use link-layer address of MAC-NAT interface */
2657 		ether_dst = &port_list->list[0].member_mac;
2658 	} else {
2659 		/* use link-layer broadcast address */
2660 		ether_dst = &ether_broadcast;
2661 	}
2662 	for (i = 0, port = port_list->list; i < port_list->count; i++, port++) {
2663 		ether_addr_t            eaddr;
2664 		dhcp_min_payload        payload;
2665 		u_int                   payload_len;
2666 
2667 		if (!link_layer_unicast && port->mac_nat) {
2668 			/* only send through non-MAC-NAT ports */
2669 			continue;
2670 		}
2671 		set_ethernet_address(&eaddr, port->unit, 0);
2672 		payload_len = make_dhcp_payload(&payload, &eaddr);
2673 		if (S_debug) {
2674 			T_LOG("%s: transmit DHCP packet (member %s)",
2675 			    port->ifname, port->member_ifname);
2676 		}
2677 		switch_port_send_udp(port,
2678 		    AF_INET,
2679 		    &eaddr,
2680 		    (union ifbrip *)&ip_src,
2681 		    BOOTP_CLIENT_PORT,
2682 		    ether_dst,
2683 		    (union ifbrip *)&ip_dst,
2684 		    BOOTP_SERVER_PORT,
2685 		    &payload,
2686 		    payload_len);
2687 
2688 		switch_port_list_check_receive(port_list, AF_INET, NULL, 0,
2689 		    validate_mac_nat_dhcp,
2690 		    port);
2691 
2692 		check_received_count(port_list, port, 1);
2693 		if (link_layer_unicast) {
2694 			/* send a single unicast to MAC-NAT interface */
2695 			break;
2696 		}
2697 	}
2698 	T_PASS("%s %s", __func__,
2699 	    link_layer_unicast ? "unicast" : "broadcast");
2700 }
2701 
2702 
2703 static void
validate_mac_nat_nd6(switch_port_t port,const struct icmp6_hdr * icmp6,u_int icmp6_len,uint8_t opt_type,u_int nd_hdr_size,switch_port_t send_port)2704 validate_mac_nat_nd6(switch_port_t port,
2705     const struct icmp6_hdr * icmp6,
2706     u_int icmp6_len,
2707     uint8_t opt_type,
2708     u_int nd_hdr_size,
2709     switch_port_t send_port)
2710 {
2711 	const uint8_t *                 linkaddr;
2712 	const uint8_t *                 ptr;
2713 	const struct nd_opt_hdr *       nd_opt;
2714 	u_int                           nd_size;
2715 
2716 	ptr = (const uint8_t *)icmp6;
2717 	nd_size = nd_hdr_size + LINKADDR_OPT_LEN;
2718 	if (icmp6_len < nd_size) {
2719 		/* no LINKADDR option */
2720 		return;
2721 	}
2722 	nd_opt = (const struct nd_opt_hdr *)(const void *)(ptr + nd_hdr_size);
2723 	T_QUIET;
2724 	T_ASSERT_EQ(nd_opt->nd_opt_type, opt_type, NULL);
2725 	T_QUIET;
2726 	T_ASSERT_EQ(GET_ND_OPT_LEN(nd_opt->nd_opt_len), LINKADDR_OPT_LEN, NULL);
2727 	linkaddr = (const uint8_t *)(nd_opt + 1);
2728 	if (port->mac_nat) {
2729 		bool    equal;
2730 
2731 		equal = (bcmp(linkaddr, &port->member_mac,
2732 		    sizeof(port->member_mac)) == 0);
2733 		T_QUIET;
2734 		T_ASSERT_TRUE(equal, "%s -> %s sender hardware translated",
2735 		    send_port->member_ifname,
2736 		    port->member_ifname);
2737 	} else {
2738 		/* source hw must match the sender */
2739 		T_QUIET;
2740 		T_ASSERT_EQ(linkaddr[EA_UNIT_INDEX], send_port->unit,
2741 		    "%s -> %s unit %u expected %u",
2742 		    send_port->member_ifname,
2743 		    port->member_ifname,
2744 		    linkaddr[EA_UNIT_INDEX], send_port->unit);
2745 	}
2746 }
2747 
2748 static void
validate_mac_nat_icmp6_out(switch_port_t port,const struct icmp6_hdr * icmp6,u_int icmp6_len,switch_port_t send_port)2749 validate_mac_nat_icmp6_out(switch_port_t port, const struct icmp6_hdr * icmp6,
2750     u_int icmp6_len, switch_port_t send_port)
2751 {
2752 	switch (icmp6->icmp6_type) {
2753 	case ND_NEIGHBOR_ADVERT:
2754 		validate_mac_nat_nd6(port, icmp6, icmp6_len,
2755 		    ND_OPT_TARGET_LINKADDR,
2756 		    sizeof(struct nd_neighbor_advert),
2757 		    send_port);
2758 		break;
2759 	case ND_NEIGHBOR_SOLICIT:
2760 		validate_mac_nat_nd6(port, icmp6, icmp6_len,
2761 		    ND_OPT_SOURCE_LINKADDR,
2762 		    sizeof(struct nd_neighbor_solicit),
2763 		    send_port);
2764 		break;
2765 	case ND_ROUTER_SOLICIT:
2766 		validate_mac_nat_nd6(port, icmp6, icmp6_len,
2767 		    ND_OPT_SOURCE_LINKADDR,
2768 		    sizeof(struct nd_router_solicit),
2769 		    send_port);
2770 		break;
2771 	default:
2772 		T_FAIL("Unsupported icmp6 type %d", icmp6->icmp6_type);
2773 		break;
2774 	}
2775 }
2776 
2777 static void
validate_mac_nat_nd6_out(switch_port_t port,const ether_header_t * eh_p,u_int pkt_len,void * context)2778 validate_mac_nat_nd6_out(switch_port_t port, const ether_header_t * eh_p,
2779     u_int pkt_len, void * context)
2780 {
2781 	const struct icmp6_hdr *        icmp6;
2782 	const struct ip6_hdr *          ip6;
2783 	switch_port_t                   send_port = (switch_port_t)context;
2784 
2785 	if (S_debug) {
2786 		T_LOG("%s received %u bytes", port->member_ifname, pkt_len);
2787 		ethernet_frame_validate(eh_p, pkt_len, true);
2788 	}
2789 	T_QUIET;
2790 	T_ASSERT_EQ(ntohs(eh_p->ether_type), (u_short)ETHERTYPE_IPV6, NULL);
2791 	ip6 = (const struct ip6_hdr *)(const void *)(eh_p + 1);
2792 	icmp6 = (const struct icmp6_hdr *)(const void *)(ip6 + 1);
2793 	T_QUIET;
2794 	T_ASSERT_GE(pkt_len, (u_int)MIN_ICMP6_LEN, NULL);
2795 	T_QUIET;
2796 	T_ASSERT_EQ(ip6->ip6_nxt, IPPROTO_ICMPV6, NULL);
2797 
2798 	/* validate the ethernet header */
2799 	if (port->mac_nat) {
2800 		bool            equal;
2801 
2802 		/* source ethernet must match MAC-NAT interface */
2803 		equal = (bcmp(eh_p->ether_shost, &port->member_mac,
2804 		    sizeof(port->member_mac)) == 0);
2805 		if (!equal) {
2806 			ethernet_frame_validate(eh_p, pkt_len, true);
2807 		}
2808 		T_QUIET;
2809 		T_ASSERT_TRUE(equal, "%s -> %s source address translated",
2810 		    send_port->member_ifname,
2811 		    port->member_ifname);
2812 	} else {
2813 		/* source ethernet must match the sender */
2814 		T_QUIET;
2815 		T_ASSERT_EQ(eh_p->ether_shost[EA_UNIT_INDEX], send_port->unit,
2816 		    "%s -> %s unit %u expected %u",
2817 		    send_port->member_ifname,
2818 		    port->member_ifname,
2819 		    eh_p->ether_shost[EA_UNIT_INDEX], send_port->unit);
2820 	}
2821 	/* validate the icmp6 payload */
2822 	validate_mac_nat_icmp6_out(port, icmp6,
2823 	    pkt_len - ETHER_IPV6_LEN,
2824 	    send_port);
2825 	port->test_count++;
2826 }
2827 
2828 static void
mac_nat_test_nd6_out(switch_port_list_t port_list)2829 mac_nat_test_nd6_out(switch_port_list_t port_list)
2830 {
2831 	ether_addr_t *  ext_mac;
2832 	switch_port_t   ext_port;
2833 	u_int           i;
2834 	union ifbrip    ip_dst;
2835 	switch_port_t   port;
2836 
2837 	get_external_ip_address(AF_INET6, &ip_dst);
2838 	ext_port = port_list->list;
2839 	T_QUIET;
2840 	T_ASSERT_TRUE(ext_port->mac_nat, NULL);
2841 	ext_mac = &ext_port->member_mac;
2842 	for (i = 0, port = port_list->list; i < port_list->count; i++, port++) {
2843 		if (port->mac_nat) {
2844 			continue;
2845 		}
2846 		/* neighbor solicit */
2847 		for (u_int j = 0; j < port->num_addrs; j++) {
2848 			ether_addr_t    eaddr;
2849 			union ifbrip    ip_src;
2850 
2851 			set_ethernet_address(&eaddr, port->unit, j);
2852 			get_ip_address(AF_INET6, port->unit, j, &ip_src);
2853 			switch_port_send_nd6(port,
2854 			    ND_NEIGHBOR_SOLICIT,
2855 			    &eaddr,
2856 			    &ip_src.ifbrip_addr6,
2857 			    NULL,
2858 			    NULL,
2859 			    &ip_dst.ifbrip_addr6);
2860 			switch_port_list_check_receive(port_list, AF_INET,
2861 			    NULL, 0,
2862 			    validate_mac_nat_nd6_out,
2863 			    port);
2864 			check_received_count(port_list, port, 1);
2865 		}
2866 		/* neighbor advert */
2867 		for (u_int j = 0; j < port->num_addrs; j++) {
2868 			ether_addr_t    eaddr;
2869 			union ifbrip    ip_src;
2870 
2871 			set_ethernet_address(&eaddr, port->unit, j);
2872 			get_ip_address(AF_INET6, port->unit, j, &ip_src);
2873 			switch_port_send_nd6(port,
2874 			    ND_NEIGHBOR_ADVERT,
2875 			    &eaddr,
2876 			    &ip_src.ifbrip_addr6,
2877 			    NULL,
2878 			    &eaddr,
2879 			    &ip_src.ifbrip_addr6);
2880 			switch_port_list_check_receive(port_list, AF_INET,
2881 			    NULL, 0,
2882 			    validate_mac_nat_nd6_out,
2883 			    port);
2884 			check_received_count(port_list, port, 1);
2885 		}
2886 		/* router solicit */
2887 		for (u_int j = 0; j < port->num_addrs; j++) {
2888 			ether_addr_t    eaddr;
2889 			union ifbrip    ip_src;
2890 
2891 			set_ethernet_address(&eaddr, port->unit, j);
2892 			get_ip_address(AF_INET6, port->unit, j, &ip_src);
2893 			//get_ipv6ll_address(port->unit, j, &ip_src.ifbrip_addr6);
2894 			switch_port_send_nd6(port,
2895 			    ND_ROUTER_SOLICIT,
2896 			    &eaddr,
2897 			    &ip_src.ifbrip_addr6,
2898 			    NULL,
2899 			    NULL,
2900 			    NULL);
2901 			switch_port_list_check_receive(port_list, AF_INET,
2902 			    NULL, 0,
2903 			    validate_mac_nat_nd6_out,
2904 			    port);
2905 			check_received_count(port_list, port, 1);
2906 		}
2907 	}
2908 	T_PASS("%s", __func__);
2909 }
2910 
2911 static void
mac_nat_send_response(switch_port_t ext_port,uint8_t af,switch_port_t port)2912 mac_nat_send_response(switch_port_t ext_port, uint8_t af, switch_port_t port)
2913 {
2914 	union ifbrip    src_ip;
2915 
2916 	T_QUIET;
2917 	T_ASSERT_TRUE(ext_port->mac_nat, "%s is MAC-NAT interface",
2918 	    ext_port->member_ifname);
2919 	if (S_debug) {
2920 		T_LOG("Generating UDP traffic destined to %s", port->ifname);
2921 	}
2922 	get_external_ip_address(af, &src_ip);
2923 	for (u_int j = 0; j < port->num_addrs; j++) {
2924 		union ifbrip    ip;
2925 
2926 		get_ip_address(af, port->unit, j, &ip);
2927 		switch_port_send_udp(ext_port,
2928 		    af,
2929 		    &ether_external,
2930 		    &src_ip,
2931 		    TEST_DEST_PORT,
2932 		    &ext_port->member_mac,
2933 		    &ip,
2934 		    TEST_SOURCE_PORT,
2935 		    NULL, 0);
2936 	}
2937 }
2938 
2939 
2940 static void
mac_nat_test_ip_once(switch_port_list_t port_list,uint8_t af,bool retry)2941 mac_nat_test_ip_once(switch_port_list_t port_list, uint8_t af, bool retry)
2942 {
2943 	union ifbrip    dst_ip;
2944 	u_int           i;
2945 	switch_port_t   port;
2946 
2947 	get_external_ip_address(af, &dst_ip);
2948 	for (i = 0, port = port_list->list; i < port_list->count; i++, port++) {
2949 		if (port->test_address_count == port->num_addrs) {
2950 			/* already populated */
2951 			continue;
2952 		}
2953 		if (S_debug) {
2954 			T_LOG("Sending on %s", port->ifname);
2955 		}
2956 		for (u_int j = 0; j < port->num_addrs; j++) {
2957 			uint32_t        generation;
2958 
2959 			if (retry) {
2960 				uint64_t        addr_bit;
2961 
2962 				addr_bit = 1 << j;
2963 				if ((port->test_address_present & addr_bit)
2964 				    != 0) {
2965 					/* already present */
2966 					continue;
2967 				}
2968 				T_LOG("Retry port %s unit %u address %u",
2969 				    port->ifname, port->unit, j);
2970 			}
2971 
2972 			generation = next_generation();
2973 			send_generation(port,
2974 			    af,
2975 			    j,
2976 			    &ether_external,
2977 			    &dst_ip,
2978 			    generation);
2979 
2980 			/* receive across all ports */
2981 			check_receive_generation(port_list,
2982 			    af,
2983 			    generation,
2984 			    validate_mac_nat,
2985 			    NULL);
2986 
2987 			/* ensure that every port saw the packet */
2988 			check_received_count(port_list, port, 1);
2989 		}
2990 	}
2991 	return;
2992 }
2993 
2994 static void
mac_nat_test_ip(switch_port_list_t port_list,uint8_t af)2995 mac_nat_test_ip(switch_port_list_t port_list, uint8_t af)
2996 {
2997 	u_int           i;
2998 	switch_port_t   port;
2999 	bool            verified = false;
3000 
3001 	/*
3002 	 * Send a packet from every port in the list so that the bridge
3003 	 * learns the MAC addresses and IP addresses.
3004 	 */
3005 #define MAC_NAT_MAX_TRIES               20
3006 	for (int try = 1; try < BROADCAST_MAX_TRIES; try++) {
3007 		bool    retry = (try > 1);
3008 
3009 		if (!retry) {
3010 			T_LOG("%s: #ports %u #addrs %u",
3011 			    __func__,
3012 			    port_list->count, port_list->list->num_addrs);
3013 		} else {
3014 			T_LOG("%s: #ports %u #addrs %u destination (TRY=%d)",
3015 			    __func__,
3016 			    port_list->count, port_list->list->num_addrs,
3017 			    try);
3018 		}
3019 		mac_nat_test_ip_once(port_list, af, retry);
3020 		/*
3021 		 * In the event of a memory allocation failure, it's possible
3022 		 * that the address was not learned. Figure out whether
3023 		 * all addresses are present, and if not, we'll retry on
3024 		 * those that are not present.
3025 		 */
3026 		verified = switch_port_list_verify_mac_nat(port_list, false);
3027 		if (verified) {
3028 			break;
3029 		}
3030 		/* wait a short time to allow the system to recover */
3031 		usleep(100 * 1000);
3032 	}
3033 	T_QUIET;
3034 	T_ASSERT_TRUE(verified, "All addresses present");
3035 
3036 	/*
3037 	 * The bridge now has an IP address <-> MAC address binding for every
3038 	 * address on each internal interface.
3039 	 *
3040 	 * Generate an inbound packet on the MAC-NAT interface targeting
3041 	 * each interface address. Verify that the packet appears on
3042 	 * the appropriate internal address with appropriate translation.
3043 	 */
3044 	for (i = 0, port = port_list->list; i < port_list->count; i++, port++) {
3045 		if (port->mac_nat) {
3046 			continue;
3047 		}
3048 		mac_nat_send_response(port_list->list, af, port);
3049 
3050 		/* receive the generated traffic */
3051 		switch_port_list_check_receive(port_list, AF_INET, NULL, 0,
3052 		    validate_mac_nat_in,
3053 		    NULL);
3054 
3055 		/* verify that only the single port got the packet */
3056 		mac_nat_check_received_count(port_list, port);
3057 	}
3058 	T_PASS("%s", __func__);
3059 }
3060 
3061 /**
3062 ** interface management
3063 **/
3064 
3065 static void
ifnet_get_lladdr(int s,const char * ifname,ether_addr_t * eaddr)3066 ifnet_get_lladdr(int s, const char * ifname, ether_addr_t * eaddr)
3067 {
3068 	int err;
3069 	struct ifreq ifr;
3070 
3071 	bzero(&ifr, sizeof(ifr));
3072 	strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
3073 	ifr.ifr_addr.sa_family = AF_LINK;
3074 	ifr.ifr_addr.sa_len = ETHER_ADDR_LEN;
3075 	err = ioctl(s, SIOCGIFLLADDR, &ifr);
3076 	T_QUIET;
3077 	T_ASSERT_POSIX_SUCCESS(err, "SIOCGIFLLADDR %s", ifname);
3078 	bcopy(ifr.ifr_addr.sa_data, eaddr->octet, ETHER_ADDR_LEN);
3079 	return;
3080 }
3081 
3082 
3083 static int
ifnet_attach_ip(int s,char * name)3084 ifnet_attach_ip(int s, char * name)
3085 {
3086 	int                     err;
3087 	struct ifreq    ifr;
3088 
3089 	bzero(&ifr, sizeof(ifr));
3090 	strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
3091 	err = ioctl(s, SIOCPROTOATTACH, &ifr);
3092 	T_QUIET;
3093 	T_ASSERT_POSIX_SUCCESS(err, "SIOCPROTOATTACH %s", ifr.ifr_name);
3094 	return err;
3095 }
3096 
3097 #if 0
3098 static int
3099 ifnet_detach_ip(int s, char * name)
3100 {
3101 	int                     err;
3102 	struct ifreq    ifr;
3103 
3104 	bzero(&ifr, sizeof(ifr));
3105 	strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
3106 	err = ioctl(s, SIOCPROTODETACH, &ifr);
3107 	T_QUIET;
3108 	T_ASSERT_POSIX_SUCCESS(err, "SIOCPROTODETACH %s", ifr.ifr_name);
3109 	return err;
3110 }
3111 #endif
3112 
3113 static int
ifnet_destroy(int s,const char * ifname,bool fail_on_error)3114 ifnet_destroy(int s, const char * ifname, bool fail_on_error)
3115 {
3116 	int             err;
3117 	struct ifreq    ifr;
3118 
3119 	bzero(&ifr, sizeof(ifr));
3120 	strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
3121 	err = ioctl(s, SIOCIFDESTROY, &ifr);
3122 	if (fail_on_error) {
3123 		T_QUIET;
3124 		T_ASSERT_POSIX_SUCCESS(err, "SIOCSIFDESTROY %s", ifr.ifr_name);
3125 	}
3126 	if (err < 0) {
3127 		T_LOG("SIOCSIFDESTROY %s", ifr.ifr_name);
3128 	}
3129 	return err;
3130 }
3131 
3132 static int
ifnet_set_flags(int s,const char * ifname,uint16_t flags_set,uint16_t flags_clear)3133 ifnet_set_flags(int s, const char * ifname,
3134     uint16_t flags_set, uint16_t flags_clear)
3135 {
3136 	uint16_t        flags_after;
3137 	uint16_t        flags_before;
3138 	struct ifreq    ifr;
3139 	int             ret;
3140 
3141 	bzero(&ifr, sizeof(ifr));
3142 	strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
3143 	ret = ioctl(s, SIOCGIFFLAGS, (caddr_t)&ifr);
3144 	if (ret != 0) {
3145 		T_LOG("SIOCGIFFLAGS %s", ifr.ifr_name);
3146 		return ret;
3147 	}
3148 	flags_before = (uint16_t)ifr.ifr_flags;
3149 	ifr.ifr_flags |= flags_set;
3150 	ifr.ifr_flags &= ~(flags_clear);
3151 	flags_after = (uint16_t)ifr.ifr_flags;
3152 	if (flags_before == flags_after) {
3153 		/* nothing to do */
3154 		ret = 0;
3155 	} else {
3156 		/* issue the ioctl */
3157 		T_QUIET;
3158 		T_ASSERT_POSIX_SUCCESS(ioctl(s, SIOCSIFFLAGS, &ifr),
3159 		    "SIOCSIFFLAGS %s 0x%x",
3160 		    ifr.ifr_name, (uint16_t)ifr.ifr_flags);
3161 		if (S_debug) {
3162 			T_LOG("setflags(%s set 0x%x clear 0x%x) 0x%x => 0x%x",
3163 			    ifr.ifr_name, flags_set, flags_clear,
3164 			    flags_before, flags_after);
3165 		}
3166 	}
3167 	return ret;
3168 }
3169 
3170 #define BRIDGE_NAME     "bridge"
3171 #define BRIDGE200       BRIDGE_NAME "200"
3172 
3173 #define FETH_NAME       "feth"
3174 
3175 /* On some platforms with DEBUG kernel, we need to wait a while */
3176 #define SIFCREATE_RETRY 600
3177 
3178 static int
ifnet_create(int s,const char * ifname)3179 ifnet_create(int s, const char * ifname)
3180 {
3181 	int             error = 0;
3182 	struct ifreq    ifr;
3183 
3184 	bzero(&ifr, sizeof(ifr));
3185 	strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
3186 
3187 	for (int i = 0; i < SIFCREATE_RETRY; i++) {
3188 		if (ioctl(s, SIOCIFCREATE, &ifr) < 0) {
3189 			error = errno;
3190 			T_LOG("SIOCSIFCREATE %s: %s", ifname,
3191 			    strerror(error));
3192 			if (error == EBUSY) {
3193 				/* interface is tearing down, try again */
3194 				usleep(10000);
3195 			} else if (error == EEXIST) {
3196 				/* interface exists, try destroying it */
3197 				(void)ifnet_destroy(s, ifname, false);
3198 			} else {
3199 				/* unexpected failure */
3200 				break;
3201 			}
3202 		} else {
3203 			error = 0;
3204 			break;
3205 		}
3206 	}
3207 	if (error == 0) {
3208 		error = ifnet_set_flags(s, ifname, IFF_UP, 0);
3209 	}
3210 	return error;
3211 }
3212 
3213 static int
siocdrvspec(int s,const char * ifname,u_long op,void * arg,size_t argsize,bool set)3214 siocdrvspec(int s, const char * ifname,
3215     u_long op, void *arg, size_t argsize, bool set)
3216 {
3217 	struct ifdrv    ifd;
3218 
3219 	memset(&ifd, 0, sizeof(ifd));
3220 	strlcpy(ifd.ifd_name, ifname, sizeof(ifd.ifd_name));
3221 	ifd.ifd_cmd = op;
3222 	ifd.ifd_len = argsize;
3223 	ifd.ifd_data = arg;
3224 	return ioctl(s, set ? SIOCSDRVSPEC : SIOCGDRVSPEC, &ifd);
3225 }
3226 
3227 
3228 static int
fake_set_peer(int s,const char * feth,const char * feth_peer)3229 fake_set_peer(int s, const char * feth, const char * feth_peer)
3230 {
3231 	struct if_fake_request  iffr;
3232 	int                     ret;
3233 
3234 	bzero((char *)&iffr, sizeof(iffr));
3235 	if (feth_peer != NULL) {
3236 		strlcpy(iffr.iffr_peer_name, feth_peer,
3237 		    sizeof(iffr.iffr_peer_name));
3238 	}
3239 	ret = siocdrvspec(s, feth, IF_FAKE_S_CMD_SET_PEER,
3240 	    &iffr, sizeof(iffr), true);
3241 	T_QUIET;
3242 	T_ASSERT_POSIX_SUCCESS(ret,
3243 	    "SIOCDRVSPEC(%s, IF_FAKE_S_CMD_SET_PEER, %s)",
3244 	    feth, (feth_peer != NULL) ? feth_peer : "<none>");
3245 	return ret;
3246 }
3247 
3248 static int
bridge_add_member(int s,const char * bridge,const char * member)3249 bridge_add_member(int s, const char * bridge, const char * member)
3250 {
3251 	struct ifbreq           req;
3252 	int                     ret;
3253 
3254 	memset(&req, 0, sizeof(req));
3255 	strlcpy(req.ifbr_ifsname, member, sizeof(req.ifbr_ifsname));
3256 	ret = siocdrvspec(s, bridge, BRDGADD, &req, sizeof(req), true);
3257 	T_QUIET;
3258 	T_ASSERT_POSIX_SUCCESS(ret, "%s %s %s", __func__, bridge, member);
3259 	return ret;
3260 }
3261 
3262 
3263 static int
bridge_member_modify_ifflags(int s,const char * bridge,const char * member,uint32_t flags_to_modify,bool set)3264 bridge_member_modify_ifflags(int s, const char * bridge, const char * member,
3265     uint32_t flags_to_modify, bool set)
3266 {
3267 	uint32_t        flags;
3268 	bool            need_set = false;
3269 	struct ifbreq   req;
3270 	int             ret;
3271 
3272 	memset(&req, 0, sizeof(req));
3273 	strlcpy(req.ifbr_ifsname, member, sizeof(req.ifbr_ifsname));
3274 	ret = siocdrvspec(s, bridge, BRDGGIFFLGS, &req, sizeof(req), false);
3275 	T_QUIET;
3276 	T_ASSERT_POSIX_SUCCESS(ret, "BRDGGIFFLGS %s %s", bridge, member);
3277 	flags = req.ifbr_ifsflags;
3278 	if (set) {
3279 		if ((flags & flags_to_modify) != flags_to_modify) {
3280 			need_set = true;
3281 			req.ifbr_ifsflags |= flags_to_modify;
3282 		}
3283 		/* need to set it */
3284 	} else if ((flags & flags_to_modify) != 0) {
3285 		/* need to clear it */
3286 		need_set = true;
3287 		req.ifbr_ifsflags &= ~flags_to_modify;
3288 	}
3289 	if (need_set) {
3290 		ret = siocdrvspec(s, bridge, BRDGSIFFLGS,
3291 		    &req, sizeof(req), true);
3292 		T_QUIET;
3293 		T_ASSERT_POSIX_SUCCESS(ret, "BRDGSIFFLGS %s %s 0x%x => 0x%x",
3294 		    bridge, member,
3295 		    flags, req.ifbr_ifsflags);
3296 	}
3297 	return ret;
3298 }
3299 
3300 static int
bridge_member_modify_mac_nat(int s,const char * bridge,const char * member,bool enable)3301 bridge_member_modify_mac_nat(int s, const char * bridge,
3302     const char * member, bool enable)
3303 {
3304 	return bridge_member_modify_ifflags(s, bridge, member,
3305 	           IFBIF_MAC_NAT,
3306 	           enable);
3307 }
3308 
3309 static int
bridge_member_modify_checksum_offload(int s,const char * bridge,const char * member,bool enable)3310 bridge_member_modify_checksum_offload(int s, const char * bridge,
3311     const char * member, bool enable)
3312 {
3313 #ifndef IFBIF_CHECKSUM_OFFLOAD
3314 #define IFBIF_CHECKSUM_OFFLOAD  0x10000 /* checksum inbound packets,
3315 	                                 * drop outbound packets with
3316 	                                 * bad checksum
3317 	                                 */
3318 #endif
3319 	return bridge_member_modify_ifflags(s, bridge, member,
3320 	           IFBIF_CHECKSUM_OFFLOAD,
3321 	           enable);
3322 }
3323 
3324 static struct ifbareq *
bridge_rt_table_copy_common(const char * bridge,u_int * ret_count)3325 bridge_rt_table_copy_common(const char * bridge, u_int * ret_count)
3326 {
3327 	struct ifbaconf         ifbac;
3328 	u_int                   len = 8 * 1024;
3329 	char *                  inbuf = NULL;
3330 	char *                  ninbuf;
3331 	int                     ret;
3332 	struct ifbareq *        rt_table = NULL;
3333 	int                     s;
3334 
3335 	s = inet_dgram_socket();
3336 
3337 	/*
3338 	 * BRDGRTS should work like other ioctl's where passing in NULL
3339 	 * for the buffer says "tell me how many there are". Unfortunately,
3340 	 * it doesn't so we have to pass in a buffer, then check that it
3341 	 * was too big.
3342 	 */
3343 	for (;;) {
3344 		ninbuf = realloc(inbuf, len);
3345 		T_QUIET;
3346 		T_ASSERT_NOTNULL((void *)ninbuf, "realloc %u", len);
3347 		ifbac.ifbac_len = len;
3348 		ifbac.ifbac_buf = inbuf = ninbuf;
3349 		ret = siocdrvspec(s, bridge, BRDGRTS,
3350 		    &ifbac, sizeof(ifbac), false);
3351 		T_QUIET;
3352 		T_ASSERT_POSIX_SUCCESS(ret, "%s %s", __func__, bridge);
3353 		if ((ifbac.ifbac_len + sizeof(*rt_table)) < len) {
3354 			/* we passed a buffer larger than what was required */
3355 			break;
3356 		}
3357 		len *= 2;
3358 	}
3359 	if (ifbac.ifbac_len == 0) {
3360 		free(ninbuf);
3361 		T_LOG("No bridge routing entries");
3362 		goto done;
3363 	}
3364 	*ret_count = ifbac.ifbac_len / sizeof(*rt_table);
3365 	rt_table = (struct ifbareq *)(void *)ninbuf;
3366 done:
3367 	if (rt_table == NULL) {
3368 		*ret_count = 0;
3369 	}
3370 	if (s >= 0) {
3371 		close(s);
3372 	}
3373 	return rt_table;
3374 }
3375 
3376 static struct ifbareq *
bridge_rt_table_copy(u_int * ret_count)3377 bridge_rt_table_copy(u_int * ret_count)
3378 {
3379 	return bridge_rt_table_copy_common(BRIDGE200, ret_count);
3380 }
3381 
3382 static void
bridge_rt_table_log(struct ifbareq * rt_table,u_int count)3383 bridge_rt_table_log(struct ifbareq *rt_table, u_int count)
3384 {
3385 	u_int                   i;
3386 	char                    ntoabuf[ETHER_NTOA_BUFSIZE];
3387 	struct ifbareq *        ifba;
3388 
3389 	for (i = 0, ifba = rt_table; i < count; i++, ifba++) {
3390 		ether_ntoa_buf((const ether_addr_t *)&ifba->ifba_dst,
3391 		    ntoabuf, sizeof(ntoabuf));
3392 		T_LOG("%s %s %lu", ifba->ifba_ifsname, ntoabuf,
3393 		    ifba->ifba_expire);
3394 	}
3395 	return;
3396 }
3397 
3398 static struct ifbrmne *
bridge_mac_nat_entries_copy_common(const char * bridge,u_int * ret_count)3399 bridge_mac_nat_entries_copy_common(const char * bridge, u_int * ret_count)
3400 {
3401 	char *                  buf = NULL;
3402 	u_int                   count = 0;
3403 	int                     err;
3404 	u_int                   i;
3405 	struct ifbrmnelist      mnl;
3406 	struct ifbrmne *        ret_list = NULL;
3407 	int                     s;
3408 	char *                  scan;
3409 
3410 
3411 	s = inet_dgram_socket();
3412 
3413 	/* find out how many there are */
3414 	bzero(&mnl, sizeof(mnl));
3415 	err = siocdrvspec(s, bridge, BRDGGMACNATLIST, &mnl, sizeof(mnl), false);
3416 	if (err != 0 && S_cleaning_up) {
3417 		T_LOG("BRDGGMACNATLIST %s failed %d", bridge, errno);
3418 		goto done;
3419 	}
3420 	T_QUIET;
3421 	T_ASSERT_POSIX_SUCCESS(err, "BRDGGMACNATLIST %s", bridge);
3422 	T_QUIET;
3423 	T_ASSERT_GE(mnl.ifbml_elsize, (uint16_t)sizeof(struct ifbrmne),
3424 	    "mac nat entry size %u minsize %u",
3425 	    mnl.ifbml_elsize, (u_int)sizeof(struct ifbrmne));
3426 	if (mnl.ifbml_len == 0) {
3427 		goto done;
3428 	}
3429 
3430 	/* call again with a buffer large enough to hold them */
3431 	buf = malloc(mnl.ifbml_len);
3432 	T_QUIET;
3433 	T_ASSERT_NOTNULL(buf, "mac nat entries buffer");
3434 	mnl.ifbml_buf = buf;
3435 	err = siocdrvspec(s, bridge, BRDGGMACNATLIST, &mnl, sizeof(mnl), false);
3436 	T_QUIET;
3437 	T_ASSERT_POSIX_SUCCESS(err, "BRDGGMACNATLIST %s", bridge);
3438 	count = mnl.ifbml_len / mnl.ifbml_elsize;
3439 	if (count == 0) {
3440 		goto done;
3441 	}
3442 	if (mnl.ifbml_elsize == sizeof(struct ifbrmne)) {
3443 		/* element size is expected size, no need to "right-size" it */
3444 		ret_list = (struct ifbrmne *)(void *)buf;
3445 		buf = NULL;
3446 		goto done;
3447 	}
3448 	/* element size is larger than we expect, create a "right-sized" array */
3449 	ret_list = malloc(count * sizeof(*ret_list));
3450 	T_QUIET;
3451 	T_ASSERT_NOTNULL(ret_list, "mac nat entries list");
3452 	for (i = 0, scan = buf; i < count; i++, scan += mnl.ifbml_elsize) {
3453 		struct ifbrmne *        ifbmne;
3454 
3455 		ifbmne = (struct ifbrmne *)(void *)scan;
3456 		ret_list[i] = *ifbmne;
3457 	}
3458 done:
3459 	if (s >= 0) {
3460 		close(s);
3461 	}
3462 	if (buf != NULL) {
3463 		free(buf);
3464 	}
3465 	*ret_count = count;
3466 	return ret_list;
3467 }
3468 
3469 static struct ifbrmne *
bridge_mac_nat_entries_copy(u_int * ret_count)3470 bridge_mac_nat_entries_copy(u_int * ret_count)
3471 {
3472 	return bridge_mac_nat_entries_copy_common(BRIDGE200, ret_count);
3473 }
3474 
3475 static void
bridge_mac_nat_entries_log(struct ifbrmne * entries,u_int count)3476 bridge_mac_nat_entries_log(struct ifbrmne * entries, u_int count)
3477 {
3478 	u_int                   i;
3479 	char                    ntoabuf[ETHER_NTOA_BUFSIZE];
3480 	char                    ntopbuf[INET6_ADDRSTRLEN];
3481 	struct ifbrmne *        scan;
3482 
3483 	for (i = 0, scan = entries; i < count; i++, scan++) {
3484 		ether_ntoa_buf((const ether_addr_t *)&scan->ifbmne_mac,
3485 		    ntoabuf, sizeof(ntoabuf));
3486 		inet_ntop(scan->ifbmne_af, &scan->ifbmne_ip,
3487 		    ntopbuf, sizeof(ntopbuf));
3488 		printf("%s %s %s %lu\n",
3489 		    scan->ifbmne_ifname, ntopbuf, ntoabuf,
3490 		    (unsigned long)scan->ifbmne_expire);
3491 	}
3492 	return;
3493 }
3494 
3495 /**
3496 ** Test Main
3497 **/
3498 static u_int                    S_n_ports;
3499 static switch_port_list_t       S_port_list;
3500 
3501 static void
3502 bridge_cleanup(const char * bridge, u_int n_ports, bool fail_on_error);
3503 
3504 static int fake_bsd_mode;
3505 static int fake_fcs;
3506 static int fake_trailer_length;
3507 
3508 static void
fake_set_trailers_fcs(bool enable)3509 fake_set_trailers_fcs(bool enable)
3510 {
3511 	int     error;
3512 	int     fcs;
3513 	size_t  len;
3514 	int     trailer_length;
3515 
3516 	if (enable) {
3517 		fcs = 1;
3518 		trailer_length = 28;
3519 	} else {
3520 		fcs = 0;
3521 		trailer_length = 0;
3522 	}
3523 
3524 	/* set fcs */
3525 	len = sizeof(fake_fcs);
3526 	error = sysctlbyname("net.link.fake.fcs",
3527 	    &fake_fcs, &len,
3528 	    &fcs, sizeof(fcs));
3529 	T_ASSERT_EQ(error, 0, "sysctl net.link.fake.fcs %d", fcs);
3530 
3531 	/* set trailer_length */
3532 	len = sizeof(fake_trailer_length);
3533 	error = sysctlbyname("net.link.fake.trailer_length",
3534 	    &fake_trailer_length, &len,
3535 	    &trailer_length, sizeof(trailer_length));
3536 	T_ASSERT_EQ(error, 0, "sysctl net.link.fake.trailer_length %d",
3537 	    trailer_length);
3538 }
3539 
3540 static void
fake_restore_trailers_fcs(void)3541 fake_restore_trailers_fcs(void)
3542 {
3543 	int     error;
3544 
3545 	error = sysctlbyname("net.link.fake.fcs",
3546 	    NULL, 0, &fake_fcs, sizeof(fake_fcs));
3547 	T_LOG("sysctl net.link.fake.fcs=%d returned %d", fake_fcs, error);
3548 	error = sysctlbyname("net.link.fake.trailer_length",
3549 	    NULL, 0, &fake_trailer_length, sizeof(fake_trailer_length));
3550 	T_LOG("sysctl net.link.fake.trailer_length=%d returned %d",
3551 	    fake_trailer_length, error);
3552 }
3553 
3554 static void
fake_set_bsd_mode(bool enable)3555 fake_set_bsd_mode(bool enable)
3556 {
3557 	int     error;
3558 	int     bsd_mode;
3559 	size_t  len;
3560 
3561 	bsd_mode = (enable) ? 1 : 0;
3562 	len = sizeof(fake_bsd_mode);
3563 	error = sysctlbyname("net.link.fake.bsd_mode",
3564 	    &fake_bsd_mode, &len,
3565 	    &bsd_mode, sizeof(bsd_mode));
3566 	T_ASSERT_EQ(error, 0, "sysctl net.link.fake.bsd_mode %d", bsd_mode);
3567 }
3568 
3569 static void
fake_restore_bsd_mode(void)3570 fake_restore_bsd_mode(void)
3571 {
3572 	int     error;
3573 
3574 	error = sysctlbyname("net.link.fake.bsd_mode",
3575 	    NULL, 0, &fake_bsd_mode, sizeof(fake_bsd_mode));
3576 	T_LOG("sysctl net.link.fake.bsd_mode=%d returned %d",
3577 	    fake_bsd_mode, error);
3578 }
3579 
3580 static void
cleanup_common(bool dump_table)3581 cleanup_common(bool dump_table)
3582 {
3583 	if (S_n_ports == 0) {
3584 		return;
3585 	}
3586 	S_cleaning_up = true;
3587 	if (S_port_list != NULL &&
3588 	    (S_port_list->mac_nat || dump_table)) {
3589 		switch_port_list_log(S_port_list);
3590 		if (S_port_list->mac_nat) {
3591 			switch_port_list_verify_mac_nat(S_port_list, true);
3592 		}
3593 		(void)switch_port_list_verify_rt_table(S_port_list, true);
3594 	}
3595 	if (S_debug) {
3596 		T_LOG("sleeping for 5 seconds\n");
3597 		sleep(5);
3598 	}
3599 	bridge_cleanup(BRIDGE200, S_n_ports, false);
3600 	return;
3601 }
3602 
3603 static void
cleanup(void)3604 cleanup(void)
3605 {
3606 	cleanup_common(true);
3607 	return;
3608 }
3609 
3610 static void
sigint_handler(__unused int sig)3611 sigint_handler(__unused int sig)
3612 {
3613 	cleanup_common(false);
3614 	signal(SIGINT, SIG_DFL);
3615 }
3616 
3617 static switch_port_list_t
bridge_setup(char * bridge,u_int n_ports,u_int num_addrs,uint8_t setup_flags)3618 bridge_setup(char * bridge, u_int n_ports, u_int num_addrs,
3619     uint8_t setup_flags)
3620 {
3621 	u_int                   addr_index = 1;
3622 	bool                    attach_stack;
3623 	bool                    checksum_offload;
3624 	errno_t                 err;
3625 	struct in_addr          ip;
3626 	switch_port_list_t      list = NULL;
3627 	bool                    mac_nat;
3628 	int                     rs = -1;
3629 	int                     s;
3630 	int                     s6 = -1;
3631 	uint8_t                 trailers;
3632 
3633 	attach_stack = (setup_flags & SETUP_FLAGS_ATTACH_STACK) != 0;
3634 	checksum_offload = (setup_flags & SETUP_FLAGS_CHECKSUM_OFFLOAD) != 0;
3635 	mac_nat = (setup_flags & SETUP_FLAGS_MAC_NAT) != 0;
3636 	trailers = (setup_flags & SETUP_FLAGS_TRAILERS) != 0;
3637 
3638 	S_n_ports = n_ports;
3639 	T_ATEND(cleanup);
3640 	T_SETUPBEGIN;
3641 	s = inet_dgram_socket();
3642 	if (attach_stack) {
3643 		rs = routing_socket();
3644 		s6 = inet6_dgram_socket();
3645 	}
3646 	err = ifnet_create(s, bridge);
3647 	if (err != 0) {
3648 		goto done;
3649 	}
3650 	bridge_if_index = (u_short)if_nametoindex(bridge);
3651 	if (attach_stack) {
3652 		ether_addr_t    bridge_mac;
3653 		char            ntopbuf_ip[INET6_ADDRSTRLEN];
3654 
3655 		ifnet_get_lladdr(s, bridge, &bridge_mac);
3656 
3657 		/* bridge gets .1 */
3658 		get_ipv4_address(0, addr_index, &bridge_ip_addr);
3659 		addr_index++;
3660 		siocaifaddr(s, bridge, bridge_ip_addr);
3661 		start_ipv6(s6, bridge);
3662 		get_ipv6_ll_address(&bridge_mac, &bridge_ipv6_addr);
3663 		inet_ntop(AF_INET6, &bridge_ipv6_addr, ntopbuf_ip,
3664 		    sizeof(ntopbuf_ip));
3665 		T_LOG("%s %s", bridge, ntopbuf_ip);
3666 	}
3667 	list = switch_port_list_alloc(n_ports, mac_nat);
3668 	fake_set_bsd_mode(true);
3669 	fake_set_trailers_fcs(trailers);
3670 	for (u_int i = 0; i < n_ports; i++) {
3671 		bool    do_mac_nat;
3672 		char    ifname[IFNAMSIZ];
3673 		u_short if_index = 0;
3674 		char    member_ifname[IFNAMSIZ];
3675 
3676 		snprintf(ifname, sizeof(ifname), "%s%d",
3677 		    FETH_NAME, i);
3678 		snprintf(member_ifname, sizeof(member_ifname), "%s%d",
3679 		    FETH_NAME, i + n_ports);
3680 		err = ifnet_create(s, ifname);
3681 		if (err != 0) {
3682 			goto done;
3683 		}
3684 		ifnet_attach_ip(s, ifname);
3685 		err = ifnet_create(s, member_ifname);
3686 		if (err != 0) {
3687 			goto done;
3688 		}
3689 		err = fake_set_peer(s, ifname, member_ifname);
3690 		if (err != 0) {
3691 			goto done;
3692 		}
3693 		if (attach_stack) {
3694 			/* members get .2, .3, etc. */
3695 			if_index = (u_short)if_nametoindex(ifname);
3696 			get_ipv4_address(0, addr_index, &ip);
3697 			siocaifaddr(s, ifname, ip);
3698 			add_scoped_subnet_route(rs, ifname, if_index, ip);
3699 			addr_index++;
3700 			start_ipv6(s6, ifname);
3701 		}
3702 		/* add the interface's peer to the bridge */
3703 		err = bridge_add_member(s, bridge, member_ifname);
3704 		if (err != 0) {
3705 			goto done;
3706 		}
3707 
3708 		do_mac_nat = (i == 0 && mac_nat);
3709 		if (do_mac_nat) {
3710 			/* enable MAC NAT on unit 0 */
3711 			err = bridge_member_modify_mac_nat(s, bridge,
3712 			    member_ifname,
3713 			    true);
3714 			if (err != 0) {
3715 				goto done;
3716 			}
3717 		} else if (checksum_offload) {
3718 			err = bridge_member_modify_checksum_offload(s, bridge,
3719 			    member_ifname,
3720 			    true);
3721 			if (err != 0) {
3722 				goto done;
3723 			}
3724 		}
3725 		/* we'll send/receive on the interface */
3726 		err = switch_port_list_add_port(s, list, i, ifname, if_index,
3727 		    member_ifname, num_addrs, do_mac_nat, &ip);
3728 		if (err != 0) {
3729 			goto done;
3730 		}
3731 	}
3732 done:
3733 	if (s >= 0) {
3734 		close(s);
3735 	}
3736 	if (s6 >= 0) {
3737 		close(s6);
3738 	}
3739 	if (err != 0 && list != NULL) {
3740 		switch_port_list_dealloc(list);
3741 		list = NULL;
3742 	}
3743 	T_SETUPEND;
3744 	return list;
3745 }
3746 
3747 static void
bridge_cleanup(const char * bridge,u_int n_ports,bool fail_on_error)3748 bridge_cleanup(const char * bridge, u_int n_ports, bool fail_on_error)
3749 {
3750 	int s;
3751 
3752 	s = inet_dgram_socket();
3753 	ifnet_destroy(s, bridge, fail_on_error);
3754 	for (u_int i = 0; i < n_ports; i++) {
3755 		char    ifname[IFNAMSIZ];
3756 		char    member_ifname[IFNAMSIZ];
3757 
3758 		snprintf(ifname, sizeof(ifname), "%s%d",
3759 		    FETH_NAME, i);
3760 		snprintf(member_ifname, sizeof(member_ifname), "%s%d",
3761 		    FETH_NAME, i + n_ports);
3762 		ifnet_destroy(s, ifname, fail_on_error);
3763 		ifnet_destroy(s, member_ifname, fail_on_error);
3764 	}
3765 	if (s >= 0) {
3766 		close(s);
3767 	}
3768 	S_n_ports = 0;
3769 	fake_restore_trailers_fcs();
3770 	fake_restore_bsd_mode();
3771 	return;
3772 }
3773 
3774 /*
3775  *  Basic Bridge Tests
3776  *
3777  *  Broadcast
3778  *  - two cases: actual broadcast, unknown ethernet
3779  *  - send broadcast packets
3780  *  - verify all received
3781  *  - check bridge rt list contains all expected MAC addresses
3782  *  - send unicast ARP packets
3783  *  - verify packets received only on expected port
3784  *
3785  *  MAC-NAT
3786  *  - verify ARP translation
3787  *  - verify IPv4 translation
3788  *  - verify DHCP broadcast bit conversion
3789  *  - verify IPv6 translation
3790  *  - verify ND6 translation (Neighbor, Router)
3791  *  - verify IPv4 subnet-local broadcast to MAC-NAT interface link-layer
3792  *    address arrives on all member links
3793  */
3794 
3795 static void
bridge_test(packet_validator_t validator,void * context,const ether_addr_t * dst_eaddr,uint8_t af,u_int n_ports,u_int num_addrs)3796 bridge_test(packet_validator_t validator,
3797     void * context,
3798     const ether_addr_t * dst_eaddr,
3799     uint8_t af, u_int n_ports, u_int num_addrs)
3800 {
3801 #if TARGET_OS_BRIDGE
3802 	T_SKIP("Test uses too much memory");
3803 #else /* TARGET_OS_BRIDGE */
3804 	switch_port_list_t port_list;
3805 
3806 	signal(SIGINT, sigint_handler);
3807 	port_list = bridge_setup(BRIDGE200, n_ports, num_addrs, 0);
3808 	if (port_list == NULL) {
3809 		T_FAIL("bridge_setup");
3810 		return;
3811 	}
3812 	S_port_list = port_list;
3813 	bridge_learning_test(port_list, af, validator, context, dst_eaddr);
3814 
3815 	//T_LOG("Sleeping for 5 seconds");
3816 	//sleep(5);
3817 	bridge_cleanup(BRIDGE200, n_ports, true);
3818 	switch_port_list_dealloc(port_list);
3819 	return;
3820 #endif /* TARGET_OS_BRIDGE */
3821 }
3822 
3823 static void
bridge_test_mac_nat_ipv4(u_int n_ports,u_int num_addrs)3824 bridge_test_mac_nat_ipv4(u_int n_ports, u_int num_addrs)
3825 {
3826 #if TARGET_OS_BRIDGE
3827 	T_SKIP("Test uses too much memory");
3828 #else /* TARGET_OS_BRIDGE */
3829 	switch_port_list_t port_list;
3830 
3831 	signal(SIGINT, sigint_handler);
3832 	port_list = bridge_setup(BRIDGE200, n_ports, num_addrs,
3833 	    SETUP_FLAGS_MAC_NAT);
3834 	if (port_list == NULL) {
3835 		T_FAIL("bridge_setup");
3836 		return;
3837 	}
3838 	S_port_list = port_list;
3839 
3840 	/* verify that IPv4 packets get translated when necessary */
3841 	mac_nat_test_ip(port_list, AF_INET);
3842 
3843 	/* verify the DHCP broadcast bit gets set appropriately */
3844 	mac_nat_test_dhcp(port_list, false);
3845 
3846 	/* verify that ARP packet gets translated when necessary */
3847 	mac_nat_test_arp_out(port_list);
3848 	mac_nat_test_arp_in(port_list);
3849 
3850 	/* verify IP broadcast to MAC-NAT interface link layer address */
3851 	mac_nat_test_dhcp(port_list, true);
3852 
3853 	if (S_debug) {
3854 		T_LOG("Sleeping for 5 seconds");
3855 		sleep(5);
3856 	}
3857 	bridge_cleanup(BRIDGE200, n_ports, true);
3858 	switch_port_list_dealloc(port_list);
3859 	return;
3860 #endif /* TARGET_OS_BRIDGE */
3861 }
3862 
3863 static void
bridge_test_mac_nat_ipv6(u_int n_ports,u_int num_addrs)3864 bridge_test_mac_nat_ipv6(u_int n_ports, u_int num_addrs)
3865 {
3866 #if TARGET_OS_BRIDGE
3867 	T_SKIP("Test uses too much memory");
3868 #else /* TARGET_OS_BRIDGE */
3869 	switch_port_list_t port_list;
3870 
3871 	signal(SIGINT, sigint_handler);
3872 	port_list = bridge_setup(BRIDGE200, n_ports, num_addrs,
3873 	    SETUP_FLAGS_MAC_NAT);
3874 	if (port_list == NULL) {
3875 		T_FAIL("bridge_setup");
3876 		return;
3877 	}
3878 	S_port_list = port_list;
3879 
3880 	/* verify that IPv6 packets get translated when necessary */
3881 	mac_nat_test_ip(port_list, AF_INET6);
3882 
3883 	/* verify that ND6 packet gets translated when necessary */
3884 	mac_nat_test_nd6_out(port_list);
3885 	if (S_debug) {
3886 		T_LOG("Sleeping for 5 seconds");
3887 		sleep(5);
3888 	}
3889 	bridge_cleanup(BRIDGE200, n_ports, true);
3890 	switch_port_list_dealloc(port_list);
3891 	return;
3892 #endif /* TARGET_OS_BRIDGE */
3893 }
3894 
3895 /*
3896  * Filter test utilities
3897  */
3898 static void
system_cmd(const char * cmd,bool fail_on_error)3899 system_cmd(const char *cmd, bool fail_on_error)
3900 {
3901 	pid_t pid = -1;
3902 	int exit_status = 0;
3903 	const char *argv[] = {
3904 		"/usr/local/bin/bash",
3905 		"-c",
3906 		cmd,
3907 		NULL
3908 	};
3909 
3910 	int rc = dt_launch_tool(&pid, (char **)(void *)argv, false, NULL, NULL);
3911 	T_QUIET;
3912 	T_ASSERT_EQ(rc, 0, "dt_launch_tool(%s) failed", cmd);
3913 
3914 	if (dt_waitpid(pid, &exit_status, NULL, 30)) {
3915 		T_QUIET;
3916 		T_ASSERT_MACH_SUCCESS(exit_status, "command(%s)", cmd);
3917 	} else {
3918 		if (fail_on_error) {
3919 			T_FAIL("dt_waitpid(%s) failed", cmd);
3920 		}
3921 	}
3922 }
3923 
3924 static bool
executable_is_present(const char * path)3925 executable_is_present(const char * path)
3926 {
3927 	struct stat statb = {};
3928 
3929 	return stat(path, &statb) == 0 && (statb.st_mode & S_IXUSR) != 0;
3930 }
3931 
3932 static void
cleanup_pf(void)3933 cleanup_pf(void)
3934 {
3935 	struct ifbrparam param;
3936 	int s = inet_dgram_socket();
3937 
3938 	system_cmd("pfctl -d", false);
3939 	system_cmd("pfctl -F all", false);
3940 
3941 	param.ifbrp_filter = 0;
3942 	siocdrvspec(s, BRIDGE200, BRDGSFILT,
3943 	    &param, sizeof(param), true);
3944 	return;
3945 }
3946 
3947 static void
block_all_traffic(bool input,const char * infname1,const char * infname2)3948 block_all_traffic(bool input, const char* infname1, const char* infname2)
3949 {
3950 	int s = inet_dgram_socket();
3951 	int ret;
3952 	struct ifbrparam param;
3953 	char command[512];
3954 	char *dir = input ? "in" : "out";
3955 
3956 	snprintf(command, sizeof(command), "echo \"block %s on %s all\nblock %s on %s all\n\" | pfctl -vvv -f -",
3957 	    dir, infname1, dir, infname2);
3958 	/* enable block all filter */
3959 	param.ifbrp_filter = IFBF_FILT_MEMBER | IFBF_FILT_ONLYIP;
3960 	ret = siocdrvspec(s, BRIDGE200, BRDGSFILT,
3961 	    &param, sizeof(param), true);
3962 	T_ASSERT_POSIX_SUCCESS(ret,
3963 	    "SIOCDRVSPEC(BRDGSFILT %s, 0x%x)",
3964 	    BRIDGE200, param.ifbrp_filter);
3965 	// ignore errors such that not having pf.os doesn't raise any issues
3966 	system_cmd(command, false);
3967 	system_cmd("pfctl -e", true);
3968 	system_cmd("pfctl -s all", true);
3969 }
3970 
3971 /*
3972  *  Basic bridge filter test
3973  *
3974  *  For both broadcast and unicast transfers ensure that data can
3975  *  be blocked using pf on the bridge
3976  */
3977 
3978 static void
filter_test(uint8_t af)3979 filter_test(uint8_t af)
3980 {
3981 #if TARGET_OS_BRIDGE
3982 	T_SKIP("pfctl isn't valid on this platform");
3983 #else /* TARGET_OS_BRIDGE */
3984 	switch_port_list_t port_list;
3985 	switch_port_t   port;
3986 	const u_int n_ports = 2;
3987 	u_int num_addrs = 1;
3988 	u_int i;
3989 	char ntoabuf[ETHER_NTOA_BUFSIZE];
3990 	union ifbrip dst_ip;
3991 	bool blocked = true;
3992 	bool input = true;
3993 	const char* ifnames[2];
3994 
3995 #define PFCTL_PATH      "/sbin/pfctl"
3996 	if (!executable_is_present(PFCTL_PATH)) {
3997 		T_SKIP("%s not present", PFCTL_PATH);
3998 		return;
3999 	}
4000 	signal(SIGINT, sigint_handler);
4001 
4002 	T_ATEND(cleanup);
4003 	T_ATEND(cleanup_pf);
4004 
4005 	port_list = bridge_setup(BRIDGE200, n_ports, num_addrs, 0);
4006 	if (port_list == NULL) {
4007 		T_FAIL("bridge_setup");
4008 		return;
4009 	}
4010 
4011 	ether_ntoa_buf(&ether_broadcast, ntoabuf, sizeof(ntoabuf));
4012 
4013 	S_port_list = port_list;
4014 	for (i = 0, port = port_list->list; i < port_list->count; i++, port++) {
4015 		ifnames[i] = port->member_ifname;
4016 	}
4017 
4018 	get_broadcast_ip_address(af, &dst_ip);
4019 	do {
4020 		do {
4021 			if (blocked) {
4022 				block_all_traffic(input, ifnames[0], ifnames[1]);
4023 			}
4024 			for (i = 0, port = port_list->list; i < port_list->count; i++, port++) {
4025 				if (S_debug) {
4026 					T_LOG("Sending on %s", port->ifname);
4027 				}
4028 				for (u_int j = 0; j < port->num_addrs; j++) {
4029 					uint32_t        generation;
4030 
4031 					generation = next_generation();
4032 					send_generation(port,
4033 					    af,
4034 					    j,
4035 					    &ether_broadcast,
4036 					    &dst_ip,
4037 					    generation);
4038 
4039 					/* receive across all ports */
4040 					check_receive_generation(port_list,
4041 					    af,
4042 					    generation,
4043 					    validate_broadcast_dhost,
4044 					    NULL);
4045 
4046 					/* ensure that every port saw the right amount of packets*/
4047 					if (blocked) {
4048 						check_received_count(port_list, port, 0);
4049 					} else {
4050 						check_received_count(port_list, port, 1);
4051 					}
4052 				}
4053 			}
4054 			T_PASS("%s broadcast %s %s", __func__, blocked ? "blocked" : "not blocked", input ? "input" : "output");
4055 			input = !input;
4056 			cleanup_pf();
4057 		} while (input == false && blocked);
4058 		blocked = !blocked;
4059 	} while (blocked == false);
4060 
4061 	do {
4062 		do {
4063 			if (blocked) {
4064 				block_all_traffic(input, ifnames[0], ifnames[1]);
4065 			}
4066 			for (i = 0, port = port_list->list; i < port_list->count; i++, port++) {
4067 				/* send unicast packets to every other port's MAC addresses */
4068 				unicast_send_all(port_list, af, port);
4069 
4070 				/* receive all of that generated traffic */
4071 				switch_port_list_check_receive(port_list, af, NULL, 0,
4072 				    validate_port_dhost, NULL);
4073 
4074 				/* ensure that every port saw the right amount of packets*/
4075 				if (blocked) {
4076 					check_received_count(port_list, port, 0);
4077 				} else {
4078 					check_received_count(port_list, port, 1);
4079 				}
4080 			}
4081 			T_PASS("%s unicast %s %s", __func__, blocked ? "blocked" : "not blocked", input ? "input" : "output");
4082 			input = !input;
4083 			cleanup_pf();
4084 		} while (input == false && blocked);
4085 		blocked = !blocked;
4086 	} while (blocked == false);
4087 
4088 	bridge_cleanup(BRIDGE200, n_ports, true);
4089 	switch_port_list_dealloc(port_list);
4090 	return;
4091 #endif /* TARGET_OS_BRIDGE */
4092 }
4093 
4094 /*
4095  * Bridge checksum offload tests
4096  */
4097 
4098 static const char *
ipproto_get_str(uint8_t proto)4099 ipproto_get_str(uint8_t proto)
4100 {
4101 	const char * str;
4102 
4103 	switch (proto) {
4104 	case IPPROTO_UDP:
4105 		str = "UDP";
4106 		break;
4107 	case IPPROTO_TCP:
4108 		str = "TCP";
4109 		break;
4110 	default:
4111 		str = "<?>";
4112 		break;
4113 	}
4114 	return str;
4115 }
4116 
4117 static void
test_traffic(uint8_t af,inet_address_t server,const char * server_ifname,int server_if_index,const char * client_ifname,int client_if_index)4118 test_traffic(uint8_t af, inet_address_t server,
4119     const char * server_ifname, int server_if_index,
4120     const char * client_ifname, int client_if_index)
4121 {
4122 	inet_endpoint   endpoint;
4123 	/* do TCP first because TCP is reliable and will populate ND cache */
4124 	uint8_t         protos[] = { IPPROTO_TCP, IPPROTO_UDP, 0 };
4125 
4126 	bzero(&endpoint, sizeof(endpoint));
4127 	endpoint.af = af;
4128 	endpoint.addr = *server;
4129 	endpoint.port = 1;
4130 	for (uint8_t * proto = protos; *proto != 0; proto++) {
4131 		bool    success;
4132 
4133 		T_LOG("%s: %s %s server %s client %s",
4134 		    __func__, af_get_str(af),
4135 		    ipproto_get_str(*proto),
4136 		    server_ifname, client_ifname);
4137 		endpoint.proto = *proto;
4138 		success = inet_transfer_local(&endpoint, server_if_index,
4139 		    client_if_index);
4140 		T_ASSERT_TRUE(success,
4141 		    "inet_transfer_local(): %s",
4142 		    inet_transfer_error_string());
4143 	}
4144 	return;
4145 }
4146 
4147 static void
test_traffic_for_af(switch_port_list_t ports,uint8_t af)4148 test_traffic_for_af(switch_port_list_t ports, uint8_t af)
4149 {
4150 	u_int           i;
4151 	inet_address    server;
4152 	int             server_if_index;
4153 	const char *    server_name;
4154 	switch_port_t   server_port;
4155 	switch_port_t   port;
4156 
4157 	/* bridge as server, each peer as client */
4158 	server_if_index = bridge_if_index;
4159 	server_name = BRIDGE200;
4160 	if (af == AF_INET) {
4161 		server.v4 = bridge_ip_addr;
4162 	} else {
4163 		server.v6 = bridge_ipv6_addr;
4164 	}
4165 	for (i = 0, port = ports->list; i < ports->count; i++, port++) {
4166 		test_traffic(af, &server, server_name,
4167 		    server_if_index, port->ifname, port->if_index);
4168 	}
4169 
4170 	/* peer 0 as server, other peers as client */
4171 	assert(ports->count > 0);
4172 	server_port = ports->list;
4173 	server_name = server_port->ifname;
4174 	server_if_index = server_port->if_index;
4175 	if (af == AF_INET) {
4176 		server.v4 = server_port->ip;
4177 	} else {
4178 		server.v6 = server_port->ip6;
4179 	}
4180 	for (i = 1, port = ports->list + 1; i < ports->count; i++, port++) {
4181 		test_traffic(af, &server, server_name,
4182 		    server_if_index, port->ifname, port->if_index);
4183 	}
4184 }
4185 
4186 static void
bridge_test_checksum_offload(u_int n_ports,uint8_t setup_flags)4187 bridge_test_checksum_offload(u_int n_ports, uint8_t setup_flags)
4188 {
4189 #if TARGET_OS_BRIDGE
4190 	T_SKIP("Test uses too much memory");
4191 #else /* TARGET_OS_BRIDGE */
4192 	switch_port_list_t port_list;
4193 
4194 	signal(SIGINT, sigint_handler);
4195 	port_list = bridge_setup(BRIDGE200, n_ports, 0,
4196 	    SETUP_FLAGS_CHECKSUM_OFFLOAD |
4197 	    SETUP_FLAGS_ATTACH_STACK | setup_flags);
4198 	if (port_list == NULL) {
4199 		T_FAIL("bridge_setup");
4200 		return;
4201 	}
4202 	test_traffic_for_af(port_list, AF_INET);
4203 	test_traffic_for_af(port_list, AF_INET6);
4204 	if (S_debug) {
4205 		T_LOG("Sleeping for 5 seconds");
4206 		sleep(5);
4207 	}
4208 	bridge_cleanup(BRIDGE200, n_ports, true);
4209 	switch_port_list_dealloc(port_list);
4210 	return;
4211 #endif /* TARGET_OS_BRIDGE */
4212 }
4213 
4214 T_DECL(if_bridge_bcast,
4215     "bridge broadcast IPv4",
4216     T_META_ASROOT(true))
4217 {
4218 	bridge_test(validate_broadcast_dhost, NULL, &ether_broadcast,
4219 	    AF_INET, 5, 1);
4220 }
4221 
4222 T_DECL(if_bridge_bcast_many,
4223     "bridge broadcast many IPv4",
4224     T_META_ASROOT(true))
4225 {
4226 	bridge_test(validate_broadcast_dhost, NULL, &ether_broadcast,
4227 	    AF_INET, 5, 20);
4228 }
4229 
4230 T_DECL(if_bridge_unknown,
4231     "bridge unknown host IPv4",
4232     T_META_ASROOT(true))
4233 {
4234 	bridge_test(validate_not_present_dhost, NULL, &ether_external,
4235 	    AF_INET, 5, 1);
4236 }
4237 
4238 T_DECL(if_bridge_bcast_v6,
4239     "bridge broadcast IPv6",
4240     T_META_ASROOT(true))
4241 {
4242 	bridge_test(validate_broadcast_dhost, NULL, &ether_broadcast,
4243 	    AF_INET6, 5, 1);
4244 }
4245 
4246 T_DECL(if_bridge_bcast_many_v6,
4247     "bridge broadcast many IPv6",
4248     T_META_ASROOT(true))
4249 {
4250 	bridge_test(validate_broadcast_dhost, NULL, &ether_broadcast,
4251 	    AF_INET6, 5, 20);
4252 }
4253 
4254 T_DECL(if_bridge_unknown_v6,
4255     "bridge unknown host IPv6",
4256     T_META_ASROOT(true))
4257 {
4258 	bridge_test(validate_not_present_dhost, NULL, &ether_external,
4259 	    AF_INET6, 5, 1);
4260 }
4261 
4262 T_DECL(if_bridge_mac_nat_ipv4,
4263     "bridge mac nat ipv4",
4264     T_META_ASROOT(true))
4265 {
4266 	bridge_test_mac_nat_ipv4(5, 10);
4267 }
4268 
4269 T_DECL(if_bridge_mac_nat_ipv6,
4270     "bridge mac nat ipv6",
4271     T_META_ASROOT(true))
4272 {
4273 	bridge_test_mac_nat_ipv6(5, 10);
4274 }
4275 
4276 T_DECL(if_bridge_filter_ipv4,
4277     "bridge filter ipv4",
4278     T_META_ASROOT(true))
4279 {
4280 	filter_test(AF_INET);
4281 }
4282 
4283 T_DECL(if_bridge_filter_ipv6,
4284     "bridge filter ipv6",
4285     T_META_ASROOT(true))
4286 {
4287 	filter_test(AF_INET6);
4288 }
4289 
4290 T_DECL(if_bridge_checksum_offload,
4291     "bridge checksum offload",
4292     T_META_ASROOT(true))
4293 {
4294 	bridge_test_checksum_offload(2, 0);
4295 }
4296 
4297 T_DECL(if_bridge_checksum_offload_trailers,
4298     "bridge checksum offload with trailers+fcs",
4299     T_META_ASROOT(true))
4300 {
4301 	bridge_test_checksum_offload(2, SETUP_FLAGS_TRAILERS);
4302 }
4303