123162Smckusick /* 229068Smckusick * Copyright (c) 1980, 1986 Regents of the University of California. 333183Sbostic * All rights reserved. 423162Smckusick * 5*44465Sbostic * %sccs.include.redist.c% 633183Sbostic * 7*44465Sbostic * @(#)raw_usrreq.c 7.9 (Berkeley) 06/28/90 823162Smckusick */ 95121Swnj 1017037Sbloom #include "param.h" 1117037Sbloom #include "mbuf.h" 1217037Sbloom #include "domain.h" 1317037Sbloom #include "protosw.h" 1417037Sbloom #include "socket.h" 1517037Sbloom #include "socketvar.h" 1617037Sbloom #include "errno.h" 1710890Ssam 1817037Sbloom #include "if.h" 1917037Sbloom #include "route.h" 2017037Sbloom #include "netisr.h" 2117037Sbloom #include "raw_cb.h" 225121Swnj 2337500Smckusick #include "machine/mtpr.h" 2410890Ssam 255121Swnj /* 265612Swnj * Initialize raw connection block q. 276211Swnj */ 285612Swnj raw_init() 295612Swnj { 306211Swnj 315612Swnj rawcb.rcb_next = rawcb.rcb_prev = &rawcb; 326211Swnj rawintrq.ifq_maxlen = IFQ_MAXLEN; 335612Swnj } 345612Swnj 3537472Ssklower 365612Swnj /* 3737472Ssklower * Raw protocol input routine. Find the socket 3837472Ssklower * associated with the packet(s) and move them over. If 3937472Ssklower * nothing exists for this packet, drop it. 4037472Ssklower */ 4137472Ssklower /* 425121Swnj * Raw protocol interface. 435121Swnj */ 446529Ssam raw_input(m0, proto, src, dst) 455612Swnj struct mbuf *m0; 4639181Ssklower register struct sockproto *proto; 476529Ssam struct sockaddr *src, *dst; 485121Swnj { 495612Swnj register struct rawcb *rp; 5037472Ssklower register struct mbuf *m = m0; 5139181Ssklower register int sockets = 0; 525612Swnj struct socket *last; 535121Swnj 545612Swnj last = 0; 555612Swnj for (rp = rawcb.rcb_next; rp != &rawcb; rp = rp->rcb_next) { 5637472Ssklower if (rp->rcb_proto.sp_family != proto->sp_family) 575612Swnj continue; 5821769Skarels if (rp->rcb_proto.sp_protocol && 5937472Ssklower rp->rcb_proto.sp_protocol != proto->sp_protocol) 605612Swnj continue; 615612Swnj /* 625612Swnj * We assume the lower level routines have 635612Swnj * placed the address in a canonical format 646509Ssam * suitable for a structure comparison. 6537472Ssklower * 6637472Ssklower * Note that if the lengths are not the same 6737472Ssklower * the comparison will fail at the first byte. 685612Swnj */ 6937472Ssklower #define equal(a1, a2) \ 7037472Ssklower (bcmp((caddr_t)(a1), (caddr_t)(a2), a1->sa_len) == 0) 7137472Ssklower if (rp->rcb_laddr && !equal(rp->rcb_laddr, dst)) 725612Swnj continue; 7337472Ssklower if (rp->rcb_faddr && !equal(rp->rcb_faddr, src)) 746509Ssam continue; 755612Swnj if (last) { 765612Swnj struct mbuf *n; 7737472Ssklower if (n = m_copy(m, 0, (int)M_COPYALL)) { 7837472Ssklower if (sbappendaddr(&last->so_rcv, src, 7921531Skarels n, (struct mbuf *)0) == 0) 8021531Skarels /* should notify about lost packet */ 8121531Skarels m_freem(n); 8239181Ssklower else { 8321531Skarels sorwakeup(last); 8439181Ssklower sockets++; 8539181Ssklower } 865646Ssam } 875612Swnj } 886509Ssam last = rp->rcb_socket; 895612Swnj } 906584Ssam if (last) { 9137472Ssklower if (sbappendaddr(&last->so_rcv, src, 9237472Ssklower m, (struct mbuf *)0) == 0) 9337472Ssklower m_freem(m); 9439181Ssklower else { 9521531Skarels sorwakeup(last); 9639181Ssklower sockets++; 9739181Ssklower } 9821531Skarels } else 9921531Skarels m_freem(m); 10039181Ssklower return (sockets); 1015121Swnj } 1025121Swnj 1038636Sroot /*ARGSUSED*/ 1046584Ssam raw_ctlinput(cmd, arg) 1056584Ssam int cmd; 10626379Skarels struct sockaddr *arg; 1076584Ssam { 1086591Ssam 1096591Ssam if (cmd < 0 || cmd > PRC_NCMDS) 1106591Ssam return; 1118636Sroot /* INCOMPLETE */ 1126584Ssam } 1136584Ssam 1145121Swnj /*ARGSUSED*/ 11540787Ssklower raw_usrreq(so, req, m, nam, control) 1165121Swnj struct socket *so; 1175121Swnj int req; 11840787Ssklower struct mbuf *m, *nam, *control; 1195121Swnj { 1205612Swnj register struct rawcb *rp = sotorawcb(so); 12112783Ssam register int error = 0; 12237472Ssklower int len; 1235121Swnj 12425501Skarels if (req == PRU_CONTROL) 12525501Skarels return (EOPNOTSUPP); 12640787Ssklower if (control && control->m_len) { 12712783Ssam error = EOPNOTSUPP; 12812783Ssam goto release; 12912783Ssam } 13037472Ssklower if (rp == 0) { 13112783Ssam error = EINVAL; 13212783Ssam goto release; 13312783Ssam } 1345612Swnj switch (req) { 1355612Swnj 1365612Swnj /* 1375612Swnj * Allocate a raw control block and fill in the 1385612Swnj * necessary info to allow packets to be routed to 1395612Swnj * the appropriate raw interface routine. 1405612Swnj */ 1415612Swnj case PRU_ATTACH: 14212783Ssam if ((so->so_state & SS_PRIV) == 0) { 14312783Ssam error = EACCES; 14413116Ssam break; 14512783Ssam } 14621769Skarels error = raw_attach(so, (int)nam); 1475612Swnj break; 1485612Swnj 1495612Swnj /* 1505612Swnj * Destroy state just before socket deallocation. 1515612Swnj * Flush data or not depending on the options. 1525612Swnj */ 1535612Swnj case PRU_DETACH: 15412783Ssam if (rp == 0) { 15512783Ssam error = ENOTCONN; 15613116Ssam break; 15712783Ssam } 1585612Swnj raw_detach(rp); 1595612Swnj break; 1605612Swnj 16137472Ssklower #ifdef notdef 1625612Swnj /* 1635612Swnj * If a socket isn't bound to a single address, 1645612Swnj * the raw input routine will hand it anything 1655612Swnj * within that protocol family (assuming there's 1665612Swnj * nothing else around it should go to). 1675612Swnj */ 1685612Swnj case PRU_CONNECT: 16937472Ssklower if (rp->rcb_faddr) { 17012783Ssam error = EISCONN; 17113116Ssam break; 17212783Ssam } 17337472Ssklower nam = m_copym(nam, 0, M_COPYALL, M_WAIT); 17437472Ssklower rp->rcb_faddr = mtod(nam, struct sockaddr *); 1755612Swnj soisconnected(so); 1765612Swnj break; 1775612Swnj 17812783Ssam case PRU_BIND: 17937472Ssklower if (rp->rcb_laddr) { 18012783Ssam error = EINVAL; /* XXX */ 18113116Ssam break; 18212783Ssam } 18312783Ssam error = raw_bind(so, nam); 18412783Ssam break; 18537472Ssklower #endif 18612783Ssam 18737472Ssklower case PRU_CONNECT2: 18837472Ssklower error = EOPNOTSUPP; 18937472Ssklower goto release; 19037472Ssklower 1915612Swnj case PRU_DISCONNECT: 19237472Ssklower if (rp->rcb_faddr == 0) { 19312783Ssam error = ENOTCONN; 19413116Ssam break; 19512783Ssam } 1965612Swnj raw_disconnect(rp); 1975612Swnj soisdisconnected(so); 1985612Swnj break; 1995612Swnj 2005612Swnj /* 2015612Swnj * Mark the connection as being incapable of further input. 2025612Swnj */ 2035612Swnj case PRU_SHUTDOWN: 2045612Swnj socantsendmore(so); 2055612Swnj break; 2065612Swnj 2075612Swnj /* 2085612Swnj * Ship a packet out. The appropriate raw output 2095612Swnj * routine handles any massaging necessary. 2105612Swnj */ 2115612Swnj case PRU_SEND: 2128395Swnj if (nam) { 21337472Ssklower if (rp->rcb_faddr) { 21412783Ssam error = EISCONN; 21513116Ssam break; 21612783Ssam } 21737472Ssklower rp->rcb_faddr = mtod(nam, struct sockaddr *); 21837472Ssklower } else if (rp->rcb_faddr == 0) { 21912783Ssam error = ENOTCONN; 22013116Ssam break; 22112783Ssam } 2226505Ssam error = (*so->so_proto->pr_output)(m, so); 22312783Ssam m = NULL; 2248395Swnj if (nam) 22537472Ssklower rp->rcb_faddr = 0; 2265612Swnj break; 2275612Swnj 2285612Swnj case PRU_ABORT: 2295612Swnj raw_disconnect(rp); 2305612Swnj sofree(so); 2315612Swnj soisdisconnected(so); 2325612Swnj break; 2335612Swnj 23416974Skarels case PRU_SENSE: 23516974Skarels /* 23616974Skarels * stat: don't bother with a blocksize. 23716974Skarels */ 23816974Skarels return (0); 23916974Skarels 2405612Swnj /* 2415612Swnj * Not supported. 2425612Swnj */ 24316773Sbloom case PRU_RCVOOB: 2445612Swnj case PRU_RCVD: 24516773Sbloom return(EOPNOTSUPP); 24616773Sbloom 24725221Skarels case PRU_LISTEN: 24816773Sbloom case PRU_ACCEPT: 2495612Swnj case PRU_SENDOOB: 2505612Swnj error = EOPNOTSUPP; 2515612Swnj break; 2525612Swnj 2536509Ssam case PRU_SOCKADDR: 25437472Ssklower if (rp->rcb_laddr == 0) { 25537472Ssklower error = EINVAL; 25637472Ssklower break; 25737472Ssklower } 25837472Ssklower len = rp->rcb_laddr->sa_len; 25937472Ssklower bcopy((caddr_t)rp->rcb_laddr, mtod(nam, caddr_t), (unsigned)len); 26037472Ssklower nam->m_len = len; 2616509Ssam break; 2626509Ssam 26314122Ssam case PRU_PEERADDR: 26437472Ssklower if (rp->rcb_faddr == 0) { 26537472Ssklower error = ENOTCONN; 26637472Ssklower break; 26737472Ssklower } 26837472Ssklower len = rp->rcb_faddr->sa_len; 26937472Ssklower bcopy((caddr_t)rp->rcb_faddr, mtod(nam, caddr_t), (unsigned)len); 27037472Ssklower nam->m_len = len; 27114122Ssam break; 27214122Ssam 2735612Swnj default: 2745612Swnj panic("raw_usrreq"); 2755612Swnj } 27612783Ssam release: 27712783Ssam if (m != NULL) 27812783Ssam m_freem(m); 2795612Swnj return (error); 2805121Swnj } 28137472Ssklower 28237472Ssklower rawintr() {} /* XXX - referenced by locore. will soon go away */ 283