1*13116Ssam /* raw_usrreq.c 4.28 83/06/14 */ 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" 810890Ssam #include "../h/errno.h" 910890Ssam 105121Swnj #include "../net/if.h" 118395Swnj #include "../net/netisr.h" 125612Swnj #include "../net/raw_cb.h" 135121Swnj 1410890Ssam #include "../vax/mtpr.h" 1510890Ssam 165121Swnj /* 175612Swnj * Initialize raw connection block q. 186211Swnj */ 195612Swnj raw_init() 205612Swnj { 216211Swnj 225612Swnj rawcb.rcb_next = rawcb.rcb_prev = &rawcb; 236211Swnj rawintrq.ifq_maxlen = IFQ_MAXLEN; 245612Swnj } 255612Swnj 265612Swnj /* 275121Swnj * Raw protocol interface. 285121Swnj */ 296529Ssam raw_input(m0, proto, src, dst) 305612Swnj struct mbuf *m0; 316509Ssam struct sockproto *proto; 326529Ssam struct sockaddr *src, *dst; 335121Swnj { 345612Swnj register struct mbuf *m; 355612Swnj struct raw_header *rh; 365121Swnj int s; 375121Swnj 385612Swnj /* 395612Swnj * Rip off an mbuf for a generic header. 405612Swnj */ 419638Ssam m = m_get(M_DONTWAIT, MT_HEADER); 425612Swnj if (m == 0) { 435612Swnj m_freem(m0); 445612Swnj return; 455612Swnj } 465612Swnj m->m_next = m0; 475612Swnj m->m_len = sizeof(struct raw_header); 485612Swnj rh = mtod(m, struct raw_header *); 496509Ssam rh->raw_dst = *dst; 506509Ssam rh->raw_src = *src; 516509Ssam rh->raw_proto = *proto; 525612Swnj 535612Swnj /* 545612Swnj * Header now contains enough info to decide 555612Swnj * which socket to place packet in (if any). 565612Swnj * Queue it up for the raw protocol process 575612Swnj * running at software interrupt level. 585612Swnj */ 595121Swnj s = splimp(); 606211Swnj if (IF_QFULL(&rawintrq)) 616211Swnj m_freem(m); 626211Swnj else 636211Swnj IF_ENQUEUE(&rawintrq, m); 645121Swnj splx(s); 656263Swnj schednetisr(NETISR_RAW); 665121Swnj } 675121Swnj 685612Swnj /* 695612Swnj * Raw protocol input routine. Process packets entered 705612Swnj * into the queue at interrupt time. Find the socket 715612Swnj * associated with the packet(s) and move them over. If 725612Swnj * nothing exists for this packet, drop it. 735612Swnj */ 745121Swnj rawintr() 755121Swnj { 765121Swnj int s; 775121Swnj struct mbuf *m; 785612Swnj register struct rawcb *rp; 796509Ssam register struct protosw *lproto; 806529Ssam register struct raw_header *rh; 815612Swnj struct socket *last; 825121Swnj 835121Swnj next: 845121Swnj s = splimp(); 855121Swnj IF_DEQUEUE(&rawintrq, m); 865121Swnj splx(s); 875121Swnj if (m == 0) 885121Swnj return; 896509Ssam rh = mtod(m, struct raw_header *); 905612Swnj last = 0; 915612Swnj for (rp = rawcb.rcb_next; rp != &rawcb; rp = rp->rcb_next) { 926509Ssam lproto = rp->rcb_socket->so_proto; 936509Ssam if (lproto->pr_family != rh->raw_proto.sp_family) 945612Swnj continue; 956509Ssam if (lproto->pr_protocol && 966509Ssam lproto->pr_protocol != rh->raw_proto.sp_protocol) 975612Swnj continue; 985612Swnj /* 995612Swnj * We assume the lower level routines have 1005612Swnj * placed the address in a canonical format 1016509Ssam * suitable for a structure comparison. 1025612Swnj */ 1036529Ssam #define equal(a1, a2) \ 1046529Ssam (bcmp((caddr_t)&(a1), (caddr_t)&(a2), sizeof (struct sockaddr)) == 0) 1056509Ssam if ((rp->rcb_flags & RAW_LADDR) && 1066529Ssam !equal(rp->rcb_laddr, rh->raw_dst)) 1075612Swnj continue; 1086509Ssam if ((rp->rcb_flags & RAW_FADDR) && 1096529Ssam !equal(rp->rcb_faddr, rh->raw_src)) 1106509Ssam continue; 1115612Swnj if (last) { 1125612Swnj struct mbuf *n; 1137517Sroot if ((n = m_copy(m->m_next, 0, (int)M_COPYALL)) == 0) 1145612Swnj goto nospace; 11512783Ssam if (sbappendaddr(&last->so_rcv, &rh->raw_src, 11612783Ssam n, (struct mbuf *)0) == 0) { 1176509Ssam /* should notify about lost packet */ 1185646Ssam m_freem(n); 1195646Ssam goto nospace; 1205646Ssam } 1215612Swnj sorwakeup(last); 1225612Swnj } 1235612Swnj nospace: 1246509Ssam last = rp->rcb_socket; 1255612Swnj } 1266584Ssam if (last) { 1276584Ssam m = m_free(m); /* header */ 12812783Ssam if (sbappendaddr(&last->so_rcv, &rh->raw_src, 12912783Ssam m, (struct mbuf *)0) == 0) 1306584Ssam goto drop; 1316584Ssam sorwakeup(last); 1326584Ssam goto next; 1336584Ssam } 1345121Swnj drop: 1355121Swnj m_freem(m); 1365121Swnj goto next; 1375121Swnj } 1385121Swnj 1398636Sroot /*ARGSUSED*/ 1406584Ssam raw_ctlinput(cmd, arg) 1416584Ssam int cmd; 1426584Ssam caddr_t arg; 1436584Ssam { 1446591Ssam 1456591Ssam if (cmd < 0 || cmd > PRC_NCMDS) 1466591Ssam return; 1478636Sroot /* INCOMPLETE */ 1486584Ssam } 1496584Ssam 1505121Swnj /*ARGSUSED*/ 15112783Ssam raw_usrreq(so, req, m, nam, rights) 1525121Swnj struct socket *so; 1535121Swnj int req; 15412783Ssam struct mbuf *m, *nam, *rights; 1555121Swnj { 1565612Swnj register struct rawcb *rp = sotorawcb(so); 15712783Ssam register int error = 0; 1585121Swnj 15912783Ssam if (rights && rights->m_len) { 16012783Ssam error = EOPNOTSUPP; 16112783Ssam goto release; 16212783Ssam } 16312783Ssam if (rp == 0 && req != PRU_ATTACH) { 16412783Ssam error = EINVAL; 16512783Ssam goto release; 16612783Ssam } 1675612Swnj switch (req) { 1685612Swnj 1695612Swnj /* 1705612Swnj * Allocate a raw control block and fill in the 1715612Swnj * necessary info to allow packets to be routed to 1725612Swnj * the appropriate raw interface routine. 1735612Swnj */ 1745612Swnj case PRU_ATTACH: 17512783Ssam if ((so->so_state & SS_PRIV) == 0) { 17612783Ssam error = EACCES; 177*13116Ssam break; 17812783Ssam } 17912783Ssam if (rp) { 18012783Ssam error = EINVAL; 181*13116Ssam break; 18212783Ssam } 1838395Swnj error = raw_attach(so); 1845612Swnj break; 1855612Swnj 1865612Swnj /* 1875612Swnj * Destroy state just before socket deallocation. 1885612Swnj * Flush data or not depending on the options. 1895612Swnj */ 1905612Swnj case PRU_DETACH: 19112783Ssam if (rp == 0) { 19212783Ssam error = ENOTCONN; 193*13116Ssam break; 19412783Ssam } 1955612Swnj raw_detach(rp); 1965612Swnj break; 1975612Swnj 1985612Swnj /* 1995612Swnj * If a socket isn't bound to a single address, 2005612Swnj * the raw input routine will hand it anything 2015612Swnj * within that protocol family (assuming there's 2025612Swnj * nothing else around it should go to). 2035612Swnj */ 2045612Swnj case PRU_CONNECT: 20512783Ssam if (rp->rcb_flags & RAW_FADDR) { 20612783Ssam error = EISCONN; 207*13116Ssam break; 20812783Ssam } 2098395Swnj raw_connaddr(rp, nam); 2105612Swnj soisconnected(so); 2115612Swnj break; 2125612Swnj 213*13116Ssam case PRU_CONNECT2: 214*13116Ssam error = EOPNOTSUPP; 215*13116Ssam goto release; 216*13116Ssam 21712783Ssam case PRU_BIND: 21812783Ssam if (rp->rcb_flags & RAW_LADDR) { 21912783Ssam error = EINVAL; /* XXX */ 220*13116Ssam break; 22112783Ssam } 22212783Ssam error = raw_bind(so, nam); 22312783Ssam break; 22412783Ssam 2255612Swnj case PRU_DISCONNECT: 22612783Ssam if ((rp->rcb_flags & RAW_FADDR) == 0) { 22712783Ssam error = ENOTCONN; 228*13116Ssam break; 22912783Ssam } 2305612Swnj raw_disconnect(rp); 2315612Swnj soisdisconnected(so); 2325612Swnj break; 2335612Swnj 2345612Swnj /* 2355612Swnj * Mark the connection as being incapable of further input. 2365612Swnj */ 2375612Swnj case PRU_SHUTDOWN: 2385612Swnj socantsendmore(so); 2395612Swnj break; 2405612Swnj 2415612Swnj /* 2425612Swnj * Ship a packet out. The appropriate raw output 2435612Swnj * routine handles any massaging necessary. 2445612Swnj */ 2455612Swnj case PRU_SEND: 2468395Swnj if (nam) { 24712783Ssam if (rp->rcb_flags & RAW_FADDR) { 24812783Ssam error = EISCONN; 249*13116Ssam break; 25012783Ssam } 2518395Swnj raw_connaddr(rp, nam); 25212783Ssam } else if ((rp->rcb_flags & RAW_FADDR) == 0) { 25312783Ssam error = ENOTCONN; 254*13116Ssam break; 25512783Ssam } 2566505Ssam error = (*so->so_proto->pr_output)(m, so); 25712783Ssam m = NULL; 2588395Swnj if (nam) 2596509Ssam rp->rcb_flags &= ~RAW_FADDR; 2605612Swnj break; 2615612Swnj 2625612Swnj case PRU_ABORT: 2635612Swnj raw_disconnect(rp); 2645612Swnj sofree(so); 2655612Swnj soisdisconnected(so); 2665612Swnj break; 2675612Swnj 26813049Ssam case PRU_CONTROL: 269*13116Ssam m = NULL; 270*13116Ssam error = EOPNOTSUPP; 271*13116Ssam break; 27213049Ssam 2735612Swnj /* 2745612Swnj * Not supported. 2755612Swnj */ 2765612Swnj case PRU_ACCEPT: 2775612Swnj case PRU_RCVD: 2785612Swnj case PRU_SENSE: 2795612Swnj case PRU_RCVOOB: 2805612Swnj case PRU_SENDOOB: 2815612Swnj error = EOPNOTSUPP; 2825612Swnj break; 2835612Swnj 2846509Ssam case PRU_SOCKADDR: 2858723Sroot bcopy((caddr_t)&rp->rcb_laddr, mtod(nam, caddr_t), 2868395Swnj sizeof (struct sockaddr)); 2878395Swnj nam->m_len = sizeof (struct sockaddr); 2886509Ssam break; 2896509Ssam 2905612Swnj default: 2915612Swnj panic("raw_usrreq"); 2925612Swnj } 29312783Ssam release: 29412783Ssam if (m != NULL) 29512783Ssam m_freem(m); 2965612Swnj return (error); 2975121Swnj } 298