Training courses

Kernel and Embedded Linux

Bootlin training courses

Embedded Linux, kernel,
Yocto Project, Buildroot, real-time,
graphics, boot time, debugging...

Bootlin logo

Elixir Cross Referencer

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
#	$NetBSD: t_ipsec_natt.sh,v 1.5 2020/06/05 03:24:58 knakahara Exp $
#
# Copyright (c) 2018 Internet Initiative Japan Inc.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
# 1. Redistributions of source code must retain the above copyright
#    notice, this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright
#    notice, this list of conditions and the following disclaimer in the
#    documentation and/or other materials provided with the distribution.
#
# THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
# ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
# PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
#

SOCK_LOCAL_A=unix://ipsec_natt_local_a
SOCK_LOCAL_B=unix://ipsec_natt_local_b
SOCK_NAT=unix://ipsec_natt_nat
SOCK_REMOTE=unix://ipsec_natt_remote
BUS_LOCAL=./bus_ipsec_natt_local
BUS_NAT=./bus_ipsec_natt_nat

DEBUG=${DEBUG:-false}

setup_servers()
{

	rump_server_crypto_start $SOCK_LOCAL_A netipsec ipsec
	rump_server_crypto_start $SOCK_LOCAL_B netipsec ipsec
	rump_server_npf_start $SOCK_NAT
	rump_server_crypto_start $SOCK_REMOTE netipsec ipsec
	rump_server_add_iface $SOCK_LOCAL_A shmif0 $BUS_LOCAL
	rump_server_add_iface $SOCK_LOCAL_B shmif0 $BUS_LOCAL
	rump_server_add_iface $SOCK_NAT shmif0 $BUS_LOCAL
	rump_server_add_iface $SOCK_NAT shmif1 $BUS_NAT
	rump_server_add_iface $SOCK_REMOTE shmif0 $BUS_NAT
}

setup_ipsecif()
{
	local sock=$1
	local ifid=$2
	local src_ip=$3
	local src_port=$4
	local dst_ip=$5
	local dst_port=$6
	local ipsecif_ip=$7
	local peer_ip=$8

	export RUMP_SERVER=$sock
	rump_server_add_iface $sock ipsec$ifid
	atf_check -s exit:0 rump.ifconfig ipsec$ifid link0 # enable NAT-T
	atf_check -s exit:0 rump.ifconfig ipsec$ifid tunnel ${src_ip},${src_port} ${dst_ip},${dst_port}
	atf_check -s exit:0 rump.ifconfig ipsec$ifid ${ipsecif_ip}/32
	atf_check -s exit:0 -o ignore \
	    rump.route -n add ${peer_ip}/32 $ipsecif_ip
}

add_sa()
{
	local sock=$1
	local proto=$2
	local algo_args="$3"
	local src_ip=$4
	local src_port=$5
	local dst_ip=$6
	local dst_port=$7
	local out_spi=$8
	local in_spi=$9
	local tmpfile=./tmp

	export RUMP_SERVER=$sock
	cat > $tmpfile <<-EOF
	add $src_ip [$src_port] $dst_ip [$dst_port] $proto $out_spi -m transport $algo_args;
	add $dst_ip [$dst_port] $src_ip [$src_port] $proto $in_spi -m transport $algo_args;
	EOF
	$DEBUG && cat $tmpfile
	atf_check -s exit:0 -o empty $HIJACKING setkey -c < $tmpfile
	# XXX it can be expired if $lifetime is very short
	#check_sa_entries $SOCK_LOCAL $ip_local $ip_remote
}

prepare_file()
{
	local file=$1
	local data="0123456789"

	touch $file
	for i in `seq 1 512`
	do
		echo $data >> $file
	done
}

build_npf_conf()
{
	local outfile=$1
	local localnet=$2

	cat > $outfile <<-EOF
	set bpf.jit off
	\$int_if = inet4(shmif0)
	\$ext_if = inet4(shmif1)
	\$localnet = { $localnet }
	map \$ext_if dynamic \$localnet -> \$ext_if
	group "external" on \$ext_if {
		pass stateful out final all
	}
	group "internal" on \$int_if {
		block in all
		pass in final from \$localnet
		pass out final all
	}
	group default {
		pass final on lo0 all
		block all
	}
	EOF
}

