# Copyright 2020 syzkaller project authors. All rights reserved.
# Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.

include <linux/net.h>
include <uapi/linux/netlink.h>
include <uapi/linux/netfilter.h>
include <uapi/linux/netfilter/nfnetlink.h>
include <uapi/linux/netfilter/nfnetlink_conntrack.h>
include <uapi/linux/netfilter/nf_conntrack_common.h>
include <net/netfilter/nf_internals.h>

type msghdr_conntrack[CMD, POLICY] msghdr_netlink[netlink_msg_netfilter_t[NFNL_SUBSYS_CTNETLINK, CMD, POLICY]]

type conntrack_id int32be[0:4]
type conntrack_zone int16be[0:4]

sendmsg$IPCTNL_MSG_CT_NEW(fd sock_nl_netfilter, msg ptr[in, msghdr_conntrack[IPCTNL_MSG_CT_NEW, ct_nla_policy]], f flags[send_flags])
sendmsg$IPCTNL_MSG_CT_GET(fd sock_nl_netfilter, msg ptr[in, msghdr_conntrack[IPCTNL_MSG_CT_GET, ct_nla_policy]], f flags[send_flags])
sendmsg$IPCTNL_MSG_CT_DELETE(fd sock_nl_netfilter, msg ptr[in, msghdr_conntrack[IPCTNL_MSG_CT_DELETE, ct_nla_policy]], f flags[send_flags])
sendmsg$IPCTNL_MSG_CT_GET_CTRZERO(fd sock_nl_netfilter, msg ptr[in, msghdr_conntrack[IPCTNL_MSG_CT_GET_CTRZERO, ct_nla_policy]], f flags[send_flags])
sendmsg$IPCTNL_MSG_CT_GET_STATS_CPU(fd sock_nl_netfilter, msg ptr[in, msghdr_conntrack[IPCTNL_MSG_CT_GET_STATS_CPU, void]], f flags[send_flags])
sendmsg$IPCTNL_MSG_CT_GET_STATS(fd sock_nl_netfilter, msg ptr[in, msghdr_conntrack[IPCTNL_MSG_CT_GET_STATS, void]], f flags[send_flags])
sendmsg$IPCTNL_MSG_CT_GET_DYING(fd sock_nl_netfilter, msg ptr[in, msghdr_conntrack[IPCTNL_MSG_CT_GET_DYING, void]], f flags[send_flags])
sendmsg$IPCTNL_MSG_CT_GET_UNCONFIRMED(fd sock_nl_netfilter, msg ptr[in, msghdr_conntrack[IPCTNL_MSG_CT_GET_UNCONFIRMED, void]], f flags[send_flags])

ct_nla_policy [
	CTA_TUPLE_ORIG		nlnest[CTA_TUPLE_ORIG, array[tuple_nla_policy]]
	CTA_TUPLE_REPLY		nlnest[CTA_TUPLE_REPLY, array[tuple_nla_policy]]
	CTA_STATUS		nlnetw[CTA_STATUS, flags[ip_conntrack_status, int32be]]
	CTA_PROTOINFO		nlnest[CTA_PROTOINFO, protoinfo_policy]
# The policy may also contain CTA_HELP_INFO, but I don't see any of the helpers use it.
	CTA_HELP		nlnest[CTA_HELP, nlattr[CTA_HELP_NAME, string[xt_helper_names]]]
	CTA_NAT_SRC		nlnest[CTA_NAT_SRC, array[nat_nla_policy]]
	CTA_TIMEOUT		nlnetw[CTA_TIMEOUT, int32be]
	CTA_MARK		nlnetw[CTA_MARK, int32be]
	CTA_ID			nlnetw[CTA_ID, conntrack_id]
	CTA_NAT_DST		nlnest[CTA_NAT_DST, array[nat_nla_policy]]
	CTA_TUPLE_MASTER	nlnest[CTA_TUPLE_MASTER, array[tuple_nla_policy]]
	CTA_ZONE		nlnetw[CTA_ZONE, conntrack_zone]
	CTA_MARK_MASK		nlnetw[CTA_MARK_MASK, conntrack_id]
	CTA_LABELS		nlnetw[CTA_LABELS, array[int32be]]
# NEED: CTA_LABELS_MASK should be of the same size as CTA_LABELS.
	CTA_LABELS_MASK		nlattr[CTA_LABELS_MASK, array[int32be]]
	CTA_SEQ_ADJ_ORIG	nlnest[CTA_SEQ_ADJ_ORIG, array[seqadj_policy]]
	CTA_SEQ_ADJ_REPLY	nlnest[CTA_SEQ_ADJ_REPLY, array[seqadj_policy]]
	CTA_SYNPROXY		nlnest[CTA_SYNPROXY, array[synproxy_policy]]
	CTA_FILTER		nlnest[CTA_FILTER, array[cta_filter_nla_policy]]
	CTA_STATUS_MASK		nlnetw[CTA_STATUS_MASK, int32be]
] [varlen]

