1*6509Ssam /* raw_usrreq.c 4.13 82/04/10 */ 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" 13*6509Ssam #include <errno.h> 145121Swnj 156211Swnj int rawqmaxlen = IFQ_MAXLEN; 166211Swnj 175121Swnj /* 185612Swnj * Initialize raw connection block q. 196211Swnj */ 205612Swnj raw_init() 215612Swnj { 226211Swnj 235612Swnj COUNT(RAW_INIT); 245612Swnj rawcb.rcb_next = rawcb.rcb_prev = &rawcb; 256211Swnj rawintrq.ifq_maxlen = IFQ_MAXLEN; 265612Swnj } 275612Swnj 285612Swnj /* 295121Swnj * Raw protocol interface. 305121Swnj */ 31*6509Ssam raw_input(m0, proto, dst, src) 325612Swnj struct mbuf *m0; 33*6509Ssam struct sockproto *proto; 34*6509Ssam struct sockaddr *dst, *src; 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 *); 53*6509Ssam rh->raw_dst = *dst; 54*6509Ssam rh->raw_src = *src; 55*6509Ssam rh->raw_proto = *proto; 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(); 646211Swnj if (IF_QFULL(&rawintrq)) 656211Swnj m_freem(m); 666211Swnj else 676211Swnj IF_ENQUEUE(&rawintrq, m); 685121Swnj splx(s); 696263Swnj schednetisr(NETISR_RAW); 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; 83*6509Ssam register struct sockaddr *laddr; 84*6509Ssam register struct protosw *lproto; 85*6509Ssam struct raw_header *rh; 865612Swnj struct socket *last; 875121Swnj 885121Swnj COUNT(RAWINTR); 895121Swnj next: 905121Swnj s = splimp(); 915121Swnj IF_DEQUEUE(&rawintrq, m); 925121Swnj splx(s); 935121Swnj if (m == 0) 945121Swnj return; 95*6509Ssam rh = mtod(m, struct raw_header *); 965612Swnj 975612Swnj /* 985612Swnj * Find the appropriate socket(s) in which to place this 995612Swnj * packet. This is done by matching the protocol and 1005612Swnj * address information prepended by raw_input against 1015612Swnj * the info stored in the control block structures. 1025612Swnj */ 1035612Swnj last = 0; 1045612Swnj for (rp = rawcb.rcb_next; rp != &rawcb; rp = rp->rcb_next) { 105*6509Ssam lproto = rp->rcb_socket->so_proto; 106*6509Ssam if (lproto->pr_family != rh->raw_proto.sp_family) 1075612Swnj continue; 108*6509Ssam if (lproto->pr_protocol && 109*6509Ssam lproto->pr_protocol != rh->raw_proto.sp_protocol) 1105612Swnj continue; 111*6509Ssam laddr = &rp->rcb_laddr; 112*6509Ssam if (laddr->sa_family && 113*6509Ssam laddr->sa_family != rh->raw_dst.sa_family) 114*6509Ssam continue; 1155612Swnj /* 1165612Swnj * We assume the lower level routines have 1175612Swnj * placed the address in a canonical format 118*6509Ssam * suitable for a structure comparison. 1195612Swnj */ 120*6509Ssam if ((rp->rcb_flags & RAW_LADDR) && 121*6509Ssam bcmp(laddr->sa_data, rh->raw_dst.sa_data, 14) != 0) 1225612Swnj continue; 123*6509Ssam if ((rp->rcb_flags & RAW_FADDR) && 124*6509Ssam bcmp(rp->rcb_faddr.sa_data, rh->raw_src.sa_data, 14) != 0) 125*6509Ssam continue; 1265612Swnj /* 1275612Swnj * To avoid extraneous packet copies, we keep 1285612Swnj * track of the last socket the packet should be 1295612Swnj * placed in, and make copies only after finding a 1305612Swnj * socket which "collides". 1315612Swnj */ 1325612Swnj if (last) { 1335612Swnj struct mbuf *n; 1345612Swnj 1356161Ssam if (n = m_copy(m->m_next, 0, (int)M_COPYALL)) 1365612Swnj goto nospace; 137*6509Ssam if (sbappendaddr(&last->so_rcv, &rh->raw_src, n)==0) { 138*6509Ssam /* should notify about lost packet */ 1395646Ssam m_freem(n); 1405646Ssam goto nospace; 1415646Ssam } 1425612Swnj sorwakeup(last); 1435612Swnj } 1445612Swnj nospace: 145*6509Ssam last = rp->rcb_socket; 1465612Swnj } 1475612Swnj if (last == 0) 1485612Swnj goto drop; 149*6509Ssam m = m_free(m); /* header */ 150*6509Ssam if (sbappendaddr(&last->so_rcv, &rh->raw_src, m) == 0) 1515646Ssam goto drop; 1525612Swnj sorwakeup(last); 1535612Swnj goto next; 1545121Swnj drop: 1555121Swnj m_freem(m); 1565121Swnj goto next; 1575121Swnj } 1585121Swnj 1595121Swnj /*ARGSUSED*/ 1605121Swnj raw_usrreq(so, req, m, addr) 1615121Swnj struct socket *so; 1625121Swnj int req; 1635121Swnj struct mbuf *m; 1645121Swnj caddr_t addr; 1655121Swnj { 1665612Swnj register struct rawcb *rp = sotorawcb(so); 1675612Swnj int error = 0; 1685121Swnj 1695121Swnj COUNT(RAW_USRREQ); 1705612Swnj if (rp == 0 && req != PRU_ATTACH) 1715612Swnj return (EINVAL); 1725121Swnj 1735612Swnj switch (req) { 1745612Swnj 1755612Swnj /* 1765612Swnj * Allocate a raw control block and fill in the 1775612Swnj * necessary info to allow packets to be routed to 1785612Swnj * the appropriate raw interface routine. 1795612Swnj */ 1805612Swnj case PRU_ATTACH: 1816211Swnj if ((so->so_state & SS_PRIV) == 0) 1826211Swnj return (EPERM); 1835612Swnj if (rp) 1846211Swnj 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: 205*6509Ssam if (rp->rcb_flags & RAW_FADDR) 2065612Swnj return (EISCONN); 2075612Swnj raw_connaddr(rp, (struct sockaddr *)addr); 2085612Swnj soisconnected(so); 2095612Swnj break; 2105612Swnj 2115612Swnj case PRU_DISCONNECT: 212*6509Ssam if ((rp->rcb_flags & RAW_FADDR) == 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) { 231*6509Ssam if (rp->rcb_flags & RAW_FADDR) 2325612Swnj return (EISCONN); 2335612Swnj raw_connaddr(rp, (struct sockaddr *)addr); 234*6509Ssam } else if ((rp->rcb_flags & RAW_FADDR) == 0) 2355612Swnj return (ENOTCONN); 2366505Ssam error = (*so->so_proto->pr_output)(m, so); 2375612Swnj if (addr) 238*6509Ssam rp->rcb_flags &= ~RAW_FADDR; 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 259*6509Ssam case PRU_SOCKADDR: 260*6509Ssam bcopy(addr, (caddr_t)&rp->rcb_laddr, sizeof (struct sockaddr)); 261*6509Ssam break; 262*6509Ssam 2635612Swnj default: 2645612Swnj panic("raw_usrreq"); 2655612Swnj } 2665612Swnj return (error); 2675121Swnj } 268