+in_pcballoc(so, head)
+ struct socket *so;
+ struct inpcb *head;
+{
+ struct mbuf *m;
+ register struct inpcb *inp;
+
+ m = m_getclr(M_DONTWAIT);
+ if (m == 0)
+ return (ENOBUFS);
+ inp = mtod(m, struct inpcb *);
+ inp->inp_head = head;
+ inp->inp_socket = so;
+ insque(inp, head);
+ so->so_pcb = (caddr_t)inp;
+ return (0);
+}
+
+in_pcbbind(inp, nam)
+ register struct inpcb *inp;
+ struct mbuf *nam;
+{
+ register struct socket *so = inp->inp_socket;
+ register struct inpcb *head = inp->inp_head;
+ register struct sockaddr_in *sin;
+ u_short lport = 0;
+
+ if (ifnet == 0)
+ return (EADDRNOTAVAIL);
+ if (inp->inp_lport || inp->inp_laddr.s_addr)
+ return (EINVAL);
+ if (nam == 0)
+ goto noname;
+ sin = mtod(nam, struct sockaddr_in *);
+ if (nam->m_len != sizeof (*sin))
+ return (EINVAL);
+ if (sin->sin_addr.s_addr) {
+ int tport = sin->sin_port;
+
+ sin->sin_port = 0; /* yech... */
+ if (if_ifwithaddr((struct sockaddr *)sin) == 0)
+ return (EADDRNOTAVAIL);
+ sin->sin_port = tport;
+ }
+ lport = sin->sin_port;
+ if (lport) {
+ u_short aport = lport;
+ int wild = 0;
+
+#if vax
+ aport = htons(aport);
+#endif
+ /* GROSS */
+ if (aport < IPPORT_RESERVED && u.u_uid != 0)
+ return (EACCES);
+ if ((so->so_proto->pr_flags & PR_CONNREQUIRED) == 0)
+ wild = INPLOOKUP_WILDCARD;
+ if (in_pcblookup(head,
+ zeroin_addr, 0, sin->sin_addr, lport, wild))
+ return (EADDRINUSE);
+ }
+ inp->inp_laddr = sin->sin_addr;
+noname:
+ if (lport == 0)
+ do {
+ if (head->inp_lport++ < IPPORT_RESERVED)
+ head->inp_lport = IPPORT_RESERVED;
+ lport = htons(head->inp_lport);
+ } while (in_pcblookup(head,
+ zeroin_addr, 0, inp->inp_laddr, lport, 0));
+ inp->inp_lport = lport;
+ return (0);
+}
+
+/*
+ * Connect from a socket to a specified address.
+ * Both address and port must be specified in argument sin.
+ * If don't have a local address for this socket yet,
+ * then pick one.
+ */
+in_pcbconnect(inp, nam)