net/netfilter/nft_rt.c

Source file repositories/reference/linux-study-clean/net/netfilter/nft_rt.c

File Facts

System
Linux kernel
Corpus path
net/netfilter/nft_rt.c
Extension
.c
Size
4618 bytes
Lines
207
Domain
Networking Core
Bucket
Sockets, Protocols, Packet Path, And Network Policy
Inferred role
Networking Core: implementation source
Status
source implementation candidate

Why This File Exists

Networking stack implementation surface: socket APIs, protocol dispatch, packet flow, routing, filtering, and network namespaces.

Dependency Surface

Detected Declarations

Annotated Snippet

struct nft_rt {
	enum nft_rt_keys	key:8;
	u8			dreg;
};

static u16 get_tcpmss(const struct nft_pktinfo *pkt, const struct dst_entry *skbdst)
{
	u32 minlen = sizeof(struct ipv6hdr), mtu = dst_mtu(skbdst);
	const struct sk_buff *skb = pkt->skb;
	struct dst_entry *dst = NULL;
	struct flowi fl;

	memset(&fl, 0, sizeof(fl));

	switch (nft_pf(pkt)) {
	case NFPROTO_IPV4:
		fl.u.ip4.daddr = ip_hdr(skb)->saddr;
		minlen = sizeof(struct iphdr) + sizeof(struct tcphdr);
		break;
	case NFPROTO_IPV6:
		fl.u.ip6.daddr = ipv6_hdr(skb)->saddr;
		minlen = sizeof(struct ipv6hdr) + sizeof(struct tcphdr);
		break;
	}

	nf_route(nft_net(pkt), &dst, &fl, false, nft_pf(pkt));
	if (dst) {
		mtu = min(mtu, dst_mtu(dst));
		dst_release(dst);
	}

	if (mtu <= minlen || mtu > 0xffff)
		return TCP_MSS_DEFAULT;

	return mtu - minlen;
}

void nft_rt_get_eval(const struct nft_expr *expr,
		     struct nft_regs *regs,
		     const struct nft_pktinfo *pkt)
{
	const struct nft_rt *priv = nft_expr_priv(expr);
	const struct sk_buff *skb = pkt->skb;
	u32 *dest = &regs->data[priv->dreg];
	const struct dst_entry *dst;

	dst = skb_dst(skb);
	if (!dst)
		goto err;

	switch (priv->key) {
#ifdef CONFIG_IP_ROUTE_CLASSID
	case NFT_RT_CLASSID:
		*dest = dst->tclassid;
		break;
#endif
	case NFT_RT_NEXTHOP4:
		if (nft_pf(pkt) != NFPROTO_IPV4)
			goto err;

		*dest = (__force u32)rt_nexthop(dst_rtable(dst),
						ip_hdr(skb)->daddr);
		break;
	case NFT_RT_NEXTHOP6:
		if (nft_pf(pkt) != NFPROTO_IPV6)
			goto err;

		memcpy(dest, rt6_nexthop(dst_rt6_info(dst),
					 &ipv6_hdr(skb)->daddr),
		       sizeof(struct in6_addr));
		break;
	case NFT_RT_TCPMSS:
		nft_reg_store16(dest, get_tcpmss(pkt, dst));
		break;
#ifdef CONFIG_XFRM
	case NFT_RT_XFRM:
		nft_reg_store8(dest, !!dst->xfrm);
		break;
#endif
	default:
		DEBUG_NET_WARN_ON_ONCE(1);
		goto err;
	}
	return;

err:
	regs->verdict.code = NFT_BREAK;
}

static const struct nla_policy nft_rt_policy[NFTA_RT_MAX + 1] = {

Annotation

Implementation Notes