示例#1
0
static unsigned int nf_route_table_hook(void *priv,
					struct sk_buff *skb,
					const struct nf_hook_state *state)
{
	unsigned int ret;
	struct nft_pktinfo pkt;
	struct in6_addr saddr, daddr;
	u_int8_t hop_limit;
	u32 mark, flowlabel;

	/* malformed packet, drop it */
	if (nft_set_pktinfo_ipv6(&pkt, skb, state) < 0)
		return NF_DROP;

	/* save source/dest address, mark, hoplimit, flowlabel, priority */
	memcpy(&saddr, &ipv6_hdr(skb)->saddr, sizeof(saddr));
	memcpy(&daddr, &ipv6_hdr(skb)->daddr, sizeof(daddr));
	mark = skb->mark;
	hop_limit = ipv6_hdr(skb)->hop_limit;

	/* flowlabel and prio (includes version, which shouldn't change either */
	flowlabel = *((u32 *)ipv6_hdr(skb));

	ret = nft_do_chain(&pkt, priv);
	if (ret != NF_DROP && ret != NF_QUEUE &&
	    (memcmp(&ipv6_hdr(skb)->saddr, &saddr, sizeof(saddr)) ||
	     memcmp(&ipv6_hdr(skb)->daddr, &daddr, sizeof(daddr)) ||
	     skb->mark != mark ||
	     ipv6_hdr(skb)->hop_limit != hop_limit ||
	     flowlabel != *((u_int32_t *)ipv6_hdr(skb))))
		return ip6_route_me_harder(state->net, skb) == 0 ? ret : NF_DROP;

	return ret;
}
示例#2
0
static unsigned int nf_nat_fn(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 *))
{
	enum ip_conntrack_info ctinfo;
	struct nf_conn *ct = nf_ct_get(skb, &ctinfo);
	struct nf_conn_nat *nat;
	enum nf_nat_manip_type maniptype = HOOK2MANIP(ops->hooknum);
	unsigned int ret;

	if (ct == NULL || nf_ct_is_untracked(ct))
		return NF_ACCEPT;

	NF_CT_ASSERT(!(ip_hdr(skb)->frag_off & htons(IP_MF | IP_OFFSET)));

	nat = nfct_nat(ct);
	if (nat == NULL) {
		/* Conntrack module was loaded late, can't add extension. */
		if (nf_ct_is_confirmed(ct))
			return NF_ACCEPT;
		nat = nf_ct_ext_add(ct, NF_CT_EXT_NAT, GFP_ATOMIC);
		if (nat == NULL)
			return NF_ACCEPT;
	}

	switch (ctinfo) {
	case IP_CT_RELATED:
	case IP_CT_RELATED + IP_CT_IS_REPLY:
		if (ip_hdr(skb)->protocol == IPPROTO_ICMP) {
			if (!nf_nat_icmp_reply_translation(skb, ct, ctinfo,
							   ops->hooknum))
				return NF_DROP;
			else
				return NF_ACCEPT;
		}
		/* Fall through */
	case IP_CT_NEW:
		if (nf_nat_initialized(ct, maniptype))
			break;

		ret = nft_do_chain(ops, skb, in, out, okfn);
		if (ret != NF_ACCEPT)
			return ret;
		if (!nf_nat_initialized(ct, maniptype)) {
			ret = nf_nat_alloc_null_binding(ct, ops->hooknum);
			if (ret != NF_ACCEPT)
				return ret;
		}
	default:
		break;
	}

	return nf_nat_packet(ct, ctinfo, ops->hooknum, skb);
}
示例#3
0
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);
}
示例#4
0
static unsigned int nft_nat_do_chain(void *priv,
				      struct sk_buff *skb,
				      const struct nf_hook_state *state,
				      struct nf_conn *ct)
{
	struct nft_pktinfo pkt;

	nft_set_pktinfo_ipv4(&pkt, skb, state);

	return nft_do_chain(&pkt, priv);
}
示例#5
0
static unsigned int nft_nat_do_chain(const struct nf_hook_ops *ops,
				     struct sk_buff *skb,
				     const struct nf_hook_state *state,
				     struct nf_conn *ct)
{
	struct nft_pktinfo pkt;

	nft_set_pktinfo_ipv6(&pkt, ops, skb, state);

	return nft_do_chain(&pkt, ops);
}
示例#6
0
static unsigned int nft_do_chain_ipv6(void *priv,
				      struct sk_buff *skb,
				      const struct nf_hook_state *state)
{
	struct nft_pktinfo pkt;

	/* malformed packet, drop it */
	if (nft_set_pktinfo_ipv6(&pkt, skb, state) < 0)
		return NF_DROP;

	return nft_do_chain(&pkt, priv);
}
示例#7
0
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);
}
示例#8
0
static unsigned int nft_ipv4_output(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 *))
{
	if (unlikely(skb->len < sizeof(struct iphdr) ||
		     ip_hdr(skb)->ihl < sizeof(struct iphdr) / 4)) {
		if (net_ratelimit())
			pr_info("nf_tables_ipv4: ignoring short SOCK_RAW "
				"packet\n");
		return NF_ACCEPT;
	}

	return nft_do_chain(ops, skb, in, out, okfn);
}
示例#9
0
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);
}
示例#10
0
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);
}