SB_EMPTY_FIXUP(&so->so_rcv);
pk_usrreq(so, req, m, nam, control)	struct socket  *so;	int             req;	register struct mbuf *m, *nam;	struct mbuf    *control;{	register struct pklcd *lcp = (struct pklcd *) so->so_pcb;	register int    error = 0;	if (req == PRU_CONTROL)		return (pk_control(so, (long) m, (caddr_t) nam,				   (struct ifnet *) control));	if (control && control->m_len) {		error = EINVAL;		goto release;	}	if (lcp == NULL && req != PRU_ATTACH) {		error = EINVAL;		goto release;	}	/*		pk_trace (pkcbhead, TR_USER, (struct pklcd *)0,			req, (struct x25_packet *)0);	*/	switch (req) {		/*		 * X.25 attaches to socket via PRU_ATTACH and allocates a		 * logical channel descriptor.  If the socket is to  receive		 * connections, then the LISTEN state is entered.		 */	case PRU_ATTACH:		if (lcp) {			error = EISCONN;			/* Socket already connected. */			break;		}		lcp = pk_attach(so);		if (lcp == 0)			error = ENOBUFS;		break;		/*		 * Detach a logical channel from the socket. If the state of		 * the channel is embryonic, simply discard it. Otherwise we		 * have to initiate a PRU_DISCONNECT which will finish later.		 */	case PRU_DETACH:		pk_disconnect(lcp);		break;		/*		 * Give the socket an address.		 */	case PRU_BIND:		if (nam->m_len == sizeof(struct x25_sockaddr))			old_to_new(nam);		error = pk_bind(lcp, nam);		break;		/*		 * Prepare to accept connections.		 */	case PRU_LISTEN:		error = pk_listen(lcp);		break;		/*		 * Initiate a CALL REQUEST to peer entity. Enter state		 * SENT_CALL and mark the socket as connecting. Set timer		 * waiting for CALL ACCEPT or CLEAR.		 */	case PRU_CONNECT:		if (nam->m_len == sizeof(struct x25_sockaddr))			old_to_new(nam);		if (pk_checksockaddr(nam))			return (EINVAL);		error = pk_connect(lcp, mtod(nam, struct sockaddr_x25 *));		break;		/*		 * Initiate a disconnect to peer entity via a CLEAR REQUEST		 * packet. The socket will be disconnected when we receive a		 * confirmation or a clear collision.		 */	case PRU_DISCONNECT:		pk_disconnect(lcp);		break;		/*		 * Accept an INCOMING CALL. Most of the work has already been		 * done by pk_input. Just return the callers address to the		 * user.		 */	case PRU_ACCEPT:		if (lcp->lcd_craddr == NULL)			break;		bcopy((caddr_t) lcp->lcd_craddr, mtod(nam, caddr_t),		      sizeof(struct sockaddr_x25));		nam->m_len = sizeof(struct sockaddr_x25);		if (lcp->lcd_flags & X25_OLDSOCKADDR)			new_to_old(nam);		break;		/*		 * After a receive, we should send a RR.		 */	case PRU_RCVD:		pk_flowcontrol(lcp, /* sbspace (&so -> so_rcv) <= */ 0, 1);		break;		/*		 * Send INTERRUPT packet.		 */	case PRU_SENDOOB:		if (m == 0) {			MGETHDR(m, M_WAITOK, MT_OOBDATA);			m->m_pkthdr.len = m->m_len = 1;			*mtod(m, octet *) = 0;		}		if (m->m_pkthdr.len > 32) {			m_freem(m);			error = EMSGSIZE;			break;		}		MCHTYPE(m, MT_OOBDATA);		/* FALLTHROUGH */		/*		 * Do send by placing data on the socket output queue.		 */	case PRU_SEND:		if (control) {			register struct cmsghdr *ch = mtod(m, struct cmsghdr *);			control->m_len -= sizeof(*ch);			control->m_data += sizeof(*ch);			error = pk_ctloutput(PRCO_SETOPT, so, ch->cmsg_level,					     ch->cmsg_type, &control);		}		if (error == 0 && m)			error = pk_send(m, lcp);		break;		/*		 * Abort a virtual circuit. For example all completed calls		 * waiting acceptance.		 */	case PRU_ABORT:		pk_disconnect(lcp);		break;		/* Begin unimplemented hooks. */	case PRU_SHUTDOWN:		error = EOPNOTSUPP;		break;	case PRU_CONTROL:		error = EOPNOTSUPP;		break;	case PRU_SENSE:#ifdef BSD4_3		((struct stat *) m)->st_blksize = so->so_snd.sb_hiwat;#else		error = EOPNOTSUPP;#endif		break;		/* End unimplemented hooks. */	case PRU_SOCKADDR:		if (lcp->lcd_ceaddr == 0)			return (EADDRNOTAVAIL);		nam->m_len = sizeof(struct sockaddr_x25);		bcopy((caddr_t) lcp->lcd_ceaddr, mtod(nam, caddr_t),		      sizeof(struct sockaddr_x25));		if (lcp->lcd_flags & X25_OLDSOCKADDR)			new_to_old(nam);		break;	case PRU_PEERADDR:		if (lcp->lcd_state != DATA_TRANSFER)			return (ENOTCONN);		nam->m_len = sizeof(struct sockaddr_x25);		bcopy(lcp->lcd_craddr ? (caddr_t) lcp->lcd_craddr :		      (caddr_t) lcp->lcd_ceaddr,		      mtod(nam, caddr_t), sizeof(struct sockaddr_x25));		if (lcp->lcd_flags & X25_OLDSOCKADDR)			new_to_old(nam);		break;		/*		 * Receive INTERRUPT packet.		 */	case PRU_RCVOOB:		if (so->so_options & SO_OOBINLINE) {			register struct mbuf *n = so->so_rcv.sb_mb;			if (n && n->m_type == MT_OOBDATA) {				unsigned        len = n->m_pkthdr.len;				so->so_rcv.sb_mb = n->m_nextpkt;				if (len != n->m_len &&				    (n = m_pullup(n, len)) == 0)					break;				m->m_len = len;				bcopy(mtod(m, caddr_t), mtod(n, caddr_t), len);				m_freem(n);			}			break;		}		m->m_len = 1;		*mtod(m, char *) = lcp->lcd_intrdata;		break;	default:		panic("pk_usrreq");	}release:	if (control != NULL)		m_freem(control);	return (error);}