/* $OpenBSD: raw_usrreq.c,v 1.31 2017/03/13 20:18:21 claudio Exp $ */ /* $NetBSD: raw_usrreq.c,v 1.11 1996/02/13 22:00:43 christos Exp $ */ /* * Copyright (c) 1980, 1986, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)raw_usrreq.c 8.1 (Berkeley) 6/10/93 */ #include #include #include #include #include #include #include #include #include #include #include /* * Initialize raw connection block q. */ void raw_init(void) { LIST_INIT(&rawcb); } int raw_usrreq(struct socket *so, int req, struct mbuf *m, struct mbuf *nam, struct mbuf *control, struct proc *p) { struct rawcb *rp = sotorawcb(so); int error = 0; int len; soassertlocked(so); if (req == PRU_CONTROL) return (EOPNOTSUPP); if (control && control->m_len) { m_freem(m); return (EOPNOTSUPP); } if (rp == 0) { m_freem(m); return (EINVAL); } switch (req) { /* * Destroy state just before socket deallocation. * Flush data or not depending on the options. */ case PRU_DETACH: if (rp == 0) { error = ENOTCONN; break; } raw_detach(rp); break; case PRU_CONNECT: case PRU_BIND: case PRU_CONNECT2: error = EOPNOTSUPP; break; case PRU_DISCONNECT: if (rp->rcb_faddr == 0) { error = ENOTCONN; break; } raw_disconnect(rp); soisdisconnected(so); break; /* * Mark the connection as being incapable of further input. */ case PRU_SHUTDOWN: socantsendmore(so); break; /* * Ship a packet out. The appropriate raw output * routine handles any massaging necessary. */ case PRU_SEND: if (nam) { if (rp->rcb_faddr) { error = EISCONN; break; } rp->rcb_faddr = mtod(nam, struct sockaddr *); } else if (rp->rcb_faddr == 0) { error = ENOTCONN; break; } error = (*so->so_proto->pr_output)(m, so, NULL, NULL); m = NULL; if (nam) rp->rcb_faddr = 0; break; case PRU_ABORT: raw_disconnect(rp); sofree(so); soisdisconnected(so); break; case PRU_SENSE: /* * stat: don't bother with a blocksize. */ return (0); /* * Not supported. */ case PRU_RCVOOB: case PRU_RCVD: return (EOPNOTSUPP); case PRU_LISTEN: case PRU_ACCEPT: case PRU_SENDOOB: error = EOPNOTSUPP; break; case PRU_SOCKADDR: if (rp->rcb_laddr == 0) { error = EINVAL; break; } len = rp->rcb_laddr->sa_len; bcopy((caddr_t)rp->rcb_laddr, mtod(nam, caddr_t), (unsigned)len); nam->m_len = len; break; case PRU_PEERADDR: if (rp->rcb_faddr == 0) { error = ENOTCONN; break; } len = rp->rcb_faddr->sa_len; bcopy((caddr_t)rp->rcb_faddr, mtod(nam, caddr_t), (unsigned)len); nam->m_len = len; break; default: panic("raw_usrreq"); } m_freem(m); return (error); }