PIDSFILE=./terminator.pids
start_natt_terminator()
{
	local sock=$1
	local ip=$2
	local port=$3
	local pidsfile=$4
	local backup=$RUMP_SERVER
	local pid=
	local terminator="$(atf_get_srcdir)/../ipsec/natt_terminator"

	export RUMP_SERVER=$sock

	env LD_PRELOAD=/usr/lib/librumphijack.so \
	    $terminator $ip $port &
	pid=$!
	if [ ! -f $PIDSFILE ]; then
		touch $PIDSFILE
	fi
	echo $pid >> $PIDSFILE

	$DEBUG && rump.netstat -a -f inet

	export RUMP_SERVER=$backup

	sleep 1
}

stop_natt_terminators()
{
	local pid=

	if [ ! -f $PIDSFILE ]; then
		return
	fi

	for pid in $(cat $PIDSFILE); do
		kill -9 $pid
	done
	rm -f $PIDSFILE
}

check_ping_packets()
{
	local sock=$1
	local bus=$2
	local from_ip=$3
	local to_ip=$4

	local outfile=./out.ping

	extract_new_packets $bus > $outfile

	export RUMP_SERVER=$sock
	atf_check -s exit:0 -o ignore rump.ping -c 1 -n -w 3 $to_ip

	extract_new_packets $bus > $outfile
	$DEBUG && cat $outfile
	atf_check -s exit:0 \
	    -o match:"$from_ip > $to_ip: ICMP echo request" \
	    cat $outfile
	atf_check -s exit:0 \
	    -o match:"$to_ip > $from_ip: ICMP echo reply" \
	    cat $outfile
}

check_ping_packets_over_ipsecif()
{
	local sock=$1
	local bus=$2
	local to_ip=$3
	local nat_from_ip=$4
	local nat_from_port=$5
	local nat_to_ip=$6
	local nat_to_port=$7

	local outfile=./out.ping_over_ipsecif

	extract_new_packets $bus > $outfile

	export RUMP_SERVER=$sock
	atf_check -s exit:0 -o ignore rump.ping -c 1 -n -w 7 $to_ip

	# Check both ports and UDP encapsulation
	extract_new_packets $bus > $outfile
	$DEBUG && cat $outfile
	atf_check -s exit:0 \
	    -o match:"${nat_from_ip}\.$nat_from_port > ${nat_to_ip}\.${nat_to_port}: UDP-encap" \
	    cat $outfile
	atf_check -s exit:0 \
	    -o match:"${nat_to_ip}\.${nat_to_port} > ${nat_from_ip}\.${nat_from_port}: UDP-encap" \
	    cat $outfile
}

check_tcp_com_prepare()
{
	local server_sock=$1
	local client_sock=$2
	local bus=$3
	local to_ip=$4
	local nat_from_ip=$5
	local nat_to_ip=$6

	local outfile=./out.prepare
	local file_send=./file.send.prepare
	local file_recv=./file.recv.prepare

	extract_new_packets $bus > $outfile

	start_nc_server $server_sock 4501 $file_recv ipv4

	prepare_file $file_send
	export RUMP_SERVER=$client_sock
	atf_check -s exit:0 $HIJACKING nc -w 3 $to_ip 4501 < $file_send
	atf_check -s exit:0 diff -q $file_send $file_recv
	extract_new_packets $bus > $outfile
	$DEBUG && cat $outfile
	atf_check -s exit:0 \
	    -o match:"${nat_from_ip}\.[0-9]+ > ${nat_to_ip}\.4501" \
	    cat $outfile
	atf_check -s exit:0 \
	    -o match:"${nat_to_ip}\.4501 > ${nat_from_ip}\.[0-9]+" \
	    cat $outfile

	stop_nc_server
}

