# -*- shell-script -*-

def &input() = {
    chain "log_in_reserved" {
	LOG log-prefix 'INPUT-RESERVED: ';
	DROP;
    }

    chain INPUT {
	policy DROP;

	# allow local packets
	interface lo ACCEPT;

	# ignore monitor interfaces
	interface $monitor_interfaces DROP;

	# connection tracking
	mod state state (ESTABLISHED RELATED) ACCEPT;

	&input_rules();

	LOG log-prefix 'INPUT: ';
    }
}

def &output() = {
    chain OUTPUT {
	policy ACCEPT;

	# ignore monitor interfaces
	outerface $monitor_interfaces DROP;
    }
}

def &forward() = {
    chain FORWARD {
	policy DROP;

	# ignore monitor interfaces
	interface $monitor_interfaces DROP;
	outerface $monitor_interfaces DROP;

	&forward_rules();

	LOG log-prefix 'FORWARD: ';
    }
}


# IPv4
domain ip {
    def &input_rules() = {
	# block reserved addresses
	saddr ! 255.255.255.255 subchain "in_reserved" {
	    # allow DHCP requests
	    saddr 0.0.0.0 daddr 255.255.255.255 proto udp dport bootps RETURN;

	    saddr $reserved_ip jump "log_in_reserved";
	}

	# allow ping and traceroute
	proto icmp icmp-type echo-request ACCEPT;
	proto udp dport 33434:33534 REJECT;

	proto tcp mod multiport destination-ports $tcp_services ACCEPT;
	proto udp mod multiport destination-ports $udp_services ACCEPT;
	saddr $local_net_ip subchain "in_local_net" {
	    proto tcp mod multiport destination-ports $local_tcp_services ACCEPT;
	    proto udp mod multiport destination-ports $local_udp_services ACCEPT;
	}
	mod addrtype dst-type BROADCAST {
	    proto udp mod multiport destination-ports $bcast_udp_services ACCEPT;
	    proto udp dport ipp &cups_broadcast_policy();
	}

	daddr 224.0.0.0/4 proto igmp ACCEPT;
    }
    def &forward_rules() = {
	interface $forward_interfaces ACCEPT;
	outerface $forward_interfaces ACCEPT;
    }
    table filter {
	&input();
	&output();
	&forward();
    }
}

# IPv6
domain ip6 {
    chain "in_reserved" {
	saddr $nonreserved_except_ip6 jump "log_in_reserved";
	saddr $nonreserved_ip6 RETURN;
	jump "log_in_reserved";
    }

    def &input_rules() = {
	# allow non-reserved addresses
	jump "in_reserved";

	proto icmpv6  subchain "in_icmp" {
	    # allow ping and stateless autoconfiguration
	    icmpv6-type (echo-request neighbour-solicitation neighbour-advertisement) ACCEPT;
	    daddr FF02::1 icmpv6-type router-advertisement ACCEPT;
	    daddr FF02::2 icmpv6-type router-solicitation ACCEPT;
	    # allow Multicast Listener Discovery
	    #daddr FF00::/8 icmpv6-type 130 131 132 143 ACCEPT;
	}
	# allow traceroute
	proto udp dport 33434:33534 REJECT;

	proto tcp mod multiport destination-ports $tcp_services ACCEPT;
	proto udp mod multiport destination-ports $udp_services ACCEPT;
	saddr $local_net_ip6 subchain "in_local_net" {
	    proto tcp mod multiport destination-ports $local_tcp_services ACCEPT;
	    proto udp mod multiport destination-ports $local_udp_services ACCEPT;
	}
    }
    def &forward_rules() = {
	interface $forward_interfaces ACCEPT;
	outerface $forward_interfaces ACCEPT;
    }
    table filter {
	&input();
	&output();
	&forward();
    }
}