seqadj_policy [
	CTA_SEQADJ_CORRECTION_POS	nlnetw[CTA_SEQADJ_CORRECTION_POS, int32be]
	CTA_SEQADJ_OFFSET_BEFORE	nlnetw[CTA_SEQADJ_OFFSET_BEFORE, int32be]
	CTA_SEQADJ_OFFSET_AFTER		nlnetw[CTA_SEQADJ_OFFSET_AFTER, int32be]
] [varlen]

tuple_nla_policy [
	CTA_TUPLE_IP	nlnest[CTA_TUPLE_IP, cta_ip_nla_policy]
	CTA_TUPLE_PROTO	nlnest[CTA_TUPLE_PROTO, nlattr[CTA_PROTO_NUM, flags[conntrack_proto, int8]]]
	CTA_TUPLE_ZONE	nlnetw[CTA_TUPLE_ZONE, conntrack_zone]
] [varlen]

cta_ip_nla_policy [
	ipv4	cta_ip_nla_policy$ipv4
	ipv6	cta_ip_nla_policy$ipv6
] [varlen]

cta_ip_nla_policy$ipv4 {
	CTA_IP_V4_SRC	nlattr[CTA_IP_V4_SRC, ipv4_addr]
	CTA_IP_V4_DST	nlattr[CTA_IP_V4_DST, ipv4_addr]
}

cta_ip_nla_policy$ipv6 {
	CTA_IP_V6_SRC	nlattr[CTA_IP_V6_SRC, ipv6_addr]
	CTA_IP_V6_DST	nlattr[CTA_IP_V6_DST, ipv6_addr]
}

protoinfo_policy [
	CTA_PROTOINFO_TCP	nlnest[CTA_PROTOINFO_TCP, array[tcp_nla_policy]]
	CTA_PROTOINFO_DCCP	nlnest[CTA_PROTOINFO_DCCP, array[dccp_nla_policy]]
	CTA_PROTOINFO_SCTP	nlnest[CTA_PROTOINFO_SCTP, array[sctp_nla_policy]]
] [varlen]

tcp_nla_policy [
	CTA_PROTOINFO_TCP_STATE			nlattr[CTA_PROTOINFO_TCP_STATE, int8]
	CTA_PROTOINFO_TCP_WSCALE_ORIGINAL	nlattr[CTA_PROTOINFO_TCP_WSCALE_ORIGINAL, int8]
	CTA_PROTOINFO_TCP_WSCALE_REPLY		nlattr[CTA_PROTOINFO_TCP_WSCALE_REPLY, int8]
	CTA_PROTOINFO_TCP_FLAGS_ORIGINAL	nlattr[CTA_PROTOINFO_TCP_FLAGS_ORIGINAL, nf_ct_tcp_flags]
	CTA_PROTOINFO_TCP_FLAGS_REPLY		nlattr[CTA_PROTOINFO_TCP_FLAGS_REPLY, nf_ct_tcp_flags]
] [varlen]

nf_ct_tcp_flags {
	flags	int8
	mask	int8
}