check_tcp_com_over_ipsecif()
{
	local server_sock=$1
	local client_sock=$2
	local bus=$3
	local to_ip=$4
	local nat_from_ip=$5
	local nat_from_port=$6
	local nat_to_ip=$7
	local nat_to_port=$8

	local outfile=./out.ipsecif
	local file_send=./file.send.ipsecif
	local file_recv=./file.recv.ipsecif

	extract_new_packets $bus > $outfile

	start_nc_server $server_sock 4501 $file_recv ipv4
	prepare_file $file_send
	export RUMP_SERVER=$client_sock
	atf_check -s exit:0 -o ignore $HIJACKING nc -w 7 $to_ip 4501 < $file_send
	atf_check -s exit:0 diff -q $file_send $file_recv
	stop_nc_server

	# Check both ports and UDP encapsulation
	extract_new_packets $bus > $outfile
	$DEBUG && cat $outfile
	atf_check -s exit:0 \
	    -o match:"${nat_from_ip}\.$nat_from_port > ${nat_to_ip}\.${nat_to_port}: UDP-encap" \
	    cat $outfile
	atf_check -s exit:0 \
	    -o match:"${nat_to_ip}\.${nat_to_port} > ${nat_from_ip}\.${nat_from_port}: UDP-encap" \
	    cat $outfile
}

