varnishtest "Test ACLs"

server s1 {
	rxreq
	expect req.url == "/"
	txresp -body "1111\n"
	rxreq
	expect req.url == "foo"
	txresp -body "2222\n"
} -start

varnish v1 -arg "-p feature=+trace"

varnish v1 -errvcl {Name acl1 must have type 'acl'.} {
	sub vcl_recv {
		if (client.ip ~ acl1) {
			set req.url = "/";
		}
	}

	backend acl1 {
		.host = "${localhost}";
	}
}

varnish v1 -vcl+backend {
	sub vcl_recv {
		if (client.ip ~ acl1) {
			set req.url = "/";
		}
	}

	acl acl1 {
		"${localhost}";
	}

	sub vcl_deliver {
		set resp.http.acl = acl1;
	}
} -start

client c1 {
	txreq -url "foo"
	rxresp
	expect resp.status == 200
	expect resp.http.acl == acl1
} -run

varnish v1 -vcl+backend {
	acl acl1 {
		! "${localhost}";
		"0.0.0.0" / 0;
		"::" / 0;
	}

	sub vcl_recv {
		if (client.ip ~ acl1) {
			set req.url = "/";
		}
	}
	sub vcl_deliver {
		set resp.http.acl = acl1;
	}
}

client c1 -run

varnish v1 -cliok "param.set vsl_mask -VCL_trace"

varnish v1 -vcl {
	import std;

	backend dummy None;

	acl acl1 +log -pedantic {
		# bad notation (confusing)
		"1.2.3.4"/24;
		"1.2.3.66"/26;

		# more specific wins
		"1.4.4.0"/22;
		"1.3.4.0"/23;
		"1.3.5.0"/26;
		"1.3.6.0"/25;
		"1.3.6.128"/25;
		"1.3.0.0"/21;
		"1.4.7";
		"1.4.6.0"/24;
	}

	sub vcl_recv {
		return (synth(200));
	}
	sub t {
		if (std.ip(req.http.ip) ~ acl1) { }
	}
	sub vcl_synth {
		# variables would be nice, but not in core (yet?)
		set req.http.ip = "1.2.3.0";	call t;
		set req.http.ip = "1.2.3.63";	call t;
		set req.http.ip = "1.2.3.64";	call t;

		set req.http.ip = "1.3.4.255";	call t;
		set req.http.ip = "1.3.5.0";	call t;
		set req.http.ip = "1.3.5.255";	call t;
		set req.http.ip = "1.3.6.0";	call t;
		set req.http.ip = "1.3.6.140";	call t;
		set req.http.ip = "1.3.7.255";	call t;

		set req.http.ip = "1.4.5.255";	call t;
		set req.http.ip = "1.4.6.64";	call t;
		set req.http.ip = "1.4.7.64";	call t;
	}
}

logexpect l1 -v v1 -g raw {
	expect * 1007	ReqHeader	{^\Qip: 1.2.3.0\E$}
	expect 0 =	VCL_acl	{^\QMATCH acl1 "1.2.3.4"/24 fixed: 1.2.3.0/24\E$}
	expect 1 =	ReqHeader	{^\Qip: 1.2.3.63\E$}
	expect 0 =	VCL_acl	{^\QMATCH acl1 "1.2.3.4"/24 fixed: 1.2.3.0/24\E$}
	expect 1 =	ReqHeader	{^\Qip: 1.2.3.64\E$}
	expect 0 =	VCL_acl	{^\QMATCH acl1 "1.2.3.66"/26 fixed: 1.2.3.64/26\E$}

	expect 1 =	ReqHeader	{^\Qip: 1.3.4.255\E$}
	expect 0 =	VCL_acl	{^\QMATCH acl1 "1.3.4.0"/23\E$}
	expect 1 =	ReqHeader	{^\Qip: 1.3.5.0\E$}
	expect 0 =	VCL_acl	{^\QMATCH acl1 "1.3.5.0"/26\E$}
	expect 1 =	ReqHeader	{^\Qip: 1.3.5.255\E$}
	expect 0 =	VCL_acl	{^\QMATCH acl1 "1.3.4.0"/23\E$}
	expect 1 =	ReqHeader	{^\Qip: 1.3.6.0\E$}
	expect 0 =	VCL_acl	{^\QMATCH acl1 "1.3.6.0"/25\E$}
	expect 1 =	ReqHeader	{^\Qip: 1.3.6.140\E$}
	expect 0 =	VCL_acl	{^\QMATCH acl1 "1.3.6.128"/25\E$}
	expect 1 =	ReqHeader	{^\Qip: 1.3.7.255\E$}
	expect 0 =	VCL_acl	{^\QMATCH acl1 "1.3.0.0"/21\E$}

	expect 1 =	ReqHeader	{^\Qip: 1.4.5.255\E$}
	expect 0 =	VCL_acl	{^\QMATCH acl1 "1.4.4.0"/22\E$}
	expect 1 =	ReqHeader	{^\Qip: 1.4.6.64\E$}
	expect 0 =	VCL_acl	{^\QMATCH acl1 "1.4.6.0"/24\E$}
	expect 1 =	ReqHeader	{^\Qip: 1.4.7.64\E$}
	expect 0 =	VCL_acl	{^\QMATCH acl1 "1.4.7"\E$}
} -start

client c1 {
	txreq
	rxresp
} -run

logexpect l1 -wait

varnish v1 -errvcl {Non-zero bits in masked part} {
	import std;

	backend dummy None;

	acl acl1 +pedantic {
		"1.2.3.4"/24;
	}

	sub vcl_recv {
		if (client.ip ~ acl1) {}
	}
}
