From 97ca6483dad3629b30f7d3c616adf94f36009e8e Mon Sep 17 00:00:00 2001 From: bluhm Date: Fri, 22 Mar 2024 18:05:01 +0000 Subject: [PATCH] Make local port which is bound during connect(2) unique per laddr. in_pcbconnect() did not pass down the address it got from in_pcbselsrc() to in_pcbpickport(). As a consequence local port numbers selected during connect(2) were globally unique although they belong to different addresses. This strict uniqueness is not necessary and wastes usable ports for outgoing connections. To solve this, pass ina from in_pcbconnect() to in_pcbbind_locked(). This does not interfere how wildcard sockets are matched with specific sockets during bind(2). It only allows non-wildcard sockets to share a local port during connect(2). OK mvs@ deraadt@ --- sys/netinet/in_pcb.c | 10 +++++----- sys/netinet/in_pcb.h | 5 +++-- sys/netinet6/in6_pcb.c | 4 ++-- 3 files changed, 10 insertions(+), 9 deletions(-) diff --git a/sys/netinet/in_pcb.c b/sys/netinet/in_pcb.c index 610b91d11bb..5eda7fd4691 100644 --- a/sys/netinet/in_pcb.c +++ b/sys/netinet/in_pcb.c @@ -1,4 +1,4 @@ -/* $OpenBSD: in_pcb.c,v 1.296 2024/02/29 12:01:59 naddy Exp $ */ +/* $OpenBSD: in_pcb.c,v 1.297 2024/03/22 18:05:01 bluhm Exp $ */ /* $NetBSD: in_pcb.c,v 1.25 1996/02/13 23:41:53 christos Exp $ */ /* @@ -277,12 +277,12 @@ in_pcballoc(struct socket *so, struct inpcbtable *table, int wait) } int -in_pcbbind_locked(struct inpcb *inp, struct mbuf *nam, struct proc *p) +in_pcbbind_locked(struct inpcb *inp, struct mbuf *nam, const void *laddr, + struct proc *p) { struct socket *so = inp->inp_socket; u_int16_t lport = 0; int wild = 0; - const void *laddr = &zeroin46_addr; int error; if (inp->inp_lport) @@ -359,7 +359,7 @@ in_pcbbind(struct inpcb *inp, struct mbuf *nam, struct proc *p) /* keep lookup, modification, and rehash in sync */ mtx_enter(&table->inpt_mtx); - error = in_pcbbind_locked(inp, nam, p); + error = in_pcbbind_locked(inp, nam, &zeroin46_addr, p); mtx_leave(&table->inpt_mtx); return error; @@ -542,7 +542,7 @@ in_pcbconnect(struct inpcb *inp, struct mbuf *nam) if (inp->inp_laddr.s_addr == INADDR_ANY) { if (inp->inp_lport == 0) { - error = in_pcbbind_locked(inp, NULL, curproc); + error = in_pcbbind_locked(inp, NULL, &ina, curproc); if (error) { mtx_leave(&table->inpt_mtx); return (error); diff --git a/sys/netinet/in_pcb.h b/sys/netinet/in_pcb.h index 1d67469c635..e16647f33fb 100644 --- a/sys/netinet/in_pcb.h +++ b/sys/netinet/in_pcb.h @@ -1,4 +1,4 @@ -/* $OpenBSD: in_pcb.h,v 1.152 2024/02/13 12:22:09 bluhm Exp $ */ +/* $OpenBSD: in_pcb.h,v 1.153 2024/03/22 18:05:01 bluhm Exp $ */ /* $NetBSD: in_pcb.h,v 1.14 1996/02/13 23:42:00 christos Exp $ */ /* @@ -307,7 +307,8 @@ extern int in_pcbnotifymiss; void in_init(void); void in_losing(struct inpcb *); int in_pcballoc(struct socket *, struct inpcbtable *, int); -int in_pcbbind_locked(struct inpcb *, struct mbuf *, struct proc *); +int in_pcbbind_locked(struct inpcb *, struct mbuf *, const void *, + struct proc *); int in_pcbbind(struct inpcb *, struct mbuf *, struct proc *); int in_pcbaddrisavail(const struct inpcb *, struct sockaddr_in *, int, struct proc *); diff --git a/sys/netinet6/in6_pcb.c b/sys/netinet6/in6_pcb.c index ac10047a6f3..88b6e60459f 100644 --- a/sys/netinet6/in6_pcb.c +++ b/sys/netinet6/in6_pcb.c @@ -1,4 +1,4 @@ -/* $OpenBSD: in6_pcb.c,v 1.141 2024/02/29 12:01:59 naddy Exp $ */ +/* $OpenBSD: in6_pcb.c,v 1.142 2024/03/22 18:05:01 bluhm Exp $ */ /* * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. @@ -313,7 +313,7 @@ in6_pcbconnect(struct inpcb *inp, struct mbuf *nam) if (IN6_IS_ADDR_UNSPECIFIED(&inp->inp_laddr6)) { if (inp->inp_lport == 0) { - error = in_pcbbind_locked(inp, NULL, curproc); + error = in_pcbbind_locked(inp, NULL, in6a, curproc); if (error) { mtx_leave(&table->inpt_mtx); return (error); -- 2.20.1