test_ipsecif_natt_transport()
{
	local algo=$1
	local ip_local_a=192.168.0.2
	local ip_local_b=192.168.0.3
	local ip_nat_local=192.168.0.1
	local ip_nat_remote=10.0.0.1
	local ip_remote=10.0.0.2
	local subnet_local=192.168.0.0
	local ip_local_ipsecif_a=172.16.100.1
	local ip_local_ipsecif_b=172.16.110.1
	local ip_remote_ipsecif_a=172.16.10.1
	local ip_remote_ipsecif_b=172.16.11.1

	local npffile=./npf.conf
	local file_send=./file.send
	local algo_args="$(generate_algo_args esp-udp $algo)"
	local pid= port_a=  port_b=

	setup_servers

	export RUMP_SERVER=$SOCK_LOCAL_A
	atf_check -s exit:0 rump.sysctl -q -w net.inet.ip.dad_count=0
	atf_check -s exit:0 rump.ifconfig shmif0 $ip_local_a/24
	atf_check -s exit:0 -o ignore \
	    rump.route -n add default $ip_nat_local

	export RUMP_SERVER=$SOCK_LOCAL_B
	atf_check -s exit:0 rump.sysctl -q -w net.inet.ip.dad_count=0
	atf_check -s exit:0 rump.ifconfig shmif0 $ip_local_b/24
	atf_check -s exit:0 -o ignore \
	    rump.route -n add default $ip_nat_local

	export RUMP_SERVER=$SOCK_NAT
	atf_check -s exit:0 rump.sysctl -q -w net.inet.ip.dad_count=0
	atf_check -s exit:0 rump.ifconfig shmif0 $ip_nat_local/24
	atf_check -s exit:0 rump.ifconfig shmif1 $ip_nat_remote/24
	atf_check -s exit:0 rump.sysctl -q -w net.inet.ip.forwarding=1

	export RUMP_SERVER=$SOCK_REMOTE
	atf_check -s exit:0 rump.sysctl -q -w net.inet.ip.dad_count=0
	atf_check -s exit:0 rump.ifconfig shmif0 $ip_remote/24
	atf_check -s exit:0 -o ignore \
	    rump.route -n add -net $subnet_local $ip_nat_remote

	# There is no NAT/NAPT. ping should just work.
	check_ping_packets $SOCK_LOCAL_A $BUS_NAT $ip_local_a $ip_remote
	check_ping_packets $SOCK_LOCAL_B $BUS_NAT $ip_local_b $ip_remote

	# Setup an NAPT with npf
	build_npf_conf $npffile "$subnet_local/24"

	export RUMP_SERVER=$SOCK_NAT
	atf_check -s exit:0 $HIJACKING_NPF npfctl reload $npffile
	atf_check -s exit:0 $HIJACKING_NPF npfctl start
	$DEBUG && ${HIJACKING},"blanket=/dev/npf" npfctl show

	# There is an NAPT. ping works but source IP/port are translated
	check_ping_packets $SOCK_LOCAL_A $BUS_NAT $ip_nat_remote $ip_remote
	check_ping_packets $SOCK_LOCAL_B $BUS_NAT $ip_nat_remote $ip_remote

	# Try TCP communications just in case
	check_tcp_com_prepare $SOCK_REMOTE $SOCK_LOCAL_A $BUS_NAT \
			      $ip_remote $ip_nat_remote $ip_remote
	check_tcp_com_prepare $SOCK_REMOTE $SOCK_LOCAL_B $BUS_NAT \
			      $ip_remote $ip_nat_remote $ip_remote

	# Launch a nc server as a terminator of NAT-T on outside the NAPT
	start_natt_terminator $SOCK_REMOTE $ip_remote 4500
	echo zzz > $file_send

	#################### Test for primary ipsecif(4) NAT-T.

	export RUMP_SERVER=$SOCK_LOCAL_A
	# Send a UDP packet to the remote server at port 4500 from the local
	# host of port 4500. This makes a mapping on the NAPT between them
	atf_check -s exit:0 $HIJACKING \
	    nc -u -w 3 -p 4500 $ip_remote 4500 < $file_send
	# Launch a nc server as a terminator of NAT-T on inside the NAPT,
	# taking over port 4500 of the local host.
	start_natt_terminator $SOCK_LOCAL_A $ip_local_a 4500

	# We need to keep the servers for NAT-T

	export RUMP_SERVER=$SOCK_LOCAL_A
	$DEBUG && rump.netstat -na -f inet
	export RUMP_SERVER=$SOCK_REMOTE
	$DEBUG && rump.netstat -na -f inet

	# Get a translated port number from 4500 on the NAPT
	export RUMP_SERVER=$SOCK_NAT
	$DEBUG && $HIJACKING_NPF npfctl list
	#          192.168.0.2:4500 10.0.0.2:4500  via shmif1:65248
	port_a=$(get_natt_port $ip_local_a $ip_nat_remote)
	$DEBUG && echo port_a=$port_a
	if [ -z "$port_a" ]; then
		atf_fail "Failed to get a translated port on NAPT"
	fi

	# Setup ESP-UDP ipsecif(4) for first client under NAPT
	setup_ipsecif $SOCK_LOCAL_A 0 $ip_local_a 4500 $ip_remote 4500 \
		      $ip_local_ipsecif_a $ip_remote_ipsecif_a
	setup_ipsecif $SOCK_REMOTE 0 $ip_remote 4500 $ip_nat_remote $port_a \
		      $ip_remote_ipsecif_a $ip_local_ipsecif_a

	add_sa $SOCK_LOCAL_A "esp-udp" "$algo_args" \
	       $ip_local_a 4500 $ip_remote 4500 10000 10001
	add_sa $SOCK_REMOTE "esp-udp" "$algo_args" \
	       $ip_remote 4500 $ip_nat_remote $port_a 10001 10000

	export RUMP_SERVER=$SOCK_LOCAL_A
	# ping should still work
	atf_check -s exit:0 -o ignore rump.ping -c 1 -n -w 3 $ip_remote

	# Try ping over the ESP-UDP ipsecif(4)
	check_ping_packets_over_ipsecif $SOCK_LOCAL_A $BUS_NAT \
					 $ip_remote_ipsecif_a $ip_nat_remote $port_a $ip_remote 4500

	# Try TCP communications over the ESP-UDP ipsecif(4)
	check_tcp_com_over_ipsecif $SOCK_REMOTE $SOCK_LOCAL_A $BUS_NAT \
				   $ip_remote_ipsecif_a $ip_nat_remote $port_a $ip_remote 4500

	#################### Test for secondary ipsecif(4) NAT-T.

	export RUMP_SERVER=$SOCK_REMOTE
	$HIJACKING setkey -D
	$HIJACKING setkey -DP

	export RUMP_SERVER=$SOCK_LOCAL_B
	# Send a UDP packet to the remote server at port 4500 from the local
	# host of port 4500. This makes a mapping on the NAPT between them
	atf_check -s exit:0 $HIJACKING \
	    nc -u -w 3 -p 4500 $ip_remote 4500 < $file_send
	# Launch a nc server as a terminator of NAT-T on inside the NAPT,
	# taking over port 4500 of the local host.
	start_natt_terminator $SOCK_LOCAL_B $ip_local_b 4500

	# We need to keep the servers for NAT-T

	export RUMP_SERVER=$SOCK_LOCAL_B
	$DEBUG && rump.netstat -na -f inet
	export RUMP_SERVER=$SOCK_REMOTE
	$DEBUG && rump.netstat -na -f inet

	# Get a translated port number from 4500 on the NAPT
	export RUMP_SERVER=$SOCK_NAT
	$DEBUG && $HIJACKING_NPF npfctl list
	#          192.168.0.2:4500 10.0.0.2:4500  via shmif1:65248
	port_b=$(get_natt_port $ip_local_b $ip_nat_remote)
	$DEBUG && echo port_b=$port_b
	if [ -z "$port_b" ]; then
		atf_fail "Failed to get a translated port on NAPT"
	fi

	# Setup ESP-UDP ipsecif(4) for first client under NAPT
	setup_ipsecif $SOCK_LOCAL_B 0 $ip_local_b 4500 $ip_remote 4500 \
		      $ip_local_ipsecif_b $ip_remote_ipsecif_b
	setup_ipsecif $SOCK_REMOTE 1 $ip_remote 4500 $ip_nat_remote $port_b \
		      $ip_remote_ipsecif_b $ip_local_ipsecif_b

	check_ping_packets_over_ipsecif $SOCK_LOCAL_A $BUS_NAT \
					 $ip_remote_ipsecif_a $ip_nat_remote $port_a $ip_remote 4500

	add_sa $SOCK_LOCAL_B "esp-udp" "$algo_args" \
	       $ip_local_b 4500 $ip_remote 4500 11000 11001
	add_sa $SOCK_REMOTE "esp-udp" "$algo_args" \
	       $ip_remote 4500 $ip_nat_remote $port_b 11001 11000

	export RUMP_SERVER=$SOCK_LOCAL_B
	# ping should still work
	atf_check -s exit:0 -o ignore rump.ping -c 1 -n -w 3 $ip_remote

	# Try ping over the ESP-UDP ipsecif(4)
	check_ping_packets_over_ipsecif $SOCK_LOCAL_B $BUS_NAT \
					 $ip_remote_ipsecif_b $ip_nat_remote $port_b $ip_remote 4500


	# Try TCP communications over the ESP-UDP ipsecif(4)
	check_tcp_com_over_ipsecif $SOCK_REMOTE $SOCK_LOCAL_B $BUS_NAT \
				   $ip_remote_ipsecif_b $ip_nat_remote $port_b $ip_remote 4500

	# Try ping over the ESP-UDP ipsecif(4) for primary again
	check_ping_packets_over_ipsecif $SOCK_LOCAL_A $BUS_NAT \
					 $ip_remote_ipsecif_a $ip_nat_remote $port_a $ip_remote 4500

	# Try TCP communications over the ESP-UDP ipsecif(4) for primary again
	check_tcp_com_over_ipsecif $SOCK_REMOTE $SOCK_LOCAL_A $BUS_NAT \
				   $ip_remote_ipsecif_a $ip_nat_remote $port_a $ip_remote 4500

	# Kill the NAT-T terminator
	stop_natt_terminators
}

add_test_ipsecif_natt_transport()
{
	local algo=$1
	local _algo=$(echo $algo | sed 's/-//g')
	local name= desc=

	desc="Test ipsecif(4) NAT-T ($algo)"
	name="ipsecif_natt_transport_${_algo}"

	atf_test_case ${name} cleanup
	eval "
	    ${name}_head() {
	        atf_set descr \"$desc\"
	        atf_set require.progs rump_server setkey nc
	    }
	    ${name}_body() {
	        test_ipsecif_natt_transport $algo
	        rump_server_destroy_ifaces
	    }
	    ${name}_cleanup() {
		stop_nc_server
		stop_natt_terminators
	        \$DEBUG && dump
	        cleanup
	    }
	"
	atf_add_test_case ${name}
}

atf_init_test_cases()
{
	local algo=

	for algo in $ESP_ENCRYPTION_ALGORITHMS_MINIMUM; do
		add_test_ipsecif_natt_transport $algo
	done
}