123162Smckusick /* 229068Smckusick * Copyright (c) 1980, 1986 Regents of the University of California. 333183Sbostic * All rights reserved. 423162Smckusick * 544465Sbostic * %sccs.include.redist.c% 633183Sbostic * 7*61357Sbostic * @(#)raw_usrreq.c 7.13 (Berkeley) 06/04/93 823162Smckusick */ 95121Swnj 1056529Sbostic #include <sys/param.h> 1156529Sbostic #include <sys/mbuf.h> 1256529Sbostic #include <sys/domain.h> 1356529Sbostic #include <sys/protosw.h> 1456529Sbostic #include <sys/socket.h> 1556529Sbostic #include <sys/socketvar.h> 1656529Sbostic #include <sys/errno.h> 1710890Ssam 1856529Sbostic #include <net/if.h> 1956529Sbostic #include <net/route.h> 2056529Sbostic #include <net/netisr.h> 2156529Sbostic #include <net/raw_cb.h> 225121Swnj 235121Swnj /* 245612Swnj * Initialize raw connection block q. 256211Swnj */ 26*61357Sbostic void 275612Swnj raw_init() 285612Swnj { 296211Swnj 305612Swnj rawcb.rcb_next = rawcb.rcb_prev = &rawcb; 315612Swnj } 325612Swnj 3337472Ssklower 345612Swnj /* 3537472Ssklower * Raw protocol input routine. Find the socket 3637472Ssklower * associated with the packet(s) and move them over. If 3737472Ssklower * nothing exists for this packet, drop it. 3837472Ssklower */ 3937472Ssklower /* 405121Swnj * Raw protocol interface. 415121Swnj */ 42*61357Sbostic void 436529Ssam raw_input(m0, proto, src, dst) 445612Swnj struct mbuf *m0; 4539181Ssklower register struct sockproto *proto; 466529Ssam struct sockaddr *src, *dst; 475121Swnj { 485612Swnj register struct rawcb *rp; 4937472Ssklower register struct mbuf *m = m0; 5039181Ssklower register int sockets = 0; 515612Swnj struct socket *last; 525121Swnj 535612Swnj last = 0; 545612Swnj for (rp = rawcb.rcb_next; rp != &rawcb; rp = rp->rcb_next) { 5537472Ssklower if (rp->rcb_proto.sp_family != proto->sp_family) 565612Swnj continue; 5721769Skarels if (rp->rcb_proto.sp_protocol && 5837472Ssklower rp->rcb_proto.sp_protocol != proto->sp_protocol) 595612Swnj continue; 605612Swnj /* 615612Swnj * We assume the lower level routines have 625612Swnj * placed the address in a canonical format 636509Ssam * suitable for a structure comparison. 6437472Ssklower * 6537472Ssklower * Note that if the lengths are not the same 6637472Ssklower * the comparison will fail at the first byte. 675612Swnj */ 6837472Ssklower #define equal(a1, a2) \ 6937472Ssklower (bcmp((caddr_t)(a1), (caddr_t)(a2), a1->sa_len) == 0) 7037472Ssklower if (rp->rcb_laddr && !equal(rp->rcb_laddr, dst)) 715612Swnj continue; 7237472Ssklower if (rp->rcb_faddr && !equal(rp->rcb_faddr, src)) 736509Ssam continue; 745612Swnj if (last) { 755612Swnj struct mbuf *n; 7637472Ssklower if (n = m_copy(m, 0, (int)M_COPYALL)) { 7737472Ssklower if (sbappendaddr(&last->so_rcv, src, 7821531Skarels n, (struct mbuf *)0) == 0) 7921531Skarels /* should notify about lost packet */ 8021531Skarels m_freem(n); 8139181Ssklower else { 8221531Skarels sorwakeup(last); 8339181Ssklower sockets++; 8439181Ssklower } 855646Ssam } 865612Swnj } 876509Ssam last = rp->rcb_socket; 885612Swnj } 896584Ssam if (last) { 9037472Ssklower if (sbappendaddr(&last->so_rcv, src, 9137472Ssklower m, (struct mbuf *)0) == 0) 9237472Ssklower m_freem(m); 9339181Ssklower else { 9421531Skarels sorwakeup(last); 9539181Ssklower sockets++; 9639181Ssklower } 9721531Skarels } else 9821531Skarels m_freem(m); 995121Swnj } 1005121Swnj 1018636Sroot /*ARGSUSED*/ 102*61357Sbostic void 1036584Ssam raw_ctlinput(cmd, arg) 1046584Ssam int cmd; 10526379Skarels struct sockaddr *arg; 1066584Ssam { 1076591Ssam 1086591Ssam if (cmd < 0 || cmd > PRC_NCMDS) 1096591Ssam return; 1108636Sroot /* INCOMPLETE */ 1116584Ssam } 1126584Ssam 1135121Swnj /*ARGSUSED*/ 114*61357Sbostic int 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 } 281