Enhance the historic behaviour of raw sockets and jails in a way

that we allow all possible jail IPs as source address rather than
forcing the "primary". While IPv6 naturally has source address
selection, for legacy IP we do not go through the pain in case
IP_HDRINCL was not set. People should bind(2) for that.

This will, for example, allow ping(|6) -S to work correctly for
non-primary addresses.

Reported by:	(ten 211.ru)
Tested by:	(ten 211.ru)
MFC after:	4 days
This commit is contained in:
Bjoern A. Zeeb 2010-04-27 15:07:08 +00:00
parent 877fc3b64b
commit 7a657e630d
2 changed files with 19 additions and 6 deletions

View File

@ -427,11 +427,24 @@ rip_output(struct mbuf *m, struct socket *so, u_long dst)
ip->ip_p = inp->inp_ip_p;
ip->ip_len = m->m_pkthdr.len;
ip->ip_src = inp->inp_laddr;
error = prison_get_ip4(inp->inp_cred, &ip->ip_src);
if (error != 0) {
INP_RUNLOCK(inp);
m_freem(m);
return (error);
if (jailed(inp->inp_cred)) {
/*
* prison_local_ip4() would be good enough but would
* let a source of INADDR_ANY pass, which we do not
* want to see from jails. We do not go through the
* pain of in_pcbladdr() for raw sockets.
*/
if (ip->ip_src.s_addr == INADDR_ANY)
error = prison_get_ip4(inp->inp_cred,
&ip->ip_src);
else
error = prison_local_ip4(inp->inp_cred,
&ip->ip_src);
if (error != 0) {
INP_RUNLOCK(inp);
m_freem(m);
return (error);
}
}
ip->ip_dst.s_addr = dst;
ip->ip_ttl = inp->inp_ip_ttl;

View File

@ -465,7 +465,7 @@ rip6_output(m, va_alist)
&oifp, &in6a);
if (error)
goto bad;
error = prison_get_ip6(in6p->inp_cred, &in6a);
error = prison_check_ip6(in6p->inp_cred, &in6a);
if (error != 0)
goto bad;
ip6->ip6_src = in6a;