1*6161Ssam /* raw_usrreq.c 4.9 82/03/13 */ 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 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; 295668Ssam struct sockproto *pf; 305668Ssam struct sockaddr *daf, *saf; 315121Swnj { 325612Swnj register struct mbuf *m; 335612Swnj struct raw_header *rh; 345121Swnj int s; 355121Swnj 365668Ssam 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 *); 495668Ssam rh->raw_dst = *daf; 505668Ssam rh->raw_src = *saf; 515668Ssam 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 || 1056045Swnj (pr->pr_protocol && pr->pr_protocol != sp->sp_protocol)) 1065612Swnj continue; 1076045Swnj if (so->so_addr.sa_family && 1086045Swnj sa->sa_family != so->so_addr.sa_family) 1095612Swnj continue; 1105612Swnj /* 1115612Swnj * We assume the lower level routines have 1125612Swnj * placed the address in a canonical format 1135612Swnj * suitable for a structure comparison. Packets 1145612Swnj * are duplicated for each receiving socket. 1155668Ssam * 1165668Ssam * SHOULD HAVE A NUMBER OF MECHANISMS FOR 1175668Ssam * MATCHING BASED ON rcb_flags 1185612Swnj */ 1195612Swnj if ((rp->rcb_flags & RAW_ADDR) && 1205612Swnj bcmp(sa->sa_data, so->so_addr.sa_data, 14) != 0) 1215612Swnj continue; 1225612Swnj /* 1235612Swnj * To avoid extraneous packet copies, we keep 1245612Swnj * track of the last socket the packet should be 1255612Swnj * placed in, and make copies only after finding a 1265612Swnj * socket which "collides". 1275612Swnj */ 1285612Swnj if (last) { 1295612Swnj struct mbuf *n; 1305612Swnj 131*6161Ssam if (n = m_copy(m->m_next, 0, (int)M_COPYALL)) 1325612Swnj goto nospace; 1335646Ssam if (sbappendaddr(&last->so_rcv, &rawp->raw_src, n) == 0) { 1345646Ssam /* 1355646Ssam * Should drop notification of lost packet 1365646Ssam * into this guy's queue, but... 1375646Ssam */ 1385646Ssam m_freem(n); 1395646Ssam goto nospace; 1405646Ssam } 1415612Swnj sorwakeup(last); 1425612Swnj } 1435612Swnj nospace: 1445612Swnj last = so; 1455612Swnj } 1465612Swnj if (last == 0) 1475612Swnj goto drop; 1485646Ssam if (sbappendaddr(&last->so_rcv, &rawp->raw_src, m->m_next) == 0) 1496045Swnj { 1506045Swnj printf("rawintr: sbappendaddr failed\n"); 1515646Ssam goto drop; 1526045Swnj } 1535646Ssam (void) m_free(m); /* generic header */ 1545612Swnj sorwakeup(last); 1555612Swnj goto next; 1565121Swnj drop: 1575121Swnj m_freem(m); 1585121Swnj goto next; 1595121Swnj } 1605121Swnj 1615121Swnj /*ARGSUSED*/ 1625121Swnj raw_usrreq(so, req, m, addr) 1635121Swnj struct socket *so; 1645121Swnj int req; 1655121Swnj struct mbuf *m; 1665121Swnj caddr_t addr; 1675121Swnj { 1685612Swnj register struct rawcb *rp = sotorawcb(so); 1695612Swnj int error = 0; 1705121Swnj 1715121Swnj COUNT(RAW_USRREQ); 1725612Swnj if (rp == 0 && req != PRU_ATTACH) 1735612Swnj return (EINVAL); 1745121Swnj 1755612Swnj switch (req) { 1765612Swnj 1775612Swnj /* 1785612Swnj * Allocate a raw control block and fill in the 1795612Swnj * necessary info to allow packets to be routed to 1805612Swnj * the appropriate raw interface routine. 1815612Swnj */ 1825612Swnj case PRU_ATTACH: 1835612Swnj if (rp) 1845612Swnj return (EINVAL);; 1855612Swnj error = raw_attach(so, (struct sockaddr *)addr); 1865612Swnj break; 1875612Swnj 1885612Swnj /* 1895612Swnj * Destroy state just before socket deallocation. 1905612Swnj * Flush data or not depending on the options. 1915612Swnj */ 1925612Swnj case PRU_DETACH: 1935612Swnj if (rp == 0) 1945612Swnj return (ENOTCONN); 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: 2055612Swnj if (rp->rcb_flags & RAW_ADDR) 2065612Swnj return (EISCONN); 2075612Swnj raw_connaddr(rp, (struct sockaddr *)addr); 2085612Swnj soisconnected(so); 2095612Swnj break; 2105612Swnj 2115612Swnj case PRU_DISCONNECT: 2125612Swnj if ((rp->rcb_flags & RAW_ADDR) == 0) 2135612Swnj return (ENOTCONN); 2145612Swnj raw_disconnect(rp); 2155612Swnj soisdisconnected(so); 2165612Swnj break; 2175612Swnj 2185612Swnj /* 2195612Swnj * Mark the connection as being incapable of further input. 2205612Swnj */ 2215612Swnj case PRU_SHUTDOWN: 2225612Swnj socantsendmore(so); 2235612Swnj break; 2245612Swnj 2255612Swnj /* 2265612Swnj * Ship a packet out. The appropriate raw output 2275612Swnj * routine handles any massaging necessary. 2285612Swnj */ 2295612Swnj case PRU_SEND: 2305612Swnj if (addr) { 2315612Swnj if (rp->rcb_flags & RAW_ADDR) 2325612Swnj return (EISCONN); 2335612Swnj raw_connaddr(rp, (struct sockaddr *)addr); 2345612Swnj } else if ((rp->rcb_flags & RAW_ADDR) == 0) 2355612Swnj return (ENOTCONN); 2365612Swnj (void) (*so->so_proto->pr_output)(m, so); 2375612Swnj if (addr) 2385612Swnj rp->rcb_flags &= ~RAW_ADDR; 2395612Swnj break; 2405612Swnj 2415612Swnj case PRU_ABORT: 2425612Swnj raw_disconnect(rp); 2435612Swnj sofree(so); 2445612Swnj soisdisconnected(so); 2455612Swnj break; 2465612Swnj 2475612Swnj /* 2485612Swnj * Not supported. 2495612Swnj */ 2505612Swnj case PRU_ACCEPT: 2515612Swnj case PRU_RCVD: 2525612Swnj case PRU_CONTROL: 2535612Swnj case PRU_SENSE: 2545612Swnj case PRU_RCVOOB: 2555612Swnj case PRU_SENDOOB: 2565612Swnj error = EOPNOTSUPP; 2575612Swnj break; 2585612Swnj 2595612Swnj default: 2605612Swnj panic("raw_usrreq"); 2615612Swnj } 2625612Swnj return (error); 2635121Swnj } 264