in_pcblookup() is always called with *:0 for the remote side.
Remove the useless bits, shuffle the tests around and it's much
easier to audit.
Ok ?
Index: netinet/in_pcb.c
===================================================================
RCS file: /cvs/src/sys/netinet/in_pcb.c,v
retrieving revision 1.201
diff -u -p -r1.201 in_pcb.c
--- netinet/in_pcb.c 8 Apr 2016 14:34:21 -0000 1.201
+++ netinet/in_pcb.c 9 Apr 2016 09:42:07 -0000
@@ -415,14 +415,13 @@ in_pcbaddrisavail(struct inpcb *inp, str
struct inpcb *t;
if (so->so_euid) {
- t = in_pcblookup(table, &zeroin_addr, 0,
- &sin->sin_addr, lport, INPLOOKUP_WILDCARD,
- inp->inp_rtableid);
+ t = in_pcblookup_local(table, &sin->sin_addr, lport,
+ INPLOOKUP_WILDCARD, inp->inp_rtableid);
if (t && (so->so_euid != t->inp_socket->so_euid))
return (EADDRINUSE);
}
- t = in_pcblookup(table, &zeroin_addr, 0,
- &sin->sin_addr, lport, wild, inp->inp_rtableid);
+ t = in_pcblookup_local(table, &sin->sin_addr, lport,
+ wild, inp->inp_rtableid);
if (t && (reuseport & t->inp_socket->so_options) == 0)
return (EADDRINUSE);
}
@@ -475,8 +474,8 @@ in_pcbpickport(u_int16_t *lport, void *l
candidate = lower;
localport = htons(candidate);
} while (in_baddynamic(localport, so->so_proto->pr_protocol) ||
- in_pcblookup(table, &zeroin46_addr, 0,
- laddr, localport, wild, inp->inp_rtableid));
+ in_pcblookup_local(table, laddr, localport, wild,
+ inp->inp_rtableid));
*lport = localport;
return (0);
@@ -734,14 +733,14 @@ in_rtchange(struct inpcb *inp, int errno
}
struct inpcb *
-in_pcblookup(struct inpcbtable *table, void *faddrp, u_int fport_arg,
- void *laddrp, u_int lport_arg, int flags, u_int rdomain)
+in_pcblookup_local(struct inpcbtable *table, void *laddrp, u_int lport_arg,
+ int flags, u_int rdomain)
{
struct inpcb *inp, *match = NULL;
int matchwild = 3, wildcard;
- u_int16_t fport = fport_arg, lport = lport_arg;
- struct in_addr faddr = *(struct in_addr *)faddrp;
+ u_int16_t lport = lport_arg;
struct in_addr laddr = *(struct in_addr *)laddrp;
+ struct in6_addr *laddr6 = (struct in6_addr *)laddrp;
struct inpcbhead *head;
rdomain = rtable_l2(rdomain); /* convert passed rtableid to rdomain */
@@ -753,60 +752,40 @@ in_pcblookup(struct inpcbtable *table, v
continue;
wildcard = 0;
#ifdef INET6
- if (flags & INPLOOKUP_IPV6) {
- struct in6_addr *laddr6 = (struct in6_addr *)laddrp;
- struct in6_addr *faddr6 = (struct in6_addr *)faddrp;
-
- if (!(inp->inp_flags & INP_IPV6))
+ if (ISSET(flags, INPLOOKUP_IPV6)) {
+ if (!ISSET(inp->inp_flags, INP_IPV6))
continue;
- if (!IN6_IS_ADDR_UNSPECIFIED(&inp->inp_laddr6)) {
- if (IN6_IS_ADDR_UNSPECIFIED(laddr6))
- wildcard++;
- else if (!IN6_ARE_ADDR_EQUAL(&inp->inp_laddr6,
laddr6))
- continue;
- } else {
- if (!IN6_IS_ADDR_UNSPECIFIED(laddr6))
- wildcard++;
- }
+ if (!IN6_IS_ADDR_UNSPECIFIED(&inp->inp_faddr6))
+ wildcard++;
- if (!IN6_IS_ADDR_UNSPECIFIED(&inp->inp_faddr6)) {
- if (IN6_IS_ADDR_UNSPECIFIED(faddr6))
+ if (!IN6_ARE_ADDR_EQUAL(&inp->inp_laddr6, laddr6)) {
+ if (IN6_IS_ADDR_UNSPECIFIED(&inp->inp_laddr6) ||
+ IN6_IS_ADDR_UNSPECIFIED(laddr6))
wildcard++;
- else if (!IN6_ARE_ADDR_EQUAL(&inp->inp_faddr6,
- faddr6) || inp->inp_fport != fport)
+ else
continue;
- } else {
- if (!IN6_IS_ADDR_UNSPECIFIED(faddr6))
- wildcard++;
}
+
} else
#endif /* INET6 */
{
#ifdef INET6
- if (inp->inp_flags & INP_IPV6)
+ if (ISSET(inp->inp_flags, INP_IPV6))
continue;
#endif /* INET6 */
- if (inp->inp_faddr.s_addr != INADDR_ANY) {
- if (faddr.s_addr == INADDR_ANY)
- wildcard++;
- else if (inp->inp_faddr.s_addr != faddr.s_addr
||
- inp->inp_fport != fport)
- continue;
- } else {
- if (faddr.s_addr != INADDR_ANY)
- wildcard++;
- }
- if (inp->inp_laddr.s_addr != INADDR_ANY) {
- if (laddr.s_addr == INADDR_ANY)
+ if (inp->inp_faddr.s_addr != INADDR_ANY)
+ wildcard++;
+
+ if (inp->inp_laddr.s_addr != laddr.s_addr) {
+ if (inp->inp_laddr.s_addr == INADDR_ANY ||
+ laddr.s_addr == INADDR_ANY)
wildcard++;
- else if (inp->inp_laddr.s_addr != laddr.s_addr)
+ else
continue;
- } else {
- if (laddr.s_addr != INADDR_ANY)
- wildcard++;
}
+
}
if ((!wildcard || (flags & INPLOOKUP_WILDCARD)) &&
wildcard < matchwild) {
Index: netinet/in_pcb.h
===================================================================
RCS file: /cvs/src/sys/netinet/in_pcb.h,v
retrieving revision 1.97
diff -u -p -r1.97 in_pcb.h
--- netinet/in_pcb.h 5 Apr 2016 19:34:05 -0000 1.97
+++ netinet/in_pcb.h 9 Apr 2016 09:42:07 -0000
@@ -271,8 +271,7 @@ int in6_setpeeraddr(struct inpcb *, str
#endif /* INET6 */
void in_pcbinit(struct inpcbtable *, int);
struct inpcb *
- in_pcblookup(struct inpcbtable *, void *, u_int, void *,
- u_int, int, u_int);
+ in_pcblookup_local(struct inpcbtable *, void *, u_int, int, u_int);
void in_pcbnotifyall(struct inpcbtable *, struct sockaddr *,
u_int, int, void (*)(struct inpcb *, int));
void in_pcbrehash(struct inpcb *);
Index: netinet6/in6_pcb.c
===================================================================
RCS file: /cvs/src/sys/netinet6/in6_pcb.c,v
retrieving revision 1.91
diff -u -p -r1.91 in6_pcb.c
--- netinet6/in6_pcb.c 5 Apr 2016 21:21:41 -0000 1.91
+++ netinet6/in6_pcb.c 9 Apr 2016 09:42:08 -0000
@@ -217,16 +217,14 @@ in6_pcbaddrisavail(struct inpcb *inp, st
struct inpcb *t;
if (so->so_euid) {
- t = in_pcblookup(table,
- (struct in_addr *)&zeroin6_addr, 0,
+ t = in_pcblookup_local(table,
(struct in_addr *)&sin6->sin6_addr, lport,
INPLOOKUP_WILDCARD | INPLOOKUP_IPV6,
inp->inp_rtableid);
if (t && (so->so_euid != t->inp_socket->so_euid))
return (EADDRINUSE);
}
- t = in_pcblookup(table,
- (struct in_addr *)&zeroin6_addr, 0,
+ t = in_pcblookup_local(table,
(struct in_addr *)&sin6->sin6_addr, lport,
wild, inp->inp_rtableid);
if (t && (reuseport & t->inp_socket->so_options) == 0)