static inline void nft_netdev_set_pktinfo_ipv4(struct nft_pktinfo *pkt, const struct nf_hook_ops *ops, struct sk_buff *skb, const struct nf_hook_state *state) { struct iphdr *iph, _iph; u32 len, thoff; nft_set_pktinfo(pkt, ops, skb, state); iph = skb_header_pointer(skb, skb_network_offset(skb), sizeof(*iph), &_iph); if (!iph) return; iph = ip_hdr(skb); if (iph->ihl < 5 || iph->version != 4) return; len = ntohs(iph->tot_len); thoff = iph->ihl * 4; if (skb->len < len) return; else if (len < thoff) return; pkt->tprot = iph->protocol; pkt->xt.thoff = thoff; pkt->xt.fragoff = ntohs(iph->frag_off) & IP_OFFSET; }
static inline void nft_netdev_set_pktinfo_ipv6(struct nft_pktinfo *pkt, const struct nf_hook_ops *ops, struct sk_buff *skb, const struct nf_hook_state *state) { nft_set_pktinfo(pkt, ops, skb, state); __nft_netdev_set_pktinfo_ipv6(pkt, ops, skb, state); }
static inline void nft_bridge_set_pktinfo_ipv4(struct nft_pktinfo *pkt, const struct nf_hook_ops *ops, struct sk_buff *skb, const struct nf_hook_state *state) { if (nft_bridge_iphdr_validate(skb)) nft_set_pktinfo_ipv4(pkt, ops, skb, state); else nft_set_pktinfo(pkt, ops, skb, state); }
static unsigned int nft_do_chain_arp(void *priv, struct sk_buff *skb, const struct nf_hook_state *state) { struct nft_pktinfo pkt; nft_set_pktinfo(&pkt, skb, state); return nft_do_chain(&pkt, priv); }
static inline void nft_bridge_set_pktinfo_ipv6(struct nft_pktinfo *pkt, const struct nf_hook_ops *ops, struct sk_buff *skb, const struct nf_hook_state *state) { #if IS_ENABLED(CONFIG_IPV6) if (nft_bridge_ip6hdr_validate(skb) && nft_set_pktinfo_ipv6(pkt, ops, skb, state) == 0) return; #endif nft_set_pktinfo(pkt, ops, skb, state); }
static unsigned int nft_do_chain_bridge(const struct nf_hook_ops *ops, struct sk_buff *skb, const struct net_device *in, const struct net_device *out, int (*okfn)(struct sk_buff *)) { struct nft_pktinfo pkt; nft_set_pktinfo(&pkt, ops, skb, in, out); return nft_do_chain(&pkt, ops); }
static unsigned int nft_do_chain_netdev(const struct nf_hook_ops *ops, struct sk_buff *skb, const struct nf_hook_state *state) { struct nft_pktinfo pkt; switch (eth_hdr(skb)->h_proto) { case htons(ETH_P_IP): nft_netdev_set_pktinfo_ipv4(&pkt, ops, skb, state); break; case htons(ETH_P_IPV6): nft_netdev_set_pktinfo_ipv6(&pkt, ops, skb, state); break; default: nft_set_pktinfo(&pkt, ops, skb, state); break; } return nft_do_chain(&pkt, ops); }
static unsigned int nft_nat_do_chain(void *priv, struct sk_buff *skb, const struct nf_hook_state *state) { struct nft_pktinfo pkt; nft_set_pktinfo(&pkt, skb, state); switch (state->pf) { #ifdef CONFIG_NF_TABLES_IPV4 case NFPROTO_IPV4: nft_set_pktinfo_ipv4(&pkt, skb); break; #endif #ifdef CONFIG_NF_TABLES_IPV6 case NFPROTO_IPV6: nft_set_pktinfo_ipv6(&pkt, skb); break; #endif default: break; } return nft_do_chain(&pkt, priv); }