1*5646Ssam /* raw_usrreq.c 4.6 82/02/01 */ 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 */ 27*5646Ssam raw_input(m0, pf, daf, saf) 285612Swnj struct mbuf *m0; 295121Swnj struct sockproto pf; 30*5646Ssam struct sockaddr daf, saf; 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 */ 395612Swnj m = m_get(M_DONTWAIT); 405612Swnj if (m == 0) { 415612Swnj m_freem(m0); 425612Swnj return; 435612Swnj } 445612Swnj m->m_next = m0; 455612Swnj m->m_off = MMINOFF; 465612Swnj m->m_len = sizeof(struct raw_header); 475612Swnj rh = mtod(m, struct raw_header *); 48*5646Ssam rh->raw_dst = daf; 49*5646Ssam rh->raw_src = saf; 505612Swnj rh->raw_protocol = pf; 515612Swnj 525612Swnj /* 535612Swnj * Header now contains enough info to decide 545612Swnj * which socket to place packet in (if any). 555612Swnj * Queue it up for the raw protocol process 565612Swnj * running at software interrupt level. 575612Swnj */ 585121Swnj s = splimp(); 595612Swnj IF_ENQUEUE(&rawintrq, m); 605121Swnj splx(s); 615121Swnj setrawintr(); 625121Swnj } 635121Swnj 645612Swnj /* 655612Swnj * Raw protocol input routine. Process packets entered 665612Swnj * into the queue at interrupt time. Find the socket 675612Swnj * associated with the packet(s) and move them over. If 685612Swnj * nothing exists for this packet, drop it. 695612Swnj */ 705121Swnj rawintr() 715121Swnj { 725121Swnj int s; 735121Swnj struct mbuf *m; 745612Swnj register struct rawcb *rp; 755612Swnj register struct socket *so; 765612Swnj register struct protosw *pr; 775612Swnj register struct sockproto *sp; 785612Swnj register struct sockaddr *sa; 79*5646Ssam struct raw_header *rawp; 805612Swnj struct socket *last; 815121Swnj 825121Swnj COUNT(RAWINTR); 835121Swnj next: 845121Swnj s = splimp(); 855121Swnj IF_DEQUEUE(&rawintrq, m); 865121Swnj splx(s); 875121Swnj if (m == 0) 885121Swnj return; 89*5646Ssam rawp = mtod(m, struct raw_header *); 90*5646Ssam sp = &rawp->raw_protocol; 91*5646Ssam sa = &rawp->raw_dst; 925612Swnj 935612Swnj /* 945612Swnj * Find the appropriate socket(s) in which to place this 955612Swnj * packet. This is done by matching the protocol and 965612Swnj * address information prepended by raw_input against 975612Swnj * the info stored in the control block structures. 985612Swnj */ 995612Swnj last = 0; 1005612Swnj for (rp = rawcb.rcb_next; rp != &rawcb; rp = rp->rcb_next) { 1015612Swnj so = rp->rcb_socket; 1025612Swnj pr = so->so_proto; 1035612Swnj if (pr->pr_family != sp->sp_family || 1045612Swnj pr->pr_protocol != sp->sp_protocol) 1055612Swnj continue; 1065612Swnj if (sa->sa_family != so->so_addr.sa_family) 1075612Swnj continue; 1085612Swnj /* 1095612Swnj * We assume the lower level routines have 1105612Swnj * placed the address in a canonical format 1115612Swnj * suitable for a structure comparison. Packets 1125612Swnj * are duplicated for each receiving socket. 1135612Swnj */ 1145612Swnj if ((rp->rcb_flags & RAW_ADDR) && 1155612Swnj bcmp(sa->sa_data, so->so_addr.sa_data, 14) != 0) 1165612Swnj continue; 1175612Swnj /* 1185612Swnj * To avoid extraneous packet copies, we keep 1195612Swnj * track of the last socket the packet should be 1205612Swnj * placed in, and make copies only after finding a 1215612Swnj * socket which "collides". 1225612Swnj */ 1235612Swnj if (last) { 1245612Swnj struct mbuf *n; 1255612Swnj 1265612Swnj if (n = m_copy(m->m_next, 0, M_COPYALL)) 1275612Swnj goto nospace; 128*5646Ssam if (sbappendaddr(&last->so_rcv, &rawp->raw_src, n) == 0) { 129*5646Ssam /* 130*5646Ssam * Should drop notification of lost packet 131*5646Ssam * into this guy's queue, but... 132*5646Ssam */ 133*5646Ssam m_freem(n); 134*5646Ssam goto nospace; 135*5646Ssam } 1365612Swnj sorwakeup(last); 1375612Swnj } 1385612Swnj nospace: 1395612Swnj last = so; 1405612Swnj } 1415612Swnj if (last == 0) 1425612Swnj goto drop; 143*5646Ssam if (sbappendaddr(&last->so_rcv, &rawp->raw_src, m->m_next) == 0) 144*5646Ssam goto drop; 145*5646Ssam (void) m_free(m); /* generic header */ 1465612Swnj sorwakeup(last); 1475612Swnj goto next; 1485121Swnj drop: 1495121Swnj m_freem(m); 1505121Swnj goto next; 1515121Swnj } 1525121Swnj 1535121Swnj /*ARGSUSED*/ 1545121Swnj raw_usrreq(so, req, m, addr) 1555121Swnj struct socket *so; 1565121Swnj int req; 1575121Swnj struct mbuf *m; 1585121Swnj caddr_t addr; 1595121Swnj { 1605612Swnj register struct rawcb *rp = sotorawcb(so); 1615612Swnj int error = 0; 1625121Swnj 1635121Swnj COUNT(RAW_USRREQ); 1645612Swnj if (rp == 0 && req != PRU_ATTACH) 1655612Swnj return (EINVAL); 1665121Swnj 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: 1755612Swnj if (rp) 1765612Swnj return (EINVAL);; 1775612Swnj error = raw_attach(so, (struct sockaddr *)addr); 1785612Swnj break; 1795612Swnj 1805612Swnj /* 1815612Swnj * Destroy state just before socket deallocation. 1825612Swnj * Flush data or not depending on the options. 1835612Swnj */ 1845612Swnj case PRU_DETACH: 1855612Swnj if (rp == 0) 1865612Swnj return (ENOTCONN); 1875612Swnj raw_detach(rp); 1885612Swnj break; 1895612Swnj 1905612Swnj /* 1915612Swnj * If a socket isn't bound to a single address, 1925612Swnj * the raw input routine will hand it anything 1935612Swnj * within that protocol family (assuming there's 1945612Swnj * nothing else around it should go to). 1955612Swnj */ 1965612Swnj case PRU_CONNECT: 1975612Swnj if (rp->rcb_flags & RAW_ADDR) 1985612Swnj return (EISCONN); 1995612Swnj raw_connaddr(rp, (struct sockaddr *)addr); 2005612Swnj soisconnected(so); 2015612Swnj break; 2025612Swnj 2035612Swnj case PRU_DISCONNECT: 2045612Swnj if ((rp->rcb_flags & RAW_ADDR) == 0) 2055612Swnj return (ENOTCONN); 2065612Swnj raw_disconnect(rp); 2075612Swnj soisdisconnected(so); 2085612Swnj break; 2095612Swnj 2105612Swnj /* 2115612Swnj * Mark the connection as being incapable of further input. 2125612Swnj */ 2135612Swnj case PRU_SHUTDOWN: 2145612Swnj socantsendmore(so); 2155612Swnj break; 2165612Swnj 2175612Swnj /* 2185612Swnj * Ship a packet out. The appropriate raw output 2195612Swnj * routine handles any massaging necessary. 2205612Swnj */ 2215612Swnj case PRU_SEND: 2225612Swnj if (addr) { 2235612Swnj if (rp->rcb_flags & RAW_ADDR) 2245612Swnj return (EISCONN); 2255612Swnj raw_connaddr(rp, (struct sockaddr *)addr); 2265612Swnj } else if ((rp->rcb_flags & RAW_ADDR) == 0) 2275612Swnj return (ENOTCONN); 2285612Swnj (void) (*so->so_proto->pr_output)(m, so); 2295612Swnj if (addr) 2305612Swnj rp->rcb_flags &= ~RAW_ADDR; 2315612Swnj break; 2325612Swnj 2335612Swnj case PRU_ABORT: 2345612Swnj raw_disconnect(rp); 2355612Swnj sofree(so); 2365612Swnj soisdisconnected(so); 2375612Swnj break; 2385612Swnj 2395612Swnj /* 2405612Swnj * Not supported. 2415612Swnj */ 2425612Swnj case PRU_ACCEPT: 2435612Swnj case PRU_RCVD: 2445612Swnj case PRU_CONTROL: 2455612Swnj case PRU_SENSE: 2465612Swnj case PRU_RCVOOB: 2475612Swnj case PRU_SENDOOB: 2485612Swnj error = EOPNOTSUPP; 2495612Swnj break; 2505612Swnj 2515612Swnj default: 2525612Swnj panic("raw_usrreq"); 2535612Swnj } 2545612Swnj return (error); 2555121Swnj } 256