Push a possible "unbind" in some situation from in6_pcbsetport() to

callers.  This also fixes a problem when the prison call could set
the inp->in6p_laddr (laddr) and a following priv_check_cred() call
would return an error and will allow us to merge the IPv4 and IPv6
implementation.

MFC after:	2 weeks
This commit is contained in:
bz 2011-03-12 16:45:15 +00:00
parent e3ccdf9a91
commit 5d37412b23
3 changed files with 9 additions and 6 deletions

View File

@ -256,8 +256,11 @@ in6_pcbbind(register struct inpcb *inp, struct sockaddr *nam,
inp->in6p_laddr = sin6->sin6_addr;
}
if (lport == 0) {
if ((error = in6_pcbsetport(&inp->in6p_laddr, inp, cred)) != 0)
if ((error = in6_pcbsetport(&inp->in6p_laddr, inp, cred)) != 0) {
/* Undo an address bind that may have occurred. */
inp->in6p_laddr = in6addr_any;
return (error);
}
} else {
inp->inp_lport = lport;
if (in_pcbinshash(inp) != 0) {

View File

@ -925,11 +925,8 @@ in6_pcbsetport(struct in6_addr *laddr, struct inpcb *inp, struct ucred *cred)
count = last - first;
do {
if (count-- < 0) { /* completely used? */
/* Undo an address bind that may have occurred. */
inp->in6p_laddr = in6addr_any;
if (count-- < 0) /* completely used? */
return (EADDRNOTAVAIL);
}
++*lastport;
if (*lastport < first || *lastport > last)
*lastport = first;

View File

@ -656,8 +656,11 @@ udp6_output(struct inpcb *inp, struct mbuf *m, struct sockaddr *addr6,
goto release;
}
if (inp->inp_lport == 0 &&
(error = in6_pcbsetport(laddr, inp, td->td_ucred)) != 0)
(error = in6_pcbsetport(laddr, inp, td->td_ucred)) != 0) {
/* Undo an address bind that may have occurred. */
inp->in6p_laddr = in6addr_any;
goto release;
}
} else {
if (IN6_IS_ADDR_UNSPECIFIED(&inp->in6p_faddr)) {
error = ENOTCONN;