1*21769Skarels /* raw_usrreq.c 6.7 85/06/02 */ 25121Swnj 317037Sbloom #include "param.h" 417037Sbloom #include "mbuf.h" 517037Sbloom #include "domain.h" 617037Sbloom #include "protosw.h" 717037Sbloom #include "socket.h" 817037Sbloom #include "socketvar.h" 917037Sbloom #include "errno.h" 1010890Ssam 1117037Sbloom #include "if.h" 1217037Sbloom #include "route.h" 1317037Sbloom #include "netisr.h" 1417037Sbloom #include "raw_cb.h" 155121Swnj 1610890Ssam #include "../vax/mtpr.h" 1710890Ssam 185121Swnj /* 195612Swnj * Initialize raw connection block q. 206211Swnj */ 215612Swnj raw_init() 225612Swnj { 236211Swnj 245612Swnj rawcb.rcb_next = rawcb.rcb_prev = &rawcb; 256211Swnj rawintrq.ifq_maxlen = IFQ_MAXLEN; 265612Swnj } 275612Swnj 285612Swnj /* 295121Swnj * Raw protocol interface. 305121Swnj */ 316529Ssam raw_input(m0, proto, src, dst) 325612Swnj struct mbuf *m0; 336509Ssam struct sockproto *proto; 346529Ssam struct sockaddr *src, *dst; 355121Swnj { 365612Swnj register struct mbuf *m; 375612Swnj struct raw_header *rh; 385121Swnj int s; 395121Swnj 405612Swnj /* 415612Swnj * Rip off an mbuf for a generic header. 425612Swnj */ 439638Ssam m = m_get(M_DONTWAIT, MT_HEADER); 445612Swnj if (m == 0) { 455612Swnj m_freem(m0); 465612Swnj return; 475612Swnj } 485612Swnj m->m_next = m0; 495612Swnj m->m_len = sizeof(struct raw_header); 505612Swnj rh = mtod(m, struct raw_header *); 516509Ssam rh->raw_dst = *dst; 526509Ssam rh->raw_src = *src; 536509Ssam rh->raw_proto = *proto; 545612Swnj 555612Swnj /* 565612Swnj * Header now contains enough info to decide 575612Swnj * which socket to place packet in (if any). 585612Swnj * Queue it up for the raw protocol process 595612Swnj * running at software interrupt level. 605612Swnj */ 615121Swnj s = splimp(); 626211Swnj if (IF_QFULL(&rawintrq)) 636211Swnj m_freem(m); 646211Swnj else 656211Swnj IF_ENQUEUE(&rawintrq, m); 665121Swnj splx(s); 676263Swnj schednetisr(NETISR_RAW); 685121Swnj } 695121Swnj 705612Swnj /* 715612Swnj * Raw protocol input routine. Process packets entered 725612Swnj * into the queue at interrupt time. Find the socket 735612Swnj * associated with the packet(s) and move them over. If 745612Swnj * nothing exists for this packet, drop it. 755612Swnj */ 765121Swnj rawintr() 775121Swnj { 785121Swnj int s; 795121Swnj struct mbuf *m; 805612Swnj register struct rawcb *rp; 816529Ssam register struct raw_header *rh; 825612Swnj struct socket *last; 835121Swnj 845121Swnj next: 855121Swnj s = splimp(); 865121Swnj IF_DEQUEUE(&rawintrq, m); 875121Swnj splx(s); 885121Swnj if (m == 0) 895121Swnj return; 906509Ssam rh = mtod(m, struct raw_header *); 915612Swnj last = 0; 925612Swnj for (rp = rawcb.rcb_next; rp != &rawcb; rp = rp->rcb_next) { 93*21769Skarels if (rp->rcb_proto.sp_family != rh->raw_proto.sp_family) 945612Swnj continue; 95*21769Skarels if (rp->rcb_proto.sp_protocol && 96*21769Skarels rp->rcb_proto.sp_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; 11321531Skarels if (n = m_copy(m->m_next, 0, (int)M_COPYALL)) { 11421531Skarels if (sbappendaddr(&last->so_rcv, &rh->raw_src, 11521531Skarels n, (struct mbuf *)0) == 0) 11621531Skarels /* should notify about lost packet */ 11721531Skarels m_freem(n); 11821531Skarels else 11921531Skarels sorwakeup(last); 1205646Ssam } 1215612Swnj } 1226509Ssam last = rp->rcb_socket; 1235612Swnj } 1246584Ssam if (last) { 12512783Ssam if (sbappendaddr(&last->so_rcv, &rh->raw_src, 12621531Skarels m->m_next, (struct mbuf *)0) == 0) 12721531Skarels m_freem(m->m_next); 12821531Skarels else 12921531Skarels sorwakeup(last); 13021531Skarels (void) m_free(m); /* header */ 13121531Skarels } else 13221531Skarels m_freem(m); 1335121Swnj goto next; 1345121Swnj } 1355121Swnj 1368636Sroot /*ARGSUSED*/ 1376584Ssam raw_ctlinput(cmd, arg) 1386584Ssam int cmd; 1396584Ssam caddr_t arg; 1406584Ssam { 1416591Ssam 1426591Ssam if (cmd < 0 || cmd > PRC_NCMDS) 1436591Ssam return; 1448636Sroot /* INCOMPLETE */ 1456584Ssam } 1466584Ssam 1475121Swnj /*ARGSUSED*/ 14812783Ssam raw_usrreq(so, req, m, nam, rights) 1495121Swnj struct socket *so; 1505121Swnj int req; 15112783Ssam struct mbuf *m, *nam, *rights; 1525121Swnj { 1535612Swnj register struct rawcb *rp = sotorawcb(so); 15412783Ssam register int error = 0; 1555121Swnj 15612783Ssam if (rights && rights->m_len) { 15712783Ssam error = EOPNOTSUPP; 15812783Ssam goto release; 15912783Ssam } 16012783Ssam if (rp == 0 && req != PRU_ATTACH) { 16112783Ssam error = EINVAL; 16212783Ssam goto release; 16312783Ssam } 1645612Swnj switch (req) { 1655612Swnj 1665612Swnj /* 1675612Swnj * Allocate a raw control block and fill in the 1685612Swnj * necessary info to allow packets to be routed to 1695612Swnj * the appropriate raw interface routine. 1705612Swnj */ 1715612Swnj case PRU_ATTACH: 17212783Ssam if ((so->so_state & SS_PRIV) == 0) { 17312783Ssam error = EACCES; 17413116Ssam break; 17512783Ssam } 17612783Ssam if (rp) { 17712783Ssam error = EINVAL; 17813116Ssam break; 17912783Ssam } 180*21769Skarels error = raw_attach(so, (int)nam); 1815612Swnj break; 1825612Swnj 1835612Swnj /* 1845612Swnj * Destroy state just before socket deallocation. 1855612Swnj * Flush data or not depending on the options. 1865612Swnj */ 1875612Swnj case PRU_DETACH: 18812783Ssam if (rp == 0) { 18912783Ssam error = ENOTCONN; 19013116Ssam break; 19112783Ssam } 1925612Swnj raw_detach(rp); 1935612Swnj break; 1945612Swnj 1955612Swnj /* 1965612Swnj * If a socket isn't bound to a single address, 1975612Swnj * the raw input routine will hand it anything 1985612Swnj * within that protocol family (assuming there's 1995612Swnj * nothing else around it should go to). 2005612Swnj */ 2015612Swnj case PRU_CONNECT: 20212783Ssam if (rp->rcb_flags & RAW_FADDR) { 20312783Ssam error = EISCONN; 20413116Ssam break; 20512783Ssam } 2068395Swnj raw_connaddr(rp, nam); 2075612Swnj soisconnected(so); 2085612Swnj break; 2095612Swnj 21013116Ssam case PRU_CONNECT2: 21113116Ssam error = EOPNOTSUPP; 21213116Ssam goto release; 21313116Ssam 21412783Ssam case PRU_BIND: 21512783Ssam if (rp->rcb_flags & RAW_LADDR) { 21612783Ssam error = EINVAL; /* XXX */ 21713116Ssam break; 21812783Ssam } 21912783Ssam error = raw_bind(so, nam); 22012783Ssam break; 22112783Ssam 2225612Swnj case PRU_DISCONNECT: 22312783Ssam if ((rp->rcb_flags & RAW_FADDR) == 0) { 22412783Ssam error = ENOTCONN; 22513116Ssam break; 22612783Ssam } 22713451Ssam if (rp->rcb_route.ro_rt) 22813451Ssam rtfree(rp->rcb_route.ro_rt); 2295612Swnj raw_disconnect(rp); 2305612Swnj soisdisconnected(so); 2315612Swnj break; 2325612Swnj 2335612Swnj /* 2345612Swnj * Mark the connection as being incapable of further input. 2355612Swnj */ 2365612Swnj case PRU_SHUTDOWN: 2375612Swnj socantsendmore(so); 2385612Swnj break; 2395612Swnj 2405612Swnj /* 2415612Swnj * Ship a packet out. The appropriate raw output 2425612Swnj * routine handles any massaging necessary. 2435612Swnj */ 2445612Swnj case PRU_SEND: 2458395Swnj if (nam) { 24612783Ssam if (rp->rcb_flags & RAW_FADDR) { 24712783Ssam error = EISCONN; 24813116Ssam break; 24912783Ssam } 2508395Swnj raw_connaddr(rp, nam); 25112783Ssam } else if ((rp->rcb_flags & RAW_FADDR) == 0) { 25212783Ssam error = ENOTCONN; 25313116Ssam break; 25412783Ssam } 25513451Ssam /* 25613451Ssam * Check for routing. If new foreign address, or 25713451Ssam * no route presently in use, try to allocate new 25813451Ssam * route. On failure, just hand packet to output 25913451Ssam * routine anyway in case it can handle it. 26013451Ssam */ 26113451Ssam if ((rp->rcb_flags & RAW_DONTROUTE) == 0) 26213451Ssam if (!equal(rp->rcb_faddr, rp->rcb_route.ro_dst) || 26313451Ssam rp->rcb_route.ro_rt == 0) { 26416773Sbloom if (rp->rcb_route.ro_rt) { 26516773Sbloom RTFREE(rp->rcb_route.ro_rt); 26616773Sbloom rp->rcb_route.ro_rt = NULL; 26716773Sbloom } 26813451Ssam rp->rcb_route.ro_dst = rp->rcb_faddr; 26913451Ssam rtalloc(&rp->rcb_route); 27013451Ssam } 2716505Ssam error = (*so->so_proto->pr_output)(m, so); 27212783Ssam m = NULL; 2738395Swnj if (nam) 2746509Ssam rp->rcb_flags &= ~RAW_FADDR; 2755612Swnj break; 2765612Swnj 2775612Swnj case PRU_ABORT: 2785612Swnj raw_disconnect(rp); 2795612Swnj sofree(so); 2805612Swnj soisdisconnected(so); 2815612Swnj break; 2825612Swnj 28316974Skarels case PRU_SENSE: 28416974Skarels /* 28516974Skarels * stat: don't bother with a blocksize. 28616974Skarels */ 28716974Skarels return (0); 28816974Skarels 2895612Swnj /* 2905612Swnj * Not supported. 2915612Swnj */ 29216773Sbloom case PRU_CONTROL: 29316773Sbloom case PRU_RCVOOB: 2945612Swnj case PRU_RCVD: 29516773Sbloom return(EOPNOTSUPP); 29616773Sbloom 29716773Sbloom case PRU_ACCEPT: 2985612Swnj case PRU_SENDOOB: 2995612Swnj error = EOPNOTSUPP; 3005612Swnj break; 3015612Swnj 3026509Ssam case PRU_SOCKADDR: 3038723Sroot bcopy((caddr_t)&rp->rcb_laddr, mtod(nam, caddr_t), 3048395Swnj sizeof (struct sockaddr)); 3058395Swnj nam->m_len = sizeof (struct sockaddr); 3066509Ssam break; 3076509Ssam 30814122Ssam case PRU_PEERADDR: 30914122Ssam bcopy((caddr_t)&rp->rcb_faddr, mtod(nam, caddr_t), 31014122Ssam sizeof (struct sockaddr)); 31114122Ssam nam->m_len = sizeof (struct sockaddr); 31214122Ssam break; 31314122Ssam 3145612Swnj default: 3155612Swnj panic("raw_usrreq"); 3165612Swnj } 31712783Ssam release: 31812783Ssam if (m != NULL) 31912783Ssam m_freem(m); 3205612Swnj return (error); 3215121Swnj } 322