raw_usrreq.c revision 1541
11541Srgrimes/* 21541Srgrimes * Copyright (c) 1980, 1986, 1993 31541Srgrimes * The Regents of the University of California. All rights reserved. 41541Srgrimes * 51541Srgrimes * Redistribution and use in source and binary forms, with or without 61541Srgrimes * modification, are permitted provided that the following conditions 71541Srgrimes * are met: 81541Srgrimes * 1. Redistributions of source code must retain the above copyright 91541Srgrimes * notice, this list of conditions and the following disclaimer. 101541Srgrimes * 2. Redistributions in binary form must reproduce the above copyright 111541Srgrimes * notice, this list of conditions and the following disclaimer in the 121541Srgrimes * documentation and/or other materials provided with the distribution. 131541Srgrimes * 3. All advertising materials mentioning features or use of this software 141541Srgrimes * must display the following acknowledgement: 151541Srgrimes * This product includes software developed by the University of 161541Srgrimes * California, Berkeley and its contributors. 171541Srgrimes * 4. Neither the name of the University nor the names of its contributors 181541Srgrimes * may be used to endorse or promote products derived from this software 191541Srgrimes * without specific prior written permission. 201541Srgrimes * 211541Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 221541Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 231541Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 241541Srgrimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 251541Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 261541Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 271541Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 281541Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 291541Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 301541Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 311541Srgrimes * SUCH DAMAGE. 321541Srgrimes * 331541Srgrimes * @(#)raw_usrreq.c 8.1 (Berkeley) 6/10/93 341541Srgrimes */ 351541Srgrimes 361541Srgrimes#include <sys/param.h> 371541Srgrimes#include <sys/mbuf.h> 381541Srgrimes#include <sys/domain.h> 391541Srgrimes#include <sys/protosw.h> 401541Srgrimes#include <sys/socket.h> 411541Srgrimes#include <sys/socketvar.h> 421541Srgrimes#include <sys/errno.h> 431541Srgrimes 441541Srgrimes#include <net/if.h> 451541Srgrimes#include <net/route.h> 461541Srgrimes#include <net/netisr.h> 471541Srgrimes#include <net/raw_cb.h> 481541Srgrimes 491541Srgrimes/* 501541Srgrimes * Initialize raw connection block q. 511541Srgrimes */ 521541Srgrimesvoid 531541Srgrimesraw_init() 541541Srgrimes{ 551541Srgrimes 561541Srgrimes rawcb.rcb_next = rawcb.rcb_prev = &rawcb; 571541Srgrimes} 581541Srgrimes 591541Srgrimes 601541Srgrimes/* 611541Srgrimes * Raw protocol input routine. Find the socket 621541Srgrimes * associated with the packet(s) and move them over. If 631541Srgrimes * nothing exists for this packet, drop it. 641541Srgrimes */ 651541Srgrimes/* 661541Srgrimes * Raw protocol interface. 671541Srgrimes */ 681541Srgrimesvoid 691541Srgrimesraw_input(m0, proto, src, dst) 701541Srgrimes struct mbuf *m0; 711541Srgrimes register struct sockproto *proto; 721541Srgrimes struct sockaddr *src, *dst; 731541Srgrimes{ 741541Srgrimes register struct rawcb *rp; 751541Srgrimes register struct mbuf *m = m0; 761541Srgrimes register int sockets = 0; 771541Srgrimes struct socket *last; 781541Srgrimes 791541Srgrimes last = 0; 801541Srgrimes for (rp = rawcb.rcb_next; rp != &rawcb; rp = rp->rcb_next) { 811541Srgrimes if (rp->rcb_proto.sp_family != proto->sp_family) 821541Srgrimes continue; 831541Srgrimes if (rp->rcb_proto.sp_protocol && 841541Srgrimes rp->rcb_proto.sp_protocol != proto->sp_protocol) 851541Srgrimes continue; 861541Srgrimes /* 871541Srgrimes * We assume the lower level routines have 881541Srgrimes * placed the address in a canonical format 891541Srgrimes * suitable for a structure comparison. 901541Srgrimes * 911541Srgrimes * Note that if the lengths are not the same 921541Srgrimes * the comparison will fail at the first byte. 931541Srgrimes */ 941541Srgrimes#define equal(a1, a2) \ 951541Srgrimes (bcmp((caddr_t)(a1), (caddr_t)(a2), a1->sa_len) == 0) 961541Srgrimes if (rp->rcb_laddr && !equal(rp->rcb_laddr, dst)) 971541Srgrimes continue; 981541Srgrimes if (rp->rcb_faddr && !equal(rp->rcb_faddr, src)) 991541Srgrimes continue; 1001541Srgrimes if (last) { 1011541Srgrimes struct mbuf *n; 1021541Srgrimes if (n = m_copy(m, 0, (int)M_COPYALL)) { 1031541Srgrimes if (sbappendaddr(&last->so_rcv, src, 1041541Srgrimes n, (struct mbuf *)0) == 0) 1051541Srgrimes /* should notify about lost packet */ 1061541Srgrimes m_freem(n); 1071541Srgrimes else { 1081541Srgrimes sorwakeup(last); 1091541Srgrimes sockets++; 1101541Srgrimes } 1111541Srgrimes } 1121541Srgrimes } 1131541Srgrimes last = rp->rcb_socket; 1141541Srgrimes } 1151541Srgrimes if (last) { 1161541Srgrimes if (sbappendaddr(&last->so_rcv, src, 1171541Srgrimes m, (struct mbuf *)0) == 0) 1181541Srgrimes m_freem(m); 1191541Srgrimes else { 1201541Srgrimes sorwakeup(last); 1211541Srgrimes sockets++; 1221541Srgrimes } 1231541Srgrimes } else 1241541Srgrimes m_freem(m); 1251541Srgrimes} 1261541Srgrimes 1271541Srgrimes/*ARGSUSED*/ 1281541Srgrimesvoid 1291541Srgrimesraw_ctlinput(cmd, arg) 1301541Srgrimes int cmd; 1311541Srgrimes struct sockaddr *arg; 1321541Srgrimes{ 1331541Srgrimes 1341541Srgrimes if (cmd < 0 || cmd > PRC_NCMDS) 1351541Srgrimes return; 1361541Srgrimes /* INCOMPLETE */ 1371541Srgrimes} 1381541Srgrimes 1391541Srgrimes/*ARGSUSED*/ 1401541Srgrimesint 1411541Srgrimesraw_usrreq(so, req, m, nam, control) 1421541Srgrimes struct socket *so; 1431541Srgrimes int req; 1441541Srgrimes struct mbuf *m, *nam, *control; 1451541Srgrimes{ 1461541Srgrimes register struct rawcb *rp = sotorawcb(so); 1471541Srgrimes register int error = 0; 1481541Srgrimes int len; 1491541Srgrimes 1501541Srgrimes if (req == PRU_CONTROL) 1511541Srgrimes return (EOPNOTSUPP); 1521541Srgrimes if (control && control->m_len) { 1531541Srgrimes error = EOPNOTSUPP; 1541541Srgrimes goto release; 1551541Srgrimes } 1561541Srgrimes if (rp == 0) { 1571541Srgrimes error = EINVAL; 1581541Srgrimes goto release; 1591541Srgrimes } 1601541Srgrimes switch (req) { 1611541Srgrimes 1621541Srgrimes /* 1631541Srgrimes * Allocate a raw control block and fill in the 1641541Srgrimes * necessary info to allow packets to be routed to 1651541Srgrimes * the appropriate raw interface routine. 1661541Srgrimes */ 1671541Srgrimes case PRU_ATTACH: 1681541Srgrimes if ((so->so_state & SS_PRIV) == 0) { 1691541Srgrimes error = EACCES; 1701541Srgrimes break; 1711541Srgrimes } 1721541Srgrimes error = raw_attach(so, (int)nam); 1731541Srgrimes break; 1741541Srgrimes 1751541Srgrimes /* 1761541Srgrimes * Destroy state just before socket deallocation. 1771541Srgrimes * Flush data or not depending on the options. 1781541Srgrimes */ 1791541Srgrimes case PRU_DETACH: 1801541Srgrimes if (rp == 0) { 1811541Srgrimes error = ENOTCONN; 1821541Srgrimes break; 1831541Srgrimes } 1841541Srgrimes raw_detach(rp); 1851541Srgrimes break; 1861541Srgrimes 1871541Srgrimes#ifdef notdef 1881541Srgrimes /* 1891541Srgrimes * If a socket isn't bound to a single address, 1901541Srgrimes * the raw input routine will hand it anything 1911541Srgrimes * within that protocol family (assuming there's 1921541Srgrimes * nothing else around it should go to). 1931541Srgrimes */ 1941541Srgrimes case PRU_CONNECT: 1951541Srgrimes if (rp->rcb_faddr) { 1961541Srgrimes error = EISCONN; 1971541Srgrimes break; 1981541Srgrimes } 1991541Srgrimes nam = m_copym(nam, 0, M_COPYALL, M_WAIT); 2001541Srgrimes rp->rcb_faddr = mtod(nam, struct sockaddr *); 2011541Srgrimes soisconnected(so); 2021541Srgrimes break; 2031541Srgrimes 2041541Srgrimes case PRU_BIND: 2051541Srgrimes if (rp->rcb_laddr) { 2061541Srgrimes error = EINVAL; /* XXX */ 2071541Srgrimes break; 2081541Srgrimes } 2091541Srgrimes error = raw_bind(so, nam); 2101541Srgrimes break; 2111541Srgrimes#endif 2121541Srgrimes 2131541Srgrimes case PRU_CONNECT2: 2141541Srgrimes error = EOPNOTSUPP; 2151541Srgrimes goto release; 2161541Srgrimes 2171541Srgrimes case PRU_DISCONNECT: 2181541Srgrimes if (rp->rcb_faddr == 0) { 2191541Srgrimes error = ENOTCONN; 2201541Srgrimes break; 2211541Srgrimes } 2221541Srgrimes raw_disconnect(rp); 2231541Srgrimes soisdisconnected(so); 2241541Srgrimes break; 2251541Srgrimes 2261541Srgrimes /* 2271541Srgrimes * Mark the connection as being incapable of further input. 2281541Srgrimes */ 2291541Srgrimes case PRU_SHUTDOWN: 2301541Srgrimes socantsendmore(so); 2311541Srgrimes break; 2321541Srgrimes 2331541Srgrimes /* 2341541Srgrimes * Ship a packet out. The appropriate raw output 2351541Srgrimes * routine handles any massaging necessary. 2361541Srgrimes */ 2371541Srgrimes case PRU_SEND: 2381541Srgrimes if (nam) { 2391541Srgrimes if (rp->rcb_faddr) { 2401541Srgrimes error = EISCONN; 2411541Srgrimes break; 2421541Srgrimes } 2431541Srgrimes rp->rcb_faddr = mtod(nam, struct sockaddr *); 2441541Srgrimes } else if (rp->rcb_faddr == 0) { 2451541Srgrimes error = ENOTCONN; 2461541Srgrimes break; 2471541Srgrimes } 2481541Srgrimes error = (*so->so_proto->pr_output)(m, so); 2491541Srgrimes m = NULL; 2501541Srgrimes if (nam) 2511541Srgrimes rp->rcb_faddr = 0; 2521541Srgrimes break; 2531541Srgrimes 2541541Srgrimes case PRU_ABORT: 2551541Srgrimes raw_disconnect(rp); 2561541Srgrimes sofree(so); 2571541Srgrimes soisdisconnected(so); 2581541Srgrimes break; 2591541Srgrimes 2601541Srgrimes case PRU_SENSE: 2611541Srgrimes /* 2621541Srgrimes * stat: don't bother with a blocksize. 2631541Srgrimes */ 2641541Srgrimes return (0); 2651541Srgrimes 2661541Srgrimes /* 2671541Srgrimes * Not supported. 2681541Srgrimes */ 2691541Srgrimes case PRU_RCVOOB: 2701541Srgrimes case PRU_RCVD: 2711541Srgrimes return(EOPNOTSUPP); 2721541Srgrimes 2731541Srgrimes case PRU_LISTEN: 2741541Srgrimes case PRU_ACCEPT: 2751541Srgrimes case PRU_SENDOOB: 2761541Srgrimes error = EOPNOTSUPP; 2771541Srgrimes break; 2781541Srgrimes 2791541Srgrimes case PRU_SOCKADDR: 2801541Srgrimes if (rp->rcb_laddr == 0) { 2811541Srgrimes error = EINVAL; 2821541Srgrimes break; 2831541Srgrimes } 2841541Srgrimes len = rp->rcb_laddr->sa_len; 2851541Srgrimes bcopy((caddr_t)rp->rcb_laddr, mtod(nam, caddr_t), (unsigned)len); 2861541Srgrimes nam->m_len = len; 2871541Srgrimes break; 2881541Srgrimes 2891541Srgrimes case PRU_PEERADDR: 2901541Srgrimes if (rp->rcb_faddr == 0) { 2911541Srgrimes error = ENOTCONN; 2921541Srgrimes break; 2931541Srgrimes } 2941541Srgrimes len = rp->rcb_faddr->sa_len; 2951541Srgrimes bcopy((caddr_t)rp->rcb_faddr, mtod(nam, caddr_t), (unsigned)len); 2961541Srgrimes nam->m_len = len; 2971541Srgrimes break; 2981541Srgrimes 2991541Srgrimes default: 3001541Srgrimes panic("raw_usrreq"); 3011541Srgrimes } 3021541Srgrimesrelease: 3031541Srgrimes if (m != NULL) 3041541Srgrimes m_freem(m); 3051541Srgrimes return (error); 3061541Srgrimes} 307