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