handles new uba stuff and fix page freeing problem
[unix-history] / usr / src / sys / netinet / in_pcb.c
index 930704f..977454b 100644 (file)
@@ -1,4 +1,4 @@
-/* in_pcb.c 4.11 81/12/02 */
+/* in_pcb.c 4.15 81/12/21 */
 
 #include "../h/param.h"
 #include "../h/systm.h"
 
 #include "../h/param.h"
 #include "../h/systm.h"
  * the disconnect is in progress.  We notice that this has happened
  * when the disconnect is complete, and perform the PRU_DETACH operation,
  * freeing the socket.
  * the disconnect is in progress.  We notice that this has happened
  * when the disconnect is complete, and perform the PRU_DETACH operation,
  * freeing the socket.
+ *
+ * TODO:
+ *     use hashing
  */
  */
+struct in_addr zeroin_addr;
 
 /*
  * Allocate a protocol control block, space
 
 /*
  * Allocate a protocol control block, space
@@ -54,32 +58,28 @@ in_pcbattach(so, head, sndcc, rcvcc, sin)
        struct sockaddr_in *sin;
 {
        struct mbuf *m;
        struct sockaddr_in *sin;
 {
        struct mbuf *m;
-       register struct inpcb *inp, *xp;
+       register struct inpcb *inp;
        struct ifnet *ifp;
        struct ifnet *ifp;
-       u_long lport;
+       u_short lport;
 
 COUNT(IN_PCBATTACH);
        if (sin) {
                if (sin->sin_family != AF_INET)
                        return (EAFNOSUPPORT);
 
 COUNT(IN_PCBATTACH);
        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);
                ifp = if_ifwithaddr(sin->sin_addr);
-               if (ifp == 0)
-                       return (EADDRNOTAVAIL);
                lport = sin->sin_port;
                lport = sin->sin_port;
-               if (lport) {
-                       xp = head->inp_next;
-                       for (; xp != head; xp = xp->inp_next) 
-                               if (xp->inp_laddr.s_addr ==
-                                   sin->sin_addr.s_addr &&
-                                   xp->inp_lport == lport &&
-                                   xp->inp_faddr.s_addr == 0)
-                                       return (EADDRINUSE);
-               }
+               if (lport &&
+                   in_pcblookup(head, zeroin_addr, 0, sin->sin_addr, lport))
+                       return (EADDRINUSE);
        } else {
        } else {
-               ifp = if_ifwithaddr(ifnet->if_addr);
+               ifp = ifnet;
                lport = 0;
        }
                lport = 0;
        }
-       m = m_getclr(M_WAIT);
+       if (ifp == 0)
+               return (EADDRNOTAVAIL);
+       m = m_getclr(0);
        if (m == 0)
                return (ENOBUFS);
        if (sbreserve(&so->so_snd, sndcc) == 0)
        if (m == 0)
                return (ENOBUFS);
        if (sbreserve(&so->so_snd, sndcc) == 0)
@@ -87,19 +87,16 @@ COUNT(IN_PCBATTACH);
        if (sbreserve(&so->so_rcv, rcvcc) == 0)
                goto bad2;
        inp = mtod(m, struct inpcb *);
        if (sbreserve(&so->so_rcv, rcvcc) == 0)
                goto bad2;
        inp = mtod(m, struct inpcb *);
+       inp->inp_head = head;
        inp->inp_laddr = ifp->if_addr;
        inp->inp_laddr = ifp->if_addr;
-       if (lport)
-               goto gotport;
-again:
-       if (head->inp_lport++ < 1024)
-               head->inp_lport = 1024;
-       for (xp = head->inp_next; xp != head; xp = xp->inp_next)
-               if (xp->inp_lport == head->inp_lport)
-                       goto again;
-       lport = htons(head->inp_lport);
-gotport:
-       inp->inp_socket = so;
+       if (lport == 0)
+               do {
+                       if (head->inp_lport++ < 1024)
+                               head->inp_lport = 1024;
+                       lport = htons(head->inp_lport);
+               } while (in_pcblookup(head, zeroin_addr, 0, inp->inp_laddr, lport));
        inp->inp_lport = lport;
        inp->inp_lport = lport;
+       inp->inp_socket = so;
        insque(inp, head);
        so->so_pcb = (caddr_t)inp;
        sin = (struct sockaddr_in *)&so->so_addr;
        insque(inp, head);
        so->so_pcb = (caddr_t)inp;
        sin = (struct sockaddr_in *)&so->so_addr;
@@ -118,18 +115,32 @@ in_pcbconnect(inp, sin)
        struct inpcb *inp;
        struct sockaddr_in *sin;
 {
        struct inpcb *inp;
        struct sockaddr_in *sin;
 {
+       struct inpcb *xp;
 
 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);
-       /* should check not already in use... */
+       xp = in_pcblookup(inp->inp_head, sin->sin_addr, sin->sin_port, inp->inp_laddr, inp->inp_lport);
+       if (xp->inp_faddr.s_addr)
+               return (EADDRINUSE);
        inp->inp_faddr = sin->sin_addr;
        inp->inp_fport = sin->sin_port;
        return (0);
 }
 
        inp->inp_faddr = sin->sin_addr;
        inp->inp_fport = sin->sin_port;
        return (0);
 }
 
+in_pcbconnaddr(inp, sp)
+       struct inpcb *inp;
+       struct sockaddr *sp;
+{
+       register struct sockaddr_in *sin = (struct sockaddr_in *)sp;
+
+       sin->sin_family = AF_INET;
+       sin->sin_port = inp->inp_fport;
+       sin->sin_addr = inp->inp_faddr;
+}
+
 in_pcbdisconnect(inp)
        struct inpcb *inp;
 {
 in_pcbdisconnect(inp)
        struct inpcb *inp;
 {