+/*
+ * When an attempt at a new connection is noted on a socket
+ * which accepts connections, sonewconn is called. If the
+ * connection is possible (subject to space constraints, etc.)
+ * then we allocate a new structure, propoerly linked into the
+ * data structure of the original socket, and return this.
+ */
+struct socket *
+sonewconn(head)
+ register struct socket *head;
+{
+ register struct socket *so;
+ register struct mbuf *m;
+
+ if (head->so_qlen + head->so_q0len > 3 * head->so_qlimit / 2)
+ goto bad;
+ m = m_getclr(M_DONTWAIT, MT_SOCKET);
+ if (m == NULL)
+ goto bad;
+ so = mtod(m, struct socket *);
+ so->so_type = head->so_type;
+ so->so_options = head->so_options &~ SO_ACCEPTCONN;
+ so->so_linger = head->so_linger;
+ so->so_state = head->so_state | SS_NOFDREF;
+ so->so_proto = head->so_proto;
+ so->so_timeo = head->so_timeo;
+ so->so_pgrp = head->so_pgrp;
+ soqinsque(head, so, 0);
+ if ((*so->so_proto->pr_usrreq)(so, PRU_ATTACH,
+ (struct mbuf *)0, (struct mbuf *)0, (struct mbuf *)0)) {
+ (void) soqremque(so, 0);
+ (void) m_free(m);
+ goto bad;
+ }
+ return (so);
+bad:
+ return ((struct socket *)0);
+}
+
+soqinsque(head, so, q)
+ register struct socket *head, *so;
+ int q;
+{
+
+ so->so_head = head;
+ if (q == 0) {
+ head->so_q0len++;
+ so->so_q0 = head->so_q0;
+ head->so_q0 = so;
+ } else {
+ head->so_qlen++;
+ so->so_q = head->so_q;
+ head->so_q = so;
+ }
+}
+
+soqremque(so, q)
+ register struct socket *so;
+ int q;
+{
+ register struct socket *head, *prev, *next;
+
+ head = so->so_head;
+ prev = head;
+ for (;;) {
+ next = q ? prev->so_q : prev->so_q0;
+ if (next == so)
+ break;
+ if (next == head)
+ return (0);
+ prev = next;
+ }
+ if (q == 0) {
+ prev->so_q0 = next->so_q0;
+ head->so_q0len--;
+ } else {
+ prev->so_q = next->so_q;
+ head->so_qlen--;
+ }
+ next->so_q0 = next->so_q = 0;
+ next->so_head = 0;
+ return (1);
+}
+