dccp_nla_policy [
	CTA_PROTOINFO_DCCP_STATE		nlattr[CTA_PROTOINFO_DCCP_STATE, int8]
	CTA_PROTOINFO_DCCP_ROLE			nlattr[CTA_PROTOINFO_DCCP_ROLE, int8]
	CTA_PROTOINFO_DCCP_HANDSHAKE_SEQ	nlnetw[CTA_PROTOINFO_DCCP_HANDSHAKE_SEQ, int64be]
] [varlen]

sctp_nla_policy [
	CTA_PROTOINFO_SCTP_STATE		nlattr[CTA_PROTOINFO_SCTP_STATE, int8]
	CTA_PROTOINFO_SCTP_VTAG_ORIGINAL	nlnetw[CTA_PROTOINFO_SCTP_VTAG_ORIGINAL, int32be]
	CTA_PROTOINFO_SCTP_VTAG_REPLY		nlnetw[CTA_PROTOINFO_SCTP_VTAG_REPLY, int32be]
] [varlen]

nat_nla_policy [
	CTA_NAT_V4_MINIP	nlattr[CTA_NAT_V4_MINIP, ipv4_addr]
	CTA_NAT_V4_MAXIP	nlattr[CTA_NAT_V4_MAXIP, ipv4_addr]
	CTA_NAT_V6_MINIP	nlattr[CTA_NAT_V6_MINIP, ipv6_addr]
	CTA_NAT_V6_MAXIP	nlattr[CTA_NAT_V6_MAXIP, ipv6_addr]
	CTA_NAT_PROTO		nlnest[CTA_NAT_PROTO, array[protonat_nla_policy]]
] [varlen]

protonat_nla_policy [
	CTA_PROTONAT_PORT_MIN	nlattr[CTA_PROTONAT_PORT_MIN, sock_port]
	CTA_PROTONAT_PORT_MAX	nlattr[CTA_PROTONAT_PORT_MAX, sock_port]
] [varlen]

synproxy_policy [
	CTA_SYNPROXY_ISN	nlnetw[CTA_SYNPROXY_ISN, int32be]
	CTA_SYNPROXY_ITS	nlnetw[CTA_SYNPROXY_ITS, int32be]
	CTA_SYNPROXY_TSOFF	nlnetw[CTA_SYNPROXY_TSOFF, int32be]
] [varlen]

cta_filter_nla_policy [
	CTA_FILTER_ORIG_FLAGS	nlattr[CTA_FILTER_ORIG_FLAGS, flags[cta_filter_flags, int32]]
	CTA_FILTER_REPLY_FLAGS	nlattr[CTA_FILTER_REPLY_FLAGS, flags[cta_filter_flags, int32]]
] [varlen]

conntrack_proto = IPPROTO_UDP, IPPROTO_TCP, IPPROTO_ICMP, IPPROTO_DCCP, IPPROTO_SCTP, IPPROTO_UDPLITE, IPPROTO_GRE, IPPROTO_ICMPV6
ip_conntrack_status = IPS_SEEN_REPLY, IPS_ASSURED, IPS_FIXED_TIMEOUT, IPS_UNTRACKED, IPS_HELPER
cta_filter_flags = CTA_FILTER_F_CTA_IP_SRC, CTA_FILTER_F_CTA_IP_DST, CTA_FILTER_F_CTA_TUPLE_ZONE, CTA_FILTER_F_CTA_PROTO_NUM, CTA_FILTER_F_CTA_PROTO_SRC_PORT, CTA_FILTER_F_CTA_PROTO_DST_PORT, CTA_FILTER_F_CTA_PROTO_ICMP_TYPE, CTA_FILTER_F_CTA_PROTO_ICMP_CODE, CTA_FILTER_F_CTA_PROTO_ICMP_ID, CTA_FILTER_F_CTA_PROTO_ICMPV6_TYPE, CTA_FILTER_F_CTA_PROTO_ICMPV6_CODE, CTA_FILTER_F_CTA_PROTO_ICMPV6_ID
