Make local port which is bound during connect(2) unique per laddr.
authorbluhm <bluhm@openbsd.org>
Fri, 22 Mar 2024 18:05:01 +0000 (18:05 +0000)
committerbluhm <bluhm@openbsd.org>
Fri, 22 Mar 2024 18:05:01 +0000 (18:05 +0000)
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
sys/netinet/in_pcb.h
sys/netinet6/in6_pcb.c

index 610b91d..5eda7fd 100644 (file)
@@ -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);
index 1d67469..e16647f 100644 (file)
@@ -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 *);
index ac10047..88b6e60 100644 (file)
@@ -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);