123162Smckusick /* 229068Smckusick * Copyright (c) 1980, 1986 Regents of the University of California. 333183Sbostic * All rights reserved. 423162Smckusick * 544465Sbostic * %sccs.include.redist.c% 633183Sbostic * 7*56529Sbostic * @(#)raw_usrreq.c 7.12 (Berkeley) 10/11/92 823162Smckusick */ 95121Swnj 10*56529Sbostic #include <sys/param.h> 11*56529Sbostic #include <sys/mbuf.h> 12*56529Sbostic #include <sys/domain.h> 13*56529Sbostic #include <sys/protosw.h> 14*56529Sbostic #include <sys/socket.h> 15*56529Sbostic #include <sys/socketvar.h> 16*56529Sbostic #include <sys/errno.h> 1710890Ssam 18*56529Sbostic #include <net/if.h> 19*56529Sbostic #include <net/route.h> 20*56529Sbostic #include <net/netisr.h> 21*56529Sbostic #include <net/raw_cb.h> 225121Swnj 235121Swnj /* 245612Swnj * Initialize raw connection block q. 256211Swnj */ 265612Swnj raw_init() 275612Swnj { 286211Swnj 295612Swnj rawcb.rcb_next = rawcb.rcb_prev = &rawcb; 305612Swnj } 315612Swnj 3237472Ssklower 335612Swnj /* 3437472Ssklower * Raw protocol input routine. Find the socket 3537472Ssklower * associated with the packet(s) and move them over. If 3637472Ssklower * nothing exists for this packet, drop it. 3737472Ssklower */ 3837472Ssklower /* 395121Swnj * Raw protocol interface. 405121Swnj */ 416529Ssam raw_input(m0, proto, src, dst) 425612Swnj struct mbuf *m0; 4339181Ssklower register struct sockproto *proto; 446529Ssam struct sockaddr *src, *dst; 455121Swnj { 465612Swnj register struct rawcb *rp; 4737472Ssklower register struct mbuf *m = m0; 4839181Ssklower register int sockets = 0; 495612Swnj struct socket *last; 505121Swnj 515612Swnj last = 0; 525612Swnj for (rp = rawcb.rcb_next; rp != &rawcb; rp = rp->rcb_next) { 5337472Ssklower if (rp->rcb_proto.sp_family != proto->sp_family) 545612Swnj continue; 5521769Skarels if (rp->rcb_proto.sp_protocol && 5637472Ssklower rp->rcb_proto.sp_protocol != proto->sp_protocol) 575612Swnj continue; 585612Swnj /* 595612Swnj * We assume the lower level routines have 605612Swnj * placed the address in a canonical format 616509Ssam * suitable for a structure comparison. 6237472Ssklower * 6337472Ssklower * Note that if the lengths are not the same 6437472Ssklower * the comparison will fail at the first byte. 655612Swnj */ 6637472Ssklower #define equal(a1, a2) \ 6737472Ssklower (bcmp((caddr_t)(a1), (caddr_t)(a2), a1->sa_len) == 0) 6837472Ssklower if (rp->rcb_laddr && !equal(rp->rcb_laddr, dst)) 695612Swnj continue; 7037472Ssklower if (rp->rcb_faddr && !equal(rp->rcb_faddr, src)) 716509Ssam continue; 725612Swnj if (last) { 735612Swnj struct mbuf *n; 7437472Ssklower if (n = m_copy(m, 0, (int)M_COPYALL)) { 7537472Ssklower if (sbappendaddr(&last->so_rcv, src, 7621531Skarels n, (struct mbuf *)0) == 0) 7721531Skarels /* should notify about lost packet */ 7821531Skarels m_freem(n); 7939181Ssklower else { 8021531Skarels sorwakeup(last); 8139181Ssklower sockets++; 8239181Ssklower } 835646Ssam } 845612Swnj } 856509Ssam last = rp->rcb_socket; 865612Swnj } 876584Ssam if (last) { 8837472Ssklower if (sbappendaddr(&last->so_rcv, src, 8937472Ssklower m, (struct mbuf *)0) == 0) 9037472Ssklower m_freem(m); 9139181Ssklower else { 9221531Skarels sorwakeup(last); 9339181Ssklower sockets++; 9439181Ssklower } 9521531Skarels } else 9621531Skarels m_freem(m); 9739181Ssklower return (sockets); 985121Swnj } 995121Swnj 1008636Sroot /*ARGSUSED*/ 1016584Ssam raw_ctlinput(cmd, arg) 1026584Ssam int cmd; 10326379Skarels struct sockaddr *arg; 1046584Ssam { 1056591Ssam 1066591Ssam if (cmd < 0 || cmd > PRC_NCMDS) 1076591Ssam return; 1088636Sroot /* INCOMPLETE */ 1096584Ssam } 1106584Ssam 1115121Swnj /*ARGSUSED*/ 11240787Ssklower raw_usrreq(so, req, m, nam, control) 1135121Swnj struct socket *so; 1145121Swnj int req; 11540787Ssklower struct mbuf *m, *nam, *control; 1165121Swnj { 1175612Swnj register struct rawcb *rp = sotorawcb(so); 11812783Ssam register int error = 0; 11937472Ssklower int len; 1205121Swnj 12125501Skarels if (req == PRU_CONTROL) 12225501Skarels return (EOPNOTSUPP); 12340787Ssklower if (control && control->m_len) { 12412783Ssam error = EOPNOTSUPP; 12512783Ssam goto release; 12612783Ssam } 12737472Ssklower if (rp == 0) { 12812783Ssam error = EINVAL; 12912783Ssam goto release; 13012783Ssam } 1315612Swnj switch (req) { 1325612Swnj 1335612Swnj /* 1345612Swnj * Allocate a raw control block and fill in the 1355612Swnj * necessary info to allow packets to be routed to 1365612Swnj * the appropriate raw interface routine. 1375612Swnj */ 1385612Swnj case PRU_ATTACH: 13912783Ssam if ((so->so_state & SS_PRIV) == 0) { 14012783Ssam error = EACCES; 14113116Ssam break; 14212783Ssam } 14321769Skarels error = raw_attach(so, (int)nam); 1445612Swnj break; 1455612Swnj 1465612Swnj /* 1475612Swnj * Destroy state just before socket deallocation. 1485612Swnj * Flush data or not depending on the options. 1495612Swnj */ 1505612Swnj case PRU_DETACH: 15112783Ssam if (rp == 0) { 15212783Ssam error = ENOTCONN; 15313116Ssam break; 15412783Ssam } 1555612Swnj raw_detach(rp); 1565612Swnj break; 1575612Swnj 15837472Ssklower #ifdef notdef 1595612Swnj /* 1605612Swnj * If a socket isn't bound to a single address, 1615612Swnj * the raw input routine will hand it anything 1625612Swnj * within that protocol family (assuming there's 1635612Swnj * nothing else around it should go to). 1645612Swnj */ 1655612Swnj case PRU_CONNECT: 16637472Ssklower if (rp->rcb_faddr) { 16712783Ssam error = EISCONN; 16813116Ssam break; 16912783Ssam } 17037472Ssklower nam = m_copym(nam, 0, M_COPYALL, M_WAIT); 17137472Ssklower rp->rcb_faddr = mtod(nam, struct sockaddr *); 1725612Swnj soisconnected(so); 1735612Swnj break; 1745612Swnj 17512783Ssam case PRU_BIND: 17637472Ssklower if (rp->rcb_laddr) { 17712783Ssam error = EINVAL; /* XXX */ 17813116Ssam break; 17912783Ssam } 18012783Ssam error = raw_bind(so, nam); 18112783Ssam break; 18237472Ssklower #endif 18312783Ssam 18437472Ssklower case PRU_CONNECT2: 18537472Ssklower error = EOPNOTSUPP; 18637472Ssklower goto release; 18737472Ssklower 1885612Swnj case PRU_DISCONNECT: 18937472Ssklower if (rp->rcb_faddr == 0) { 19012783Ssam error = ENOTCONN; 19113116Ssam break; 19212783Ssam } 1935612Swnj raw_disconnect(rp); 1945612Swnj soisdisconnected(so); 1955612Swnj break; 1965612Swnj 1975612Swnj /* 1985612Swnj * Mark the connection as being incapable of further input. 1995612Swnj */ 2005612Swnj case PRU_SHUTDOWN: 2015612Swnj socantsendmore(so); 2025612Swnj break; 2035612Swnj 2045612Swnj /* 2055612Swnj * Ship a packet out. The appropriate raw output 2065612Swnj * routine handles any massaging necessary. 2075612Swnj */ 2085612Swnj case PRU_SEND: 2098395Swnj if (nam) { 21037472Ssklower if (rp->rcb_faddr) { 21112783Ssam error = EISCONN; 21213116Ssam break; 21312783Ssam } 21437472Ssklower rp->rcb_faddr = mtod(nam, struct sockaddr *); 21537472Ssklower } else if (rp->rcb_faddr == 0) { 21612783Ssam error = ENOTCONN; 21713116Ssam break; 21812783Ssam } 2196505Ssam error = (*so->so_proto->pr_output)(m, so); 22012783Ssam m = NULL; 2218395Swnj if (nam) 22237472Ssklower rp->rcb_faddr = 0; 2235612Swnj break; 2245612Swnj 2255612Swnj case PRU_ABORT: 2265612Swnj raw_disconnect(rp); 2275612Swnj sofree(so); 2285612Swnj soisdisconnected(so); 2295612Swnj break; 2305612Swnj 23116974Skarels case PRU_SENSE: 23216974Skarels /* 23316974Skarels * stat: don't bother with a blocksize. 23416974Skarels */ 23516974Skarels return (0); 23616974Skarels 2375612Swnj /* 2385612Swnj * Not supported. 2395612Swnj */ 24016773Sbloom case PRU_RCVOOB: 2415612Swnj case PRU_RCVD: 24216773Sbloom return(EOPNOTSUPP); 24316773Sbloom 24425221Skarels case PRU_LISTEN: 24516773Sbloom case PRU_ACCEPT: 2465612Swnj case PRU_SENDOOB: 2475612Swnj error = EOPNOTSUPP; 2485612Swnj break; 2495612Swnj 2506509Ssam case PRU_SOCKADDR: 25137472Ssklower if (rp->rcb_laddr == 0) { 25237472Ssklower error = EINVAL; 25337472Ssklower break; 25437472Ssklower } 25537472Ssklower len = rp->rcb_laddr->sa_len; 25637472Ssklower bcopy((caddr_t)rp->rcb_laddr, mtod(nam, caddr_t), (unsigned)len); 25737472Ssklower nam->m_len = len; 2586509Ssam break; 2596509Ssam 26014122Ssam case PRU_PEERADDR: 26137472Ssklower if (rp->rcb_faddr == 0) { 26237472Ssklower error = ENOTCONN; 26337472Ssklower break; 26437472Ssklower } 26537472Ssklower len = rp->rcb_faddr->sa_len; 26637472Ssklower bcopy((caddr_t)rp->rcb_faddr, mtod(nam, caddr_t), (unsigned)len); 26737472Ssklower nam->m_len = len; 26814122Ssam break; 26914122Ssam 2705612Swnj default: 2715612Swnj panic("raw_usrreq"); 2725612Swnj } 27312783Ssam release: 27412783Ssam if (m != NULL) 27512783Ssam m_freem(m); 2765612Swnj return (error); 2775121Swnj } 278