multi-homing and wildcards
authorBill Joy <wnj@ucbvax.Berkeley.EDU>
Sun, 28 Feb 1982 09:48:02 +0000 (01:48 -0800)
committerBill Joy <wnj@ucbvax.Berkeley.EDU>
Sun, 28 Feb 1982 09:48:02 +0000 (01:48 -0800)
SCCS-vsn: sys/netinet/in.h 4.9
SCCS-vsn: sys/netinet/in_pcb.c 4.17
SCCS-vsn: sys/netinet/tcp_input.c 1.55
SCCS-vsn: sys/netinet/tcp_usrreq.c 1.52
SCCS-vsn: sys/netinet/udp_usrreq.c 4.20

usr/src/sys/netinet/in.h
usr/src/sys/netinet/in_pcb.c
usr/src/sys/netinet/tcp_input.c
usr/src/sys/netinet/tcp_usrreq.c
usr/src/sys/netinet/udp_usrreq.c

index e42a1ea..7bbb47b 100644 (file)
@@ -1,4 +1,4 @@
-/* in.h 4.8 82/02/03 */
+/* in.h 4.9 82/02/27 */
 
 /*
  * Constants and structures defined by the internet system,
 
 /*
  * Constants and structures defined by the internet system,
@@ -9,7 +9,7 @@
  * Protocols
  */
 #define        IPPROTO_ICMP            1               /* control message protocol */
  * Protocols
  */
 #define        IPPROTO_ICMP            1               /* control message protocol */
-#define        IPPROTO_GG              2               /* gateway^2 (deprecated) */
+#define        IPPROTO_GGP             2               /* gateway^2 (deprecated) */
 #define        IPPROTO_TCP             6               /* tcp */
 #define        IPPROTO_PUP             12              /* pup */
 #define        IPPROTO_UDP             17              /* user datagram protocol */
 #define        IPPROTO_TCP             6               /* tcp */
 #define        IPPROTO_PUP             12              /* pup */
 #define        IPPROTO_UDP             17              /* user datagram protocol */
@@ -42,6 +42,8 @@
 #define        IPPORT_TTYLINK          87
 #define        IPPORT_SUPDUP           95
 
 #define        IPPORT_TTYLINK          87
 #define        IPPORT_SUPDUP           95
 
+#define        IPPORT_RESERVED         1024
+
 /*
  * Link numbers
  */
 /*
  * Link numbers
  */
@@ -66,6 +68,8 @@ struct in_addr {
 #endif
 };
 
 #endif
 };
 
+#define        INADDR_ANY      0x00000000
+
 /*
  * Socket address, internet style.
  */
 /*
  * Socket address, internet style.
  */
index b62bc78..81e2b5d 100644 (file)
@@ -1,4 +1,4 @@
-/*     in_pcb.c        4.16    82/02/15        */
+/*     in_pcb.c        4.17    82/02/27        */
 
 #include "../h/param.h"
 #include "../h/systm.h"
 
 #include "../h/param.h"
 #include "../h/systm.h"
