1*5668Ssam /* raw_usrreq.c 4.7 82/02/02 */ 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" 85121Swnj #include "../h/mtpr.h" 95121Swnj #include "../net/in.h" 105121Swnj #include "../net/in_systm.h" 115121Swnj #include "../net/if.h" 125612Swnj #include "../net/raw_cb.h" 135612Swnj #include "/usr/include/errno.h" 145121Swnj 155121Swnj /* 165612Swnj * Initialize raw connection block q. 175612Swnj */ 185612Swnj raw_init() 195612Swnj { 205612Swnj COUNT(RAW_INIT); 215612Swnj rawcb.rcb_next = rawcb.rcb_prev = &rawcb; 225612Swnj } 235612Swnj 245612Swnj /* 255121Swnj * Raw protocol interface. 265121Swnj */ 275646Ssam raw_input(m0, pf, daf, saf) 285612Swnj struct mbuf *m0; 29*5668Ssam struct sockproto *pf; 30*5668Ssam struct sockaddr *daf, *saf; 315121Swnj { 325612Swnj register struct mbuf *m; 335612Swnj struct raw_header *rh; 345121Swnj int s; 355121Swnj 36*5668Ssam COUNT(RAW_INPUT); 375612Swnj /* 385612Swnj * Rip off an mbuf for a generic header. 395612Swnj */ 405612Swnj m = m_get(M_DONTWAIT); 415612Swnj if (m == 0) { 425612Swnj m_freem(m0); 435612Swnj return; 445612Swnj } 455612Swnj m->m_next = m0; 465612Swnj m->m_off = MMINOFF; 475612Swnj m->m_len = sizeof(struct raw_header); 485612Swnj rh = mtod(m, struct raw_header *); 49*5668Ssam rh->raw_dst = *daf; 50*5668Ssam rh->raw_src = *saf; 51*5668Ssam rh->raw_protocol = *pf; 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(); 605612Swnj IF_ENQUEUE(&rawintrq, m); 615121Swnj splx(s); 625121Swnj setrawintr(); 635121Swnj } 645121Swnj 655612Swnj /* 665612Swnj * Raw protocol input routine. Process packets entered 675612Swnj * into the queue at interrupt time. Find the socket 685612Swnj * associated with the packet(s) and move them over. If 695612Swnj * nothing exists for this packet, drop it. 705612Swnj */ 715121Swnj rawintr() 725121Swnj { 735121Swnj int s; 745121Swnj struct mbuf *m; 755612Swnj register struct rawcb *rp; 765612Swnj register struct socket *so; 775612Swnj register struct protosw *pr; 785612Swnj register struct sockproto *sp; 795612Swnj register struct sockaddr *sa; 805646Ssam struct raw_header *rawp; 815612Swnj struct socket *last; 825121Swnj 835121Swnj COUNT(RAWINTR); 845121Swnj next: 855121Swnj s = splimp(); 865121Swnj IF_DEQUEUE(&rawintrq, m); 875121Swnj splx(s); 885121Swnj if (m == 0) 895121Swnj return; 905646Ssam rawp = mtod(m, struct raw_header *); 915646Ssam sp = &rawp->raw_protocol; 925646Ssam sa = &rawp->raw_dst; 935612Swnj 945612Swnj /* 955612Swnj * Find the appropriate socket(s) in which to place this 965612Swnj * packet. This is done by matching the protocol and 975612Swnj * address information prepended by raw_input against 985612Swnj * the info stored in the control block structures. 995612Swnj */ 1005612Swnj last = 0; 1015612Swnj for (rp = rawcb.rcb_next; rp != &rawcb; rp = rp->rcb_next) { 1025612Swnj so = rp->rcb_socket; 1035612Swnj pr = so->so_proto; 1045612Swnj if (pr->pr_family != sp->sp_family || 1055612Swnj pr->pr_protocol != sp->sp_protocol) 1065612Swnj continue; 1075612Swnj if (sa->sa_family != so->so_addr.sa_family) 1085612Swnj continue; 1095612Swnj /* 1105612Swnj * We assume the lower level routines have 1115612Swnj * placed the address in a canonical format 1125612Swnj * suitable for a structure comparison. Packets 1135612Swnj * are duplicated for each receiving socket. 114*5668Ssam * 115*5668Ssam * SHOULD HAVE A NUMBER OF MECHANISMS FOR 116*5668Ssam * MATCHING BASED ON rcb_flags 1175612Swnj */ 1185612Swnj if ((rp->rcb_flags & RAW_ADDR) && 1195612Swnj bcmp(sa->sa_data, so->so_addr.sa_data, 14) != 0) 1205612Swnj continue; 1215612Swnj /* 1225612Swnj * To avoid extraneous packet copies, we keep 1235612Swnj * track of the last socket the packet should be 1245612Swnj * placed in, and make copies only after finding a 1255612Swnj * socket which "collides". 1265612Swnj */ 1275612Swnj if (last) { 1285612Swnj struct mbuf *n; 1295612Swnj 1305612Swnj if (n = m_copy(m->m_next, 0, M_COPYALL)) 1315612Swnj goto nospace; 1325646Ssam if (sbappendaddr(&last->so_rcv, &rawp->raw_src, n) == 0) { 1335646Ssam /* 1345646Ssam * Should drop notification of lost packet 1355646Ssam * into this guy's queue, but... 1365646Ssam */ 1375646Ssam m_freem(n); 1385646Ssam goto nospace; 1395646Ssam } 1405612Swnj sorwakeup(last); 1415612Swnj } 1425612Swnj nospace: 1435612Swnj last = so; 1445612Swnj } 1455612Swnj if (last == 0) 1465612Swnj goto drop; 1475646Ssam if (sbappendaddr(&last->so_rcv, &rawp->raw_src, m->m_next) == 0) 1485646Ssam goto drop; 1495646Ssam (void) m_free(m); /* generic header */ 1505612Swnj sorwakeup(last); 1515612Swnj goto next; 1525121Swnj drop: 1535121Swnj m_freem(m); 1545121Swnj goto next; 1555121Swnj } 1565121Swnj 1575121Swnj /*ARGSUSED*/ 1585121Swnj raw_usrreq(so, req, m, addr) 1595121Swnj struct socket *so; 1605121Swnj int req; 1615121Swnj struct mbuf *m; 1625121Swnj caddr_t addr; 1635121Swnj { 1645612Swnj register struct rawcb *rp = sotorawcb(so); 1655612Swnj int error = 0; 1665121Swnj 1675121Swnj COUNT(RAW_USRREQ); 1685612Swnj if (rp == 0 && req != PRU_ATTACH) 1695612Swnj return (EINVAL); 1705121Swnj 1715612Swnj switch (req) { 1725612Swnj 1735612Swnj /* 1745612Swnj * Allocate a raw control block and fill in the 1755612Swnj * necessary info to allow packets to be routed to 1765612Swnj * the appropriate raw interface routine. 1775612Swnj */ 1785612Swnj case PRU_ATTACH: 1795612Swnj if (rp) 1805612Swnj return (EINVAL);; 1815612Swnj error = raw_attach(so, (struct sockaddr *)addr); 1825612Swnj break; 1835612Swnj 1845612Swnj /* 1855612Swnj * Destroy state just before socket deallocation. 1865612Swnj * Flush data or not depending on the options. 1875612Swnj */ 1885612Swnj case PRU_DETACH: 1895612Swnj if (rp == 0) 1905612Swnj return (ENOTCONN); 1915612Swnj raw_detach(rp); 1925612Swnj break; 1935612Swnj 1945612Swnj /* 1955612Swnj * If a socket isn't bound to a single address, 1965612Swnj * the raw input routine will hand it anything 1975612Swnj * within that protocol family (assuming there's 1985612Swnj * nothing else around it should go to). 1995612Swnj */ 2005612Swnj case PRU_CONNECT: 2015612Swnj if (rp->rcb_flags & RAW_ADDR) 2025612Swnj return (EISCONN); 2035612Swnj raw_connaddr(rp, (struct sockaddr *)addr); 2045612Swnj soisconnected(so); 2055612Swnj break; 2065612Swnj 2075612Swnj case PRU_DISCONNECT: 2085612Swnj if ((rp->rcb_flags & RAW_ADDR) == 0) 2095612Swnj return (ENOTCONN); 2105612Swnj raw_disconnect(rp); 2115612Swnj soisdisconnected(so); 2125612Swnj break; 2135612Swnj 2145612Swnj /* 2155612Swnj * Mark the connection as being incapable of further input. 2165612Swnj */ 2175612Swnj case PRU_SHUTDOWN: 2185612Swnj socantsendmore(so); 2195612Swnj break; 2205612Swnj 2215612Swnj /* 2225612Swnj * Ship a packet out. The appropriate raw output 2235612Swnj * routine handles any massaging necessary. 2245612Swnj */ 2255612Swnj case PRU_SEND: 2265612Swnj if (addr) { 2275612Swnj if (rp->rcb_flags & RAW_ADDR) 2285612Swnj return (EISCONN); 2295612Swnj raw_connaddr(rp, (struct sockaddr *)addr); 2305612Swnj } else if ((rp->rcb_flags & RAW_ADDR) == 0) 2315612Swnj return (ENOTCONN); 2325612Swnj (void) (*so->so_proto->pr_output)(m, so); 2335612Swnj if (addr) 2345612Swnj rp->rcb_flags &= ~RAW_ADDR; 2355612Swnj break; 2365612Swnj 2375612Swnj case PRU_ABORT: 2385612Swnj raw_disconnect(rp); 2395612Swnj sofree(so); 2405612Swnj soisdisconnected(so); 2415612Swnj break; 2425612Swnj 2435612Swnj /* 2445612Swnj * Not supported. 2455612Swnj */ 2465612Swnj case PRU_ACCEPT: 2475612Swnj case PRU_RCVD: 2485612Swnj case PRU_CONTROL: 2495612Swnj case PRU_SENSE: 2505612Swnj case PRU_RCVOOB: 2515612Swnj case PRU_SENDOOB: 2525612Swnj error = EOPNOTSUPP; 2535612Swnj break; 2545612Swnj 2555612Swnj default: 2565612Swnj panic("raw_usrreq"); 2575612Swnj } 2585612Swnj return (error); 2595121Swnj } 260