Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 55be7a9c authored by David S. Miller's avatar David S. Miller
Browse files

ipv4: Add redirect support to all protocol icmp error handlers.

parent b42597e2
Loading
Loading
Loading
Loading
+11 −0
Original line number Diff line number Diff line
@@ -195,6 +195,14 @@ static inline void dccp_do_pmtu_discovery(struct sock *sk,
	} /* else let the usual retransmit timer handle it */
}

static void dccp_do_redirect(struct sk_buff *skb, struct sock *sk)
{
	struct dst_entry *dst = __sk_dst_check(sk, 0);

	if (dst && dst->ops->redirect)
		dst->ops->redirect(dst, skb);
}

/*
 * This routine is called by the ICMP module when it gets some sort of error
 * condition. If err < 0 then the socket should be closed and the error
@@ -259,6 +267,9 @@ static void dccp_v4_err(struct sk_buff *skb, u32 info)
	}

	switch (type) {
	case ICMP_REDIRECT:
		dccp_do_redirect(skb, sk);
		goto out;
	case ICMP_SOURCE_QUENCH:
		/* Just silently ignore these. */
		goto out;
+13 −5
Original line number Diff line number Diff line
@@ -398,17 +398,25 @@ static void ah4_err(struct sk_buff *skb, u32 info)
	struct ip_auth_hdr *ah = (struct ip_auth_hdr *)(skb->data+(iph->ihl<<2));
	struct xfrm_state *x;

	if (icmp_hdr(skb)->type != ICMP_DEST_UNREACH ||
	    icmp_hdr(skb)->code != ICMP_FRAG_NEEDED)
	switch (icmp_hdr(skb)->type) {
	case ICMP_DEST_UNREACH:
		if (icmp_hdr(skb)->code != ICMP_FRAG_NEEDED)
			return;
	case ICMP_REDIRECT:
		break;
	default:
		return;
	}

	x = xfrm_state_lookup(net, skb->mark, (const xfrm_address_t *)&iph->daddr,
			      ah->spi, IPPROTO_AH, AF_INET);
	if (!x)
		return;
	pr_debug("pmtu discovery on SA AH/%08x/%08x\n",
		 ntohl(ah->spi), ntohl(iph->daddr));

	if (icmp_hdr(skb)->type == ICMP_DEST_UNREACH)
		ipv4_update_pmtu(skb, net, info, 0, 0, IPPROTO_AH, 0);
	else
		ipv4_redirect(skb, net, 0, 0, IPPROTO_AH, 0);
	xfrm_state_put(x);
}

+13 −5
Original line number Diff line number Diff line
@@ -484,17 +484,25 @@ static void esp4_err(struct sk_buff *skb, u32 info)
	struct ip_esp_hdr *esph = (struct ip_esp_hdr *)(skb->data+(iph->ihl<<2));
	struct xfrm_state *x;

	if (icmp_hdr(skb)->type != ICMP_DEST_UNREACH ||
	    icmp_hdr(skb)->code != ICMP_FRAG_NEEDED)
	switch (icmp_hdr(skb)->type) {
	case ICMP_DEST_UNREACH:
		if (icmp_hdr(skb)->code != ICMP_FRAG_NEEDED)
			return;
	case ICMP_REDIRECT:
		break;
	default:
		return;
	}

	x = xfrm_state_lookup(net, skb->mark, (const xfrm_address_t *)&iph->daddr,
			      esph->spi, IPPROTO_ESP, AF_INET);
	if (!x)
		return;
	NETDEBUG(KERN_DEBUG "pmtu discovery on SA ESP/%08x/%08x\n",
		 ntohl(esph->spi), ntohl(iph->daddr));

	if (icmp_hdr(skb)->type == ICMP_DEST_UNREACH)
		ipv4_update_pmtu(skb, net, info, 0, 0, IPPROTO_ESP, 0);
	else
		ipv4_redirect(skb, net, 0, 0, IPPROTO_ESP, 0);
	xfrm_state_put(x);
}

+8 −1
Original line number Diff line number Diff line
@@ -528,6 +528,9 @@ static void ipgre_err(struct sk_buff *skb, u32 info)
		if (code != ICMP_EXC_TTL)
			return;
		break;

	case ICMP_REDIRECT:
		break;
	}

	rcu_read_lock();
@@ -543,7 +546,11 @@ static void ipgre_err(struct sk_buff *skb, u32 info)
				 t->parms.link, 0, IPPROTO_GRE, 0);
		goto out;
	}

	if (type == ICMP_REDIRECT) {
		ipv4_redirect(skb, dev_net(skb->dev), t->parms.link, 0,
			      IPPROTO_GRE, 0);
		goto out;
	}
	if (t->parms.iph.daddr == 0 ||
	    ipv4_is_multicast(t->parms.iph.daddr))
		goto out;
+13 −5
Original line number Diff line number Diff line
@@ -31,18 +31,26 @@ static void ipcomp4_err(struct sk_buff *skb, u32 info)
	struct ip_comp_hdr *ipch = (struct ip_comp_hdr *)(skb->data+(iph->ihl<<2));
	struct xfrm_state *x;

	if (icmp_hdr(skb)->type != ICMP_DEST_UNREACH ||
	    icmp_hdr(skb)->code != ICMP_FRAG_NEEDED)
	switch (icmp_hdr(skb)->type) {
	case ICMP_DEST_UNREACH:
		if (icmp_hdr(skb)->code != ICMP_FRAG_NEEDED)
			return;
	case ICMP_REDIRECT:
		break;
	default:
		return;
	}

	spi = htonl(ntohs(ipch->cpi));
	x = xfrm_state_lookup(net, skb->mark, (const xfrm_address_t *)&iph->daddr,
			      spi, IPPROTO_COMP, AF_INET);
	if (!x)
		return;
	NETDEBUG(KERN_DEBUG "pmtu discovery on SA IPCOMP/%08x/%pI4\n",
		 spi, &iph->daddr);

	if (icmp_hdr(skb)->type == ICMP_DEST_UNREACH)
		ipv4_update_pmtu(skb, net, info, 0, 0, IPPROTO_COMP, 0);
	else
		ipv4_redirect(skb, net, 0, 0, IPPROTO_COMP, 0);
	xfrm_state_put(x);
}

Loading