1*10263Ssam /* raw_usrreq.c 4.24 83/01/13 */ 25121Swnj 35121Swnj #include "../h/param.h" 45121Swnj #include "../h/mbuf.h" 55612Swnj #include "../h/protosw.h" 65121Swnj #include "../h/socket.h" 75121Swnj #include "../h/socketvar.h" 88636Sroot #include "../vax/mtpr.h" 95121Swnj #include "../net/if.h" 108395Swnj #include "../net/netisr.h" 115612Swnj #include "../net/raw_cb.h" 126509Ssam #include <errno.h> 135121Swnj 145121Swnj /* 155612Swnj * Initialize raw connection block q. 166211Swnj */ 175612Swnj raw_init() 185612Swnj { 196211Swnj 205612Swnj rawcb.rcb_next = rawcb.rcb_prev = &rawcb; 216211Swnj rawintrq.ifq_maxlen = IFQ_MAXLEN; 225612Swnj } 235612Swnj 245612Swnj /* 255121Swnj * Raw protocol interface. 265121Swnj */ 276529Ssam raw_input(m0, proto, src, dst) 285612Swnj struct mbuf *m0; 296509Ssam struct sockproto *proto; 306529Ssam struct sockaddr *src, *dst; 315121Swnj { 325612Swnj register struct mbuf *m; 335612Swnj struct raw_header *rh; 345121Swnj int s; 355121Swnj 365612Swnj /* 375612Swnj * Rip off an mbuf for a generic header. 385612Swnj */ 399638Ssam m = m_get(M_DONTWAIT, MT_HEADER); 405612Swnj if (m == 0) { 415612Swnj m_freem(m0); 425612Swnj return; 435612Swnj } 445612Swnj m->m_next = m0; 455612Swnj m->m_len = sizeof(struct raw_header); 465612Swnj rh = mtod(m, struct raw_header *); 476509Ssam rh->raw_dst = *dst; 486509Ssam rh->raw_src = *src; 496509Ssam rh->raw_proto = *proto; 505612Swnj 515612Swnj /* 525612Swnj * Header now contains enough info to decide 535612Swnj * which socket to place packet in (if any). 545612Swnj * Queue it up for the raw protocol process 555612Swnj * running at software interrupt level. 565612Swnj */ 575121Swnj s = splimp(); 586211Swnj if (IF_QFULL(&rawintrq)) 596211Swnj m_freem(m); 606211Swnj else 616211Swnj IF_ENQUEUE(&rawintrq, m); 625121Swnj splx(s); 636263Swnj schednetisr(NETISR_RAW); 645121Swnj } 655121Swnj 665612Swnj /* 675612Swnj * Raw protocol input routine. Process packets entered 685612Swnj * into the queue at interrupt time. Find the socket 695612Swnj * associated with the packet(s) and move them over. If 705612Swnj * nothing exists for this packet, drop it. 715612Swnj */ 725121Swnj rawintr() 735121Swnj { 745121Swnj int s; 755121Swnj struct mbuf *m; 765612Swnj register struct rawcb *rp; 776509Ssam register struct protosw *lproto; 786529Ssam register struct raw_header *rh; 795612Swnj struct socket *last; 805121Swnj 815121Swnj next: 825121Swnj s = splimp(); 835121Swnj IF_DEQUEUE(&rawintrq, m); 845121Swnj splx(s); 855121Swnj if (m == 0) 865121Swnj return; 876509Ssam rh = mtod(m, struct raw_header *); 885612Swnj last = 0; 895612Swnj for (rp = rawcb.rcb_next; rp != &rawcb; rp = rp->rcb_next) { 906509Ssam lproto = rp->rcb_socket->so_proto; 916509Ssam if (lproto->pr_family != rh->raw_proto.sp_family) 925612Swnj continue; 936509Ssam if (lproto->pr_protocol && 946509Ssam lproto->pr_protocol != rh->raw_proto.sp_protocol) 955612Swnj continue; 965612Swnj /* 975612Swnj * We assume the lower level routines have 985612Swnj * placed the address in a canonical format 996509Ssam * suitable for a structure comparison. 1005612Swnj */ 1016529Ssam #define equal(a1, a2) \ 1026529Ssam (bcmp((caddr_t)&(a1), (caddr_t)&(a2), sizeof (struct sockaddr)) == 0) 1036509Ssam if ((rp->rcb_flags & RAW_LADDR) && 1046529Ssam !equal(rp->rcb_laddr, rh->raw_dst)) 1055612Swnj continue; 1066509Ssam if ((rp->rcb_flags & RAW_FADDR) && 1076529Ssam !equal(rp->rcb_faddr, rh->raw_src)) 1086509Ssam continue; 1095612Swnj if (last) { 1105612Swnj struct mbuf *n; 1117517Sroot if ((n = m_copy(m->m_next, 0, (int)M_COPYALL)) == 0) 1125612Swnj goto nospace; 1136509Ssam if (sbappendaddr(&last->so_rcv, &rh->raw_src, n)==0) { 1146509Ssam /* should notify about lost packet */ 1155646Ssam m_freem(n); 1165646Ssam goto nospace; 1175646Ssam } 1185612Swnj sorwakeup(last); 1195612Swnj } 1205612Swnj nospace: 1216509Ssam last = rp->rcb_socket; 1225612Swnj } 1236584Ssam if (last) { 1246584Ssam m = m_free(m); /* header */ 1256584Ssam if (sbappendaddr(&last->so_rcv, &rh->raw_src, m) == 0) 1266584Ssam goto drop; 1276584Ssam sorwakeup(last); 1286584Ssam goto next; 1296584Ssam } 1305121Swnj drop: 1315121Swnj m_freem(m); 1325121Swnj goto next; 1335121Swnj } 1345121Swnj 1358636Sroot /*ARGSUSED*/ 1366584Ssam raw_ctlinput(cmd, arg) 1376584Ssam int cmd; 1386584Ssam caddr_t arg; 1396584Ssam { 1406591Ssam 1416591Ssam if (cmd < 0 || cmd > PRC_NCMDS) 1426591Ssam return; 1438636Sroot /* INCOMPLETE */ 1446584Ssam } 1456584Ssam 1465121Swnj /*ARGSUSED*/ 147*10263Ssam raw_usrreq(so, req, m, nam) 1485121Swnj struct socket *so; 1495121Swnj int req; 1508395Swnj struct mbuf *m, *nam; 1515121Swnj { 1525612Swnj register struct rawcb *rp = sotorawcb(so); 1535612Swnj int error = 0; 1545121Swnj 1555612Swnj if (rp == 0 && req != PRU_ATTACH) 1565612Swnj return (EINVAL); 1575121Swnj 1585612Swnj switch (req) { 1595612Swnj 1605612Swnj /* 1615612Swnj * Allocate a raw control block and fill in the 1625612Swnj * necessary info to allow packets to be routed to 1635612Swnj * the appropriate raw interface routine. 1645612Swnj */ 1655612Swnj case PRU_ATTACH: 1666211Swnj if ((so->so_state & SS_PRIV) == 0) 1676584Ssam return (EACCES); 1685612Swnj if (rp) 1696211Swnj return (EINVAL); 1708395Swnj error = raw_attach(so); 1715612Swnj break; 1725612Swnj 1735612Swnj /* 1745612Swnj * Destroy state just before socket deallocation. 1755612Swnj * Flush data or not depending on the options. 1765612Swnj */ 1775612Swnj case PRU_DETACH: 1785612Swnj if (rp == 0) 1795612Swnj return (ENOTCONN); 1805612Swnj raw_detach(rp); 1815612Swnj break; 1825612Swnj 1835612Swnj /* 1845612Swnj * If a socket isn't bound to a single address, 1855612Swnj * the raw input routine will hand it anything 1865612Swnj * within that protocol family (assuming there's 1875612Swnj * nothing else around it should go to). 1885612Swnj */ 1895612Swnj case PRU_CONNECT: 1906509Ssam if (rp->rcb_flags & RAW_FADDR) 1915612Swnj return (EISCONN); 1928395Swnj raw_connaddr(rp, nam); 1935612Swnj soisconnected(so); 1945612Swnj break; 1955612Swnj 1965612Swnj case PRU_DISCONNECT: 1976509Ssam if ((rp->rcb_flags & RAW_FADDR) == 0) 1985612Swnj return (ENOTCONN); 1995612Swnj raw_disconnect(rp); 2005612Swnj soisdisconnected(so); 2015612Swnj break; 2025612Swnj 2035612Swnj /* 2045612Swnj * Mark the connection as being incapable of further input. 2055612Swnj */ 2065612Swnj case PRU_SHUTDOWN: 2075612Swnj socantsendmore(so); 2085612Swnj break; 2095612Swnj 2105612Swnj /* 2115612Swnj * Ship a packet out. The appropriate raw output 2125612Swnj * routine handles any massaging necessary. 2135612Swnj */ 2145612Swnj case PRU_SEND: 2158395Swnj if (nam) { 2166509Ssam if (rp->rcb_flags & RAW_FADDR) 2175612Swnj return (EISCONN); 2188395Swnj raw_connaddr(rp, nam); 2196509Ssam } else if ((rp->rcb_flags & RAW_FADDR) == 0) 2205612Swnj return (ENOTCONN); 2216505Ssam error = (*so->so_proto->pr_output)(m, so); 2228395Swnj if (nam) 2236509Ssam rp->rcb_flags &= ~RAW_FADDR; 2245612Swnj break; 2255612Swnj 2265612Swnj case PRU_ABORT: 2275612Swnj raw_disconnect(rp); 2285612Swnj sofree(so); 2295612Swnj soisdisconnected(so); 2305612Swnj break; 2315612Swnj 2325612Swnj /* 2335612Swnj * Not supported. 2345612Swnj */ 2355612Swnj case PRU_ACCEPT: 2365612Swnj case PRU_RCVD: 2375612Swnj case PRU_CONTROL: 2385612Swnj case PRU_SENSE: 2395612Swnj case PRU_RCVOOB: 2405612Swnj case PRU_SENDOOB: 2415612Swnj error = EOPNOTSUPP; 2425612Swnj break; 2435612Swnj 2446509Ssam case PRU_SOCKADDR: 2458723Sroot bcopy((caddr_t)&rp->rcb_laddr, mtod(nam, caddr_t), 2468395Swnj sizeof (struct sockaddr)); 2478395Swnj nam->m_len = sizeof (struct sockaddr); 2486509Ssam break; 2496509Ssam 2505612Swnj default: 2515612Swnj panic("raw_usrreq"); 2525612Swnj } 2535612Swnj return (error); 2545121Swnj } 255