1*6211Swnj /* raw_usrreq.c 4.10 82/03/15 */ 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" 136045Swnj #include "../errno.h" 145121Swnj 15*6211Swnj int rawqmaxlen = IFQ_MAXLEN; 16*6211Swnj 175121Swnj /* 185612Swnj * Initialize raw connection block q. 19*6211Swnj */ 205612Swnj raw_init() 215612Swnj { 22*6211Swnj 235612Swnj COUNT(RAW_INIT); 245612Swnj rawcb.rcb_next = rawcb.rcb_prev = &rawcb; 25*6211Swnj rawintrq.ifq_maxlen = IFQ_MAXLEN; 265612Swnj } 275612Swnj 285612Swnj /* 295121Swnj * Raw protocol interface. 305121Swnj */ 315646Ssam raw_input(m0, pf, daf, saf) 325612Swnj struct mbuf *m0; 335668Ssam struct sockproto *pf; 345668Ssam struct sockaddr *daf, *saf; 355121Swnj { 365612Swnj register struct mbuf *m; 375612Swnj struct raw_header *rh; 385121Swnj int s; 395121Swnj 405668Ssam COUNT(RAW_INPUT); 415612Swnj /* 425612Swnj * Rip off an mbuf for a generic header. 435612Swnj */ 445612Swnj m = m_get(M_DONTWAIT); 455612Swnj if (m == 0) { 465612Swnj m_freem(m0); 475612Swnj return; 485612Swnj } 495612Swnj m->m_next = m0; 505612Swnj m->m_off = MMINOFF; 515612Swnj m->m_len = sizeof(struct raw_header); 525612Swnj rh = mtod(m, struct raw_header *); 535668Ssam rh->raw_dst = *daf; 545668Ssam rh->raw_src = *saf; 555668Ssam rh->raw_protocol = *pf; 565612Swnj 575612Swnj /* 585612Swnj * Header now contains enough info to decide 595612Swnj * which socket to place packet in (if any). 605612Swnj * Queue it up for the raw protocol process 615612Swnj * running at software interrupt level. 625612Swnj */ 635121Swnj s = splimp(); 64*6211Swnj if (IF_QFULL(&rawintrq)) 65*6211Swnj m_freem(m); 66*6211Swnj else 67*6211Swnj IF_ENQUEUE(&rawintrq, m); 685121Swnj splx(s); 695121Swnj setrawintr(); 705121Swnj } 715121Swnj 725612Swnj /* 735612Swnj * Raw protocol input routine. Process packets entered 745612Swnj * into the queue at interrupt time. Find the socket 755612Swnj * associated with the packet(s) and move them over. If 765612Swnj * nothing exists for this packet, drop it. 775612Swnj */ 785121Swnj rawintr() 795121Swnj { 805121Swnj int s; 815121Swnj struct mbuf *m; 825612Swnj register struct rawcb *rp; 835612Swnj register struct socket *so; 845612Swnj register struct protosw *pr; 855612Swnj register struct sockproto *sp; 865612Swnj register struct sockaddr *sa; 875646Ssam struct raw_header *rawp; 885612Swnj struct socket *last; 895121Swnj 905121Swnj COUNT(RAWINTR); 915121Swnj next: 925121Swnj s = splimp(); 935121Swnj IF_DEQUEUE(&rawintrq, m); 945121Swnj splx(s); 955121Swnj if (m == 0) 965121Swnj return; 975646Ssam rawp = mtod(m, struct raw_header *); 985646Ssam sp = &rawp->raw_protocol; 995646Ssam sa = &rawp->raw_dst; 1005612Swnj 1015612Swnj /* 1025612Swnj * Find the appropriate socket(s) in which to place this 1035612Swnj * packet. This is done by matching the protocol and 1045612Swnj * address information prepended by raw_input against 1055612Swnj * the info stored in the control block structures. 1065612Swnj */ 1075612Swnj last = 0; 1085612Swnj for (rp = rawcb.rcb_next; rp != &rawcb; rp = rp->rcb_next) { 1095612Swnj so = rp->rcb_socket; 1105612Swnj pr = so->so_proto; 1115612Swnj if (pr->pr_family != sp->sp_family || 1126045Swnj (pr->pr_protocol && pr->pr_protocol != sp->sp_protocol)) 1135612Swnj continue; 1146045Swnj if (so->so_addr.sa_family && 1156045Swnj sa->sa_family != so->so_addr.sa_family) 1165612Swnj continue; 1175612Swnj /* 1185612Swnj * We assume the lower level routines have 1195612Swnj * placed the address in a canonical format 1205612Swnj * suitable for a structure comparison. Packets 1215612Swnj * are duplicated for each receiving socket. 1225668Ssam * 1235668Ssam * SHOULD HAVE A NUMBER OF MECHANISMS FOR 1245668Ssam * MATCHING BASED ON rcb_flags 1255612Swnj */ 1265612Swnj if ((rp->rcb_flags & RAW_ADDR) && 1275612Swnj bcmp(sa->sa_data, so->so_addr.sa_data, 14) != 0) 1285612Swnj continue; 1295612Swnj /* 1305612Swnj * To avoid extraneous packet copies, we keep 1315612Swnj * track of the last socket the packet should be 1325612Swnj * placed in, and make copies only after finding a 1335612Swnj * socket which "collides". 1345612Swnj */ 1355612Swnj if (last) { 1365612Swnj struct mbuf *n; 1375612Swnj 1386161Ssam if (n = m_copy(m->m_next, 0, (int)M_COPYALL)) 1395612Swnj goto nospace; 1405646Ssam if (sbappendaddr(&last->so_rcv, &rawp->raw_src, n) == 0) { 1415646Ssam /* 1425646Ssam * Should drop notification of lost packet 1435646Ssam * into this guy's queue, but... 1445646Ssam */ 1455646Ssam m_freem(n); 1465646Ssam goto nospace; 1475646Ssam } 1485612Swnj sorwakeup(last); 1495612Swnj } 1505612Swnj nospace: 1515612Swnj last = so; 1525612Swnj } 1535612Swnj if (last == 0) 1545612Swnj goto drop; 1555646Ssam if (sbappendaddr(&last->so_rcv, &rawp->raw_src, m->m_next) == 0) 1566045Swnj { 1576045Swnj printf("rawintr: sbappendaddr failed\n"); 1585646Ssam goto drop; 1596045Swnj } 1605646Ssam (void) m_free(m); /* generic header */ 1615612Swnj sorwakeup(last); 1625612Swnj goto next; 1635121Swnj drop: 1645121Swnj m_freem(m); 1655121Swnj goto next; 1665121Swnj } 1675121Swnj 1685121Swnj /*ARGSUSED*/ 1695121Swnj raw_usrreq(so, req, m, addr) 1705121Swnj struct socket *so; 1715121Swnj int req; 1725121Swnj struct mbuf *m; 1735121Swnj caddr_t addr; 1745121Swnj { 1755612Swnj register struct rawcb *rp = sotorawcb(so); 1765612Swnj int error = 0; 1775121Swnj 1785121Swnj COUNT(RAW_USRREQ); 1795612Swnj if (rp == 0 && req != PRU_ATTACH) 1805612Swnj return (EINVAL); 1815121Swnj 1825612Swnj switch (req) { 1835612Swnj 1845612Swnj /* 1855612Swnj * Allocate a raw control block and fill in the 1865612Swnj * necessary info to allow packets to be routed to 1875612Swnj * the appropriate raw interface routine. 1885612Swnj */ 1895612Swnj case PRU_ATTACH: 190*6211Swnj if ((so->so_state & SS_PRIV) == 0) 191*6211Swnj return (EPERM); 1925612Swnj if (rp) 193*6211Swnj return (EINVAL); 1945612Swnj error = raw_attach(so, (struct sockaddr *)addr); 1955612Swnj break; 1965612Swnj 1975612Swnj /* 1985612Swnj * Destroy state just before socket deallocation. 1995612Swnj * Flush data or not depending on the options. 2005612Swnj */ 2015612Swnj case PRU_DETACH: 2025612Swnj if (rp == 0) 2035612Swnj return (ENOTCONN); 2045612Swnj raw_detach(rp); 2055612Swnj break; 2065612Swnj 2075612Swnj /* 2085612Swnj * If a socket isn't bound to a single address, 2095612Swnj * the raw input routine will hand it anything 2105612Swnj * within that protocol family (assuming there's 2115612Swnj * nothing else around it should go to). 2125612Swnj */ 2135612Swnj case PRU_CONNECT: 2145612Swnj if (rp->rcb_flags & RAW_ADDR) 2155612Swnj return (EISCONN); 2165612Swnj raw_connaddr(rp, (struct sockaddr *)addr); 2175612Swnj soisconnected(so); 2185612Swnj break; 2195612Swnj 2205612Swnj case PRU_DISCONNECT: 2215612Swnj if ((rp->rcb_flags & RAW_ADDR) == 0) 2225612Swnj return (ENOTCONN); 2235612Swnj raw_disconnect(rp); 2245612Swnj soisdisconnected(so); 2255612Swnj break; 2265612Swnj 2275612Swnj /* 2285612Swnj * Mark the connection as being incapable of further input. 2295612Swnj */ 2305612Swnj case PRU_SHUTDOWN: 2315612Swnj socantsendmore(so); 2325612Swnj break; 2335612Swnj 2345612Swnj /* 2355612Swnj * Ship a packet out. The appropriate raw output 2365612Swnj * routine handles any massaging necessary. 2375612Swnj */ 2385612Swnj case PRU_SEND: 2395612Swnj if (addr) { 2405612Swnj if (rp->rcb_flags & RAW_ADDR) 2415612Swnj return (EISCONN); 2425612Swnj raw_connaddr(rp, (struct sockaddr *)addr); 2435612Swnj } else if ((rp->rcb_flags & RAW_ADDR) == 0) 2445612Swnj return (ENOTCONN); 2455612Swnj (void) (*so->so_proto->pr_output)(m, so); 2465612Swnj if (addr) 2475612Swnj rp->rcb_flags &= ~RAW_ADDR; 2485612Swnj break; 2495612Swnj 2505612Swnj case PRU_ABORT: 2515612Swnj raw_disconnect(rp); 2525612Swnj sofree(so); 2535612Swnj soisdisconnected(so); 2545612Swnj break; 2555612Swnj 2565612Swnj /* 2575612Swnj * Not supported. 2585612Swnj */ 2595612Swnj case PRU_ACCEPT: 2605612Swnj case PRU_RCVD: 2615612Swnj case PRU_CONTROL: 2625612Swnj case PRU_SENSE: 2635612Swnj case PRU_RCVOOB: 2645612Swnj case PRU_SENDOOB: 2655612Swnj error = EOPNOTSUPP; 2665612Swnj break; 2675612Swnj 2685612Swnj default: 2695612Swnj panic("raw_usrreq"); 2705612Swnj } 2715612Swnj return (error); 2725121Swnj } 273