@@ -59,26 +59,31 @@ in_pcbattach(so, head, sndcc, rcvcc, sin)
 {
        struct mbuf *m;
        register struct inpcb *inp;
 {
        struct mbuf *m;
        register struct inpcb *inp;
-       struct ifnet *ifp;
-       u_short lport;
+       u_short lport = 0;
 
 COUNT(IN_PCBATTACH);
 
 COUNT(IN_PCBATTACH);
+       if (ifnet == 0)
+               return (EADDRNOTAVAIL);
        if (sin) {
                if (sin->sin_family != AF_INET)
                        return (EAFNOSUPPORT);
        if (sin) {
                if (sin->sin_family != AF_INET)
                        return (EAFNOSUPPORT);
-               if (ifnet && sin->sin_addr.s_addr == 0)
-                       sin->sin_addr = ifnet->if_addr;
-               ifp = if_ifwithaddr(sin->sin_addr);
+               if (sin->sin_addr.s_addr &&
+                   if_ifwithaddr(sin->sin_addr.s_addr) == 0)
+                       return (EADDRNOTAVAIL);
                lport = sin->sin_port;
                lport = sin->sin_port;
-               if (lport &&
-                   in_pcblookup(head, zeroin_addr, 0, sin->sin_addr, lport))
-                       return (EADDRINUSE);
-       } else {
-               ifp = ifnet;
-               lport = 0;
+               if (lport) {
+                       u_short aport = lport;
+#if vax
+                       aport = htons(aport);
+#endif
+                       /* GROSS */
+                       if (aport < IPPORT_RESERVED && u.u_uid != 0)
+                               return (EPERM);
+                       if (in_pcblookup(head,
+                           zeroin_addr, 0, sin->sin_addr, lport, 0))
+                               return (EADDRINUSE);
+               }
        }
        }
-       if (ifp == 0)
-               return (EADDRNOTAVAIL);
        m = m_getclr(M_DONTWAIT);
        if (m == 0)
                return (ENOBUFS);
        m = m_getclr(M_DONTWAIT);
        if (m == 0)
                return (ENOBUFS);
@@ -88,21 +93,20 @@ COUNT(IN_PCBATTACH);
                goto bad2;
        inp = mtod(m, struct inpcb *);
        inp->inp_head = head;
                goto bad2;
        inp = mtod(m, struct inpcb *);
        inp->inp_head = head;
-       inp->inp_laddr = ifp->if_addr;
+       if (sin)
+               inp->inp_laddr = sin->sin_addr;
        if (lport == 0)
                do {
        if (lport == 0)
                do {
-                       if (head->inp_lport++ < 1024)
-                               head->inp_lport = 1024;
+                       if (head->inp_lport++ < IPPORT_RESERVED)
+                               head->inp_lport = IPPORT_RESERVED;
                        lport = htons(head->inp_lport);
                        lport = htons(head->inp_lport);
-               } while (in_pcblookup(head, zeroin_addr, 0, inp->inp_laddr, lport));
+               } while (in_pcblookup(head,
+                           zeroin_addr, 0, inp->inp_laddr, lport, 0));
        inp->inp_lport = lport;
        inp->inp_socket = so;
        insque(inp, head);
        so->so_pcb = (caddr_t)inp;
        inp->inp_lport = lport;
        inp->inp_socket = so;
        insque(inp, head);
        so->so_pcb = (caddr_t)inp;
-       sin = (struct sockaddr_in *)&so->so_addr;
-       sin->sin_family = AF_INET;
-       sin->sin_addr = inp->inp_laddr;
-       sin->sin_port = inp->inp_lport;
+       in_setsockaddr(inp);
        return (0);
 bad2:
        sbrelease(&so->so_snd);
        return (0);
 bad2:
        sbrelease(&so->so_snd);
@@ -115,30 +119,36 @@ in_pcbconnect(inp, sin)
        struct inpcb *inp;
        struct sockaddr_in *sin;
 {
        struct inpcb *inp;
        struct sockaddr_in *sin;
 {
-       struct inpcb *xp;
+       struct ifnet *ifp;
 
 COUNT(IN_PCBCONNECT);
        if (sin->sin_family != AF_INET)
                return (EAFNOSUPPORT);
        if (sin->sin_addr.s_addr == 0 || sin->sin_port == 0)
                return (EADDRNOTAVAIL);
 
 COUNT(IN_PCBCONNECT);
        if (sin->sin_family != AF_INET)
                return (EAFNOSUPPORT);
        if (sin->sin_addr.s_addr == 0 || sin->sin_port == 0)
                return (EADDRNOTAVAIL);
-       xp = in_pcblookup(inp->inp_head, sin->sin_addr, sin->sin_port, inp->inp_laddr, inp->inp_lport);
-       if (xp->inp_faddr.s_addr)
+       if (inp->inp_laddr.s_addr == 0) {
+               ifp = if_ifonnetof(sin->sin_addr.s_addr);
+               if (ifp == 0)
+                       ifp = ifnet;
+               inp->inp_laddr = ifp->if_addr;
+       }
+       if (in_pcblookup(inp->inp_head,
+           sin->sin_addr, sin->sin_port, inp->inp_laddr, inp->inp_lport, 0))
                return (EADDRINUSE);
        inp->inp_faddr = sin->sin_addr;
        inp->inp_fport = sin->sin_port;
        return (0);
 }
 
                return (EADDRINUSE);
        inp->inp_faddr = sin->sin_addr;
        inp->inp_fport = sin->sin_port;
        return (0);
 }
 
-in_pcbconnaddr(inp, sp)
+in_setsockaddr(inp)
        struct inpcb *inp;
        struct inpcb *inp;
-       struct sockaddr *sp;
 {
 {
-       register struct sockaddr_in *sin = (struct sockaddr_in *)sp;
+       register struct sockaddr_in *sin =
+           (struct sockaddr_in *)&inp->inp_socket->so_addr;
 
        sin->sin_family = AF_INET;
 
        sin->sin_family = AF_INET;
-       sin->sin_port = inp->inp_fport;
-       sin->sin_addr = inp->inp_faddr;
+       sin->sin_addr = inp->inp_laddr;
+       sin->sin_port = inp->inp_lport;
 }
 
 in_pcbdisconnect(inp)
 }
 
 in_pcbdisconnect(inp)
@@ -165,29 +175,51 @@ in_pcbdetach(inp)
 /*
  * Look for a control block to accept a segment.
  * First choice is an exact address match.
 /*
  * Look for a control block to accept a segment.
  * First choice is an exact address match.
- * Second choice is a match of local address, with
- * unspecified foreign address.
+ * Second choice is a match with either the foreign or the local
+ * address specified.
+ *
+ * SHOULD ALLOW MATCH ON MULTI-HOMING ONLY
  */
 struct inpcb *
  */
 struct inpcb *
-in_pcblookup(head, faddr, fport, laddr, lport)
+in_pcblookup(head, faddr, fport, laddr, lport, enter)
        struct inpcb *head;
        struct in_addr faddr, laddr;
        u_short fport, lport;
        struct inpcb *head;
        struct in_addr faddr, laddr;
        u_short fport, lport;
+       int enter;
 {
 {
-       register struct inpcb *inp;
-       struct inpcb *match = 0;
+       register struct inpcb *inp, *match = 0;
+       int matchwild = 3, wildcard;
 
        for (inp = head->inp_next; inp != head; inp = inp->inp_next) {
 
        for (inp = head->inp_next; inp != head; inp = inp->inp_next) {
-               if (inp->inp_laddr.s_addr != laddr.s_addr ||
-                   inp->inp_lport != lport)
+               if (inp->inp_lport != lport)
                        continue;
                        continue;
-               if (inp->inp_faddr.s_addr == 0) {
-                       match = inp;
+               wildcard = 0;
+               if (inp->inp_laddr.s_addr != 0) {
+                       if (inp->inp_laddr.s_addr != laddr.s_addr)
+                               continue;
+               } else {
+                       if (laddr.s_addr != 0)
+                               wildcard++;
+               }
+               if (inp->inp_faddr.s_addr != 0) {
+                       if (inp->inp_faddr.s_addr != faddr.s_addr)
+                               continue;
+               } else {
+                       if (faddr.s_addr != 0)
+                               wildcard++;
+               }
+               if (enter == 0 && wildcard)
                        continue;
                        continue;
+               if (wildcard < matchwild) {
+                       match = inp;
+                       matchwild = wildcard;
+                       if (matchwild == 0)
+                               break;
                }
                }
-               if (inp->inp_faddr.s_addr == faddr.s_addr &&
-                   inp->inp_fport == fport)
-                       return (inp);
+       }
+       if (match && enter) {
+               match->inp_laddr = laddr;
+               in_setsockaddr(match);
        }
        return (match);
 }
        }
        return (match);
 }
index 9f5275c..1ad4f2e 100644 (file)
@@ -1,4 +1,4 @@
-/*     tcp_input.c     1.54    82/02/25        */
+/*     tcp_input.c     1.55    82/02/27        */
 
 #include "../h/param.h"
 #include "../h/systm.h"
 
 #include "../h/param.h"
 #include "../h/systm.h"
@@ -122,10 +122,11 @@ COUNT(TCP_INPUT);
 #endif
 
        /*
 #endif
 
        /*
-        * Locate pcb for segment.
+        * Locate pcb for segment.  On match, update the local
+        * address stored in the block to reflect anchoring.
         */
        inp = in_pcblookup
         */
        inp = in_pcblookup
-               (&tcb, ti->ti_src, ti->ti_sport, ti->ti_dst, ti->ti_dport);
+               (&tcb, ti->ti_src, ti->ti_sport, ti->ti_dst, ti->ti_dport, 1);
 
        /*
         * If the state is CLOSED (i.e., TCB does not exist) then
 
        /*
         * If the state is CLOSED (i.e., TCB does not exist) then
index c75b9f7..092bbb4 100644 (file)
@@ -1,4 +1,4 @@
-/* tcp_usrreq.c 1.51 82/02/25 */
+/* tcp_usrreq.c 1.52 82/02/27 */
 
 #include "../h/param.h"
 #include "../h/systm.h"
 
 #include "../h/param.h"
 #include "../h/systm.h"
@@ -154,7 +154,6 @@ COUNT(TCP_USRREQ);
         * of the peer, storing through addr.
         */
        case PRU_ACCEPT:
         * of the peer, storing through addr.
         */
        case PRU_ACCEPT:
-               in_pcbconnaddr(inp, (struct sockaddr *)addr);
                break;
 
        /*
                break;
 
        /*
index feb48b0..5be15f6 100644 (file)
@@ -1,4 +1,4 @@
-/*     udp_usrreq.c    4.19    82/01/19        */
+/*     udp_usrreq.c    4.20    82/02/27        */
 
 #include "../h/param.h"
 #include "../h/dir.h"
 
 #include "../h/param.h"
 #include "../h/dir.h"
@@ -82,10 +82,11 @@ COUNT(UDP_INPUT);
        }
 
        /*
        }
 
        /*
-        * Locate pcb for datagram.
+        * Locate pcb for datagram.  On wildcard match, update
+        * control block to anchor network and host address.
         */
        inp = in_pcblookup(&udb,
         */
        inp = in_pcblookup(&udb,
-           ui->ui_src, ui->ui_sport, ui->ui_dst, ui->ui_dport);
+           ui->ui_src, ui->ui_sport, ui->ui_dst, ui->ui_dport, 1);
        if (inp == 0)
                goto bad;
 
        if (inp == 0)
                goto bad;
 
@@ -214,8 +215,11 @@ COUNT(UDP_USRREQ);
                socantsendmore(so);
                break;
 
                socantsendmore(so);
                break;
 
-       case PRU_SEND:
+       case PRU_SEND: {
+               struct in_addr laddr;
+
                if (addr) {
                if (addr) {
+                       laddr = inp->inp_laddr;
                        if (inp->inp_faddr.s_addr)
                                return (EISCONN);
                        error = in_pcbconnect(inp, (struct sockaddr_in *)addr);
                        if (inp->inp_faddr.s_addr)
                                return (EISCONN);
                        error = in_pcbconnect(inp, (struct sockaddr_in *)addr);
@@ -226,8 +230,11 @@ COUNT(UDP_USRREQ);
                                return (ENOTCONN);
                }
                udp_output(inp, m);
                                return (ENOTCONN);
                }
                udp_output(inp, m);
-               if (addr)
+               if (addr) {
                        in_pcbdisconnect(inp);
                        in_pcbdisconnect(inp);
+                       inp->inp_laddr = laddr;
+               }
+               }
                break;
 
        case PRU_ABORT:
                break;
 
        case PRU_ABORT: