"""
ICMPv6 plays an important role in IPv6 connectivity.

RFC 4890 gives some recommendations, which are in this rule file.
"""

# IPv6 recommended ICMPv6 filters (RFC 4890)
add_chain("rfc4890")
ip6tables("INPUT", "-p icmpv6 -j rfc4890")
ip6tables("OUTPUT", "-p icmpv6 -j rfc4890")
# RFC 4890, 4.4.1 "Must not be dropped" local configuration
# RFC 4890, 4.4.2 "Should not be dropped" local configuration
ip6tables("rfc4890", "-p icmpv6 --icmpv6-type destination-unreachable -j ACCEPT")
ip6tables("rfc4890", "-p icmpv6 --icmpv6-type packet-too-big -j ACCEPT")
ip6tables("rfc4890", "-p icmpv6 --icmpv6-type time-exceeded -j ACCEPT")
ip6tables("rfc4890", "-p icmpv6 --icmpv6-type parameter-problem -j ACCEPT")
ip6tables("rfc4890", "-p icmpv6 --icmpv6-type echo-request -j ACCEPT")
ip6tables("rfc4890", "-p icmpv6 --icmpv6-type echo-reply -j ACCEPT")

ip6tables("rfc4890", "-p icmpv6 --icmpv6-type router-solicitation -j ACCEPT")
ip6tables("rfc4890", "-p icmpv6 --icmpv6-type router-advertisement -j ACCEPT")
ip6tables("rfc4890", "-p icmpv6 --icmpv6-type neighbour-solicitation -j ACCEPT")
ip6tables("rfc4890", "-p icmpv6 --icmpv6-type neighbour-advertisement -j ACCEPT")
ip6tables("rfc4890", "-p icmpv6 --icmpv6-type 141 -j ACCEPT") # inverse neighbor solicitation
ip6tables("rfc4890", "-p icmpv6 --icmpv6-type 142 -j ACCEPT") # inverse neighbor advertisement

ip6tables("rfc4890", "-p icmpv6 --icmpv6-type 130 -j ACCEPT") # listener query
ip6tables("rfc4890", "-p icmpv6 --icmpv6-type 131 -j ACCEPT") # listener report
ip6tables("rfc4890", "-p icmpv6 --icmpv6-type 132 -j ACCEPT") # listener done
ip6tables("rfc4890", "-p icmpv6 --icmpv6-type 143 -j ACCEPT") # listener report v2
ip6tables("rfc4890", "-p icmpv6 --icmpv6-type 148 -j ACCEPT") # cert path solicitation
ip6tables("rfc4890", "-p icmpv6 --icmpv6-type 149 -j ACCEPT") # cert path advertisement
ip6tables("rfc4890", "-p icmpv6 --icmpv6-type 151 -j ACCEPT") # multicast advertisement
ip6tables("rfc4890", "-p icmpv6 --icmpv6-type 152 -j ACCEPT") # multicast solicitation
ip6tables("rfc4890", "-p icmpv6 --icmpv6-type 153 -j ACCEPT") # multicast termination

### 4.4.4: for which a policy should be defined
# We do NOT include these, but leave it to the administator to define
# policy, as suggested by RFC 4890:
# redirect (137), node information query (139,140), unallocated

### 4.4.5: should be dropped
ip6tables("rfc4890", "-p icmpv6 --icmpv6-type 100 -j DROP") # experimental
ip6tables("rfc4890", "-p icmpv6 --icmpv6-type 101 -j DROP") # experimental
ip6tables("rfc4890", "-p icmpv6 --icmpv6-type 200 -j DROP") # experimental
ip6tables("rfc4890", "-p icmpv6 --icmpv6-type 201 -j DROP") # experimental
ip6tables("rfc4890", "-p icmpv6 --icmpv6-type 127 -j DROP") # future extensions
ip6tables("rfc4890", "-p icmpv6 --icmpv6-type 255 -j DROP") # future extensions

### ICMPv6 forwarding rules
add_chain("rfc4890f")
ip6tables("FORWARD", "-p icmpv6 -j rfc4890f")
# RFC 4890, 4.3.1 "Must not be dropped" transit
# RFC 4890, 4.3.2 "Normally should not be dropped" transit
ip6tables("rfc4890f", "-p icmpv6 --icmpv6-type destination-unreachable -j ACCEPT")
ip6tables("rfc4890f", "-p icmpv6 --icmpv6-type packet-too-big -j ACCEPT")
ip6tables("rfc4890f", "-p icmpv6 --icmpv6-type time-exceeded -j ACCEPT")
ip6tables("rfc4890f", "-p icmpv6 --icmpv6-type parameter-problem -j ACCEPT")
ip6tables("rfc4890f", "-p icmpv6 --icmpv6-type echo-request -j ACCEPT")
ip6tables("rfc4890f", "-p icmpv6 --icmpv6-type echo-reply -j ACCEPT")
ip6tables("rfc4890f", "-p icmpv6 --icmpv6-type 144 -j ACCEPT")
ip6tables("rfc4890f", "-p icmpv6 --icmpv6-type 145 -j ACCEPT")
ip6tables("rfc4890f", "-p icmpv6 --icmpv6-type 146 -j ACCEPT")
ip6tables("rfc4890f", "-p icmpv6 --icmpv6-type 147 -j ACCEPT")

# RFC 4890, 4.3.3 "Will be dropped anyway, no attention needed"
# We could explicitly drop them, but leave it to the kernel to behave

### 4.3.4: for which a policy should be defined
# We do NOT include these, but leave it to the administator to define
# policy, as suggested by RFC 4890:
# seamoby (150), unallocated (5-99, 102-126)

### 4.3.5: should be dropped
ip6tables("rfc4890f", "-p icmpv6 --icmpv6-type 139 -j DROP") # node information query
ip6tables("rfc4890f", "-p icmpv6 --icmpv6-type 140 -j DROP") # node information response
ip6tables("rfc4890f", "-p icmpv6 --icmpv6-type 138 -j DROP") # router renumbering
ip6tables("rfc4890f", "-p icmpv6 --icmpv6-type 101 -j DROP") # experimental
ip6tables("rfc4890f", "-p icmpv6 --icmpv6-type 200 -j DROP") # experimental
ip6tables("rfc4890f", "-p icmpv6 --icmpv6-type 201 -j DROP") # experimental
ip6tables("rfc4890f", "-p icmpv6 --icmpv6-type 127 -j DROP") # future extensions
ip6tables("rfc4890f", "-p icmpv6 --icmpv6-type 255 -j DROP") # future extensions

