#ifndef _COMPAT_NET_NETLINK_H
#define _COMPAT_NET_NETLINK_H 1

#include "../../compat/config.h"

#include_next <net/netlink.h>
#include <net/genetlink.h>

#ifndef HAVE_NLA_FOR_EACH_NESTED_TYPE
#define nla_for_each_nested_type(pos, type, nla, rem) \
		nla_for_each_nested(pos, nla, rem) \
				if (nla_type(pos) == type)
#endif

#ifndef HAVE_NLA_POLICY_NESTED

#undef NLA_POLICY_RANGE
#define NLA_POLICY_RANGE(tp, _min, _max) {		\
		.type = NLA_ENSURE_INT_TYPE(tp),		\
}

#undef _NLA_POLICY_NESTED
#define _NLA_POLICY_NESTED(maxattr, policy) \
		{ .type = NLA_NESTED, .validation_data = policy, .len = maxattr }

#undef _NLA_POLICY_NESTED_ARRAY
#define _NLA_POLICY_NESTED_ARRAY(maxattr, policy) \
		{ .type = NLA_NESTED_ARRAY, .validation_data = policy, .len = maxattr }

#undef NLA_POLICY_NESTED
#define NLA_POLICY_NESTED(policy) \
		_NLA_POLICY_NESTED(ARRAY_SIZE(policy) - 1, policy)

#undef NLA_POLICY_NESTED_ARRAY
#define NLA_POLICY_NESTED_ARRAY(policy) \
		_NLA_POLICY_NESTED_ARRAY(ARRAY_SIZE(policy) - 1, policy)

#undef __NLA_ENSURE
#define __NLA_ENSURE(condition) BUILD_BUG_ON_ZERO(!(condition))

#undef NLA_ENSURE_INT_TYPE
#define NLA_ENSURE_INT_TYPE(tp)				\
	(__NLA_ENSURE(tp == NLA_S8 || tp == NLA_U8 ||	\
		      tp == NLA_S16 || tp == NLA_U16 ||	\
		      tp == NLA_S32 || tp == NLA_U32 ||	\
		      tp == NLA_S64 || tp == NLA_U64) + tp)

#undef NLA_POLICY_MAX
#define NLA_POLICY_MAX(tp, _max) {			\
	.type = NLA_ENSURE_INT_TYPE(tp),		\
}
#endif

#ifndef HAVE_NLA_POLICY_BITFIELD32
#define NLA_POLICY_BITFIELD32(valid) \
		{ .type = NLA_BITFIELD32 }
#endif

#ifndef HAVE_NLA_PUT_BITFIELD32
static inline int nla_put_bitfield32(struct sk_buff *skb, int attrtype,
		__u32 value, __u32 selector)
{
	struct nla_bitfield32 tmp = { value, selector, };

	return nla_put(skb, attrtype, sizeof(tmp), &tmp);
}
#endif

#ifndef HAVE_NLA_NEST_START_NOFLAG
static inline struct nlattr *nla_nest_start_noflag(struct sk_buff *skb,
		int attrtype)
{
	struct nlattr *start = (struct nlattr *)skb_tail_pointer(skb);

	if (nla_put(skb, attrtype, 0, NULL) < 0)
		return NULL;

	return start;
}
#endif

#ifndef HAVE_NLMSG_FOR_EACH_ATTR_TYPE
/**
 * nlmsg_for_each_attr_type - iterate over a stream of attributes
 * @pos: loop counter, set to the current attribute
 * @type: required attribute type for @pos
 * @nlh: netlink message header
 * @hdrlen: length of the family specific header
 * @rem: initialized to len, holds bytes currently remaining in stream
 */
#define nlmsg_for_each_attr_type(pos, type, nlh, hdrlen, rem) \
	nlmsg_for_each_attr(pos, nlh, hdrlen, rem) \
		if (nla_type(pos) == type)

#endif /* HAVE_NLMSG_FOR_EACH_ATTR_TYPE */

#endif	/* _COMPAT_NET_NETLINK_H */

