Commit d46f8270 authored by Menglong Dong's avatar Menglong Dong Committed by Paolo Abeni
Browse files

net: ip: make ip_mc_validate_source() return drop reason



Make ip_mc_validate_source() return drop reason, and adjust the call of
it in ip_route_input_mc().

Another caller of it is ip_rcv_finish_core->udp_v4_early_demux, and the
errno is not checked in detail, so we don't do more adjustment for it.

The drop reason "SKB_DROP_REASON_IP_LOCALNET" is added in this commit.

Signed-off-by: default avatarMenglong Dong <dongml2@chinatelecom.cn>
Signed-off-by: default avatarPaolo Abeni <pabeni@redhat.com>
parent c6c67078
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -78,6 +78,7 @@
	FN(IP_INNOROUTES)		\
	FN(IP_LOCAL_SOURCE)		\
	FN(IP_INVALID_SOURCE)		\
	FN(IP_LOCALNET)			\
	FN(PKT_TOO_BIG)			\
	FN(DUP_FRAG)			\
	FN(FRAG_REASM_TIMEOUT)		\
@@ -383,6 +384,8 @@ enum skb_drop_reason {
	 * 2) source ip is zero and not IGMP
	 */
	SKB_DROP_REASON_IP_INVALID_SOURCE,
	/** @SKB_DROP_REASON_IP_LOCALNET: source or dest ip is local net */
	SKB_DROP_REASON_IP_LOCALNET,
	/**
	 * @SKB_DROP_REASON_PKT_TOO_BIG: packet size is too big (maybe exceed the
	 * MTU)
+4 −3
Original line number Diff line number Diff line
@@ -199,7 +199,8 @@ static inline struct rtable *ip_route_output_gre(struct net *net, struct flowi4
	return ip_route_output_key(net, fl4);
}

int ip_mc_validate_source(struct sk_buff *skb, __be32 daddr, __be32 saddr,
enum skb_drop_reason
ip_mc_validate_source(struct sk_buff *skb, __be32 daddr, __be32 saddr,
		      dscp_t dscp, struct net_device *dev,
		      struct in_device *in_dev, u32 *itag);
int ip_route_input_noref(struct sk_buff *skb, __be32 daddr, __be32 saddr,
+19 −16
Original line number Diff line number Diff line
@@ -1678,7 +1678,8 @@ struct rtable *rt_dst_clone(struct net_device *dev, struct rtable *rt)
EXPORT_SYMBOL(rt_dst_clone);

/* called in rcu_read_lock() section */
int ip_mc_validate_source(struct sk_buff *skb, __be32 daddr, __be32 saddr,
enum skb_drop_reason
ip_mc_validate_source(struct sk_buff *skb, __be32 daddr, __be32 saddr,
		      dscp_t dscp, struct net_device *dev,
		      struct in_device *in_dev, u32 *itag)
{
@@ -1686,26 +1687,28 @@ int ip_mc_validate_source(struct sk_buff *skb, __be32 daddr, __be32 saddr,

	/* Primary sanity checks. */
	if (!in_dev)
		return -EINVAL;
		return SKB_DROP_REASON_NOT_SPECIFIED;

	if (ipv4_is_multicast(saddr) || ipv4_is_lbcast(saddr) ||
	    skb->protocol != htons(ETH_P_IP))
		return -EINVAL;
	if (ipv4_is_multicast(saddr) || ipv4_is_lbcast(saddr))
		return SKB_DROP_REASON_IP_INVALID_SOURCE;

	if (skb->protocol != htons(ETH_P_IP))
		return SKB_DROP_REASON_INVALID_PROTO;

	if (ipv4_is_loopback(saddr) && !IN_DEV_ROUTE_LOCALNET(in_dev))
		return -EINVAL;
		return SKB_DROP_REASON_IP_LOCALNET;

	if (ipv4_is_zeronet(saddr)) {
		if (!ipv4_is_local_multicast(daddr) &&
		    ip_hdr(skb)->protocol != IPPROTO_IGMP)
			return -EINVAL;
			return SKB_DROP_REASON_IP_INVALID_SOURCE;
	} else {
		reason = fib_validate_source_reason(skb, saddr, 0, dscp, 0,
						    dev, in_dev, itag);
		if (reason)
			return -EINVAL;
			return reason;
	}
	return 0;
	return SKB_NOT_DROPPED_YET;
}

/* called in rcu_read_lock() section */
@@ -1715,14 +1718,14 @@ ip_route_input_mc(struct sk_buff *skb, __be32 daddr, __be32 saddr,
{
	struct in_device *in_dev = __in_dev_get_rcu(dev);
	unsigned int flags = RTCF_MULTICAST;
	enum skb_drop_reason reason;
	struct rtable *rth;
	u32 itag = 0;
	int err;

	err = ip_mc_validate_source(skb, daddr, saddr, dscp, dev, in_dev,
	reason = ip_mc_validate_source(skb, daddr, saddr, dscp, dev, in_dev,
				       &itag);
	if (err)
		return SKB_DROP_REASON_NOT_SPECIFIED;
	if (reason)
		return reason;

	if (our)
		flags |= RTCF_LOCAL;