1*5612Swnj /* raw_usrreq.c 4.5 82/01/24 */ 25121Swnj 35121Swnj #include "../h/param.h" 45121Swnj #include "../h/mbuf.h" 5*5612Swnj #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" 12*5612Swnj #include "../net/raw_cb.h" 13*5612Swnj #include "/usr/include/errno.h" 145121Swnj 155121Swnj /* 16*5612Swnj * Initialize raw connection block q. 17*5612Swnj */ 18*5612Swnj raw_init() 19*5612Swnj { 20*5612Swnj COUNT(RAW_INIT); 21*5612Swnj rawcb.rcb_next = rawcb.rcb_prev = &rawcb; 22*5612Swnj } 23*5612Swnj 24*5612Swnj /* 255121Swnj * Raw protocol interface. 265121Swnj */ 27*5612Swnj raw_input(m0, pf, af) 28*5612Swnj struct mbuf *m0; 295121Swnj struct sockproto pf; 305121Swnj struct sockaddr af; 315121Swnj { 32*5612Swnj register struct mbuf *m; 33*5612Swnj struct raw_header *rh; 345121Swnj int s; 355121Swnj 36*5612Swnj /* 37*5612Swnj * Rip off an mbuf for a generic header. 38*5612Swnj */ 39*5612Swnj m = m_get(M_DONTWAIT); 40*5612Swnj if (m == 0) { 41*5612Swnj m_freem(m0); 42*5612Swnj return; 43*5612Swnj } 44*5612Swnj m->m_next = m0; 45*5612Swnj m->m_off = MMINOFF; 46*5612Swnj m->m_len = sizeof(struct raw_header); 47*5612Swnj rh = mtod(m, struct raw_header *); 48*5612Swnj rh->raw_address = af; 49*5612Swnj rh->raw_protocol = pf; 50*5612Swnj 51*5612Swnj /* 52*5612Swnj * Header now contains enough info to decide 53*5612Swnj * which socket to place packet in (if any). 54*5612Swnj * Queue it up for the raw protocol process 55*5612Swnj * running at software interrupt level. 56*5612Swnj */ 575121Swnj s = splimp(); 58*5612Swnj IF_ENQUEUE(&rawintrq, m); 595121Swnj splx(s); 605121Swnj setrawintr(); 615121Swnj } 625121Swnj 63*5612Swnj /* 64*5612Swnj * Raw protocol input routine. Process packets entered 65*5612Swnj * into the queue at interrupt time. Find the socket 66*5612Swnj * associated with the packet(s) and move them over. If 67*5612Swnj * nothing exists for this packet, drop it. 68*5612Swnj */ 695121Swnj rawintr() 705121Swnj { 715121Swnj int s; 725121Swnj struct mbuf *m; 73*5612Swnj register struct rawcb *rp; 74*5612Swnj register struct socket *so; 75*5612Swnj register struct protosw *pr; 76*5612Swnj register struct sockproto *sp; 77*5612Swnj register struct sockaddr *sa; 78*5612Swnj struct socket *last; 795121Swnj 805121Swnj COUNT(RAWINTR); 815121Swnj next: 825121Swnj s = splimp(); 835121Swnj IF_DEQUEUE(&rawintrq, m); 845121Swnj splx(s); 855121Swnj if (m == 0) 865121Swnj return; 87*5612Swnj sp = &(mtod(m, struct raw_header *)->raw_protocol); 88*5612Swnj sa = &(mtod(m, struct raw_header *)->raw_address); 89*5612Swnj 90*5612Swnj /* 91*5612Swnj * Find the appropriate socket(s) in which to place this 92*5612Swnj * packet. This is done by matching the protocol and 93*5612Swnj * address information prepended by raw_input against 94*5612Swnj * the info stored in the control block structures. 95*5612Swnj */ 96*5612Swnj last = 0; 97*5612Swnj for (rp = rawcb.rcb_next; rp != &rawcb; rp = rp->rcb_next) { 98*5612Swnj so = rp->rcb_socket; 99*5612Swnj pr = so->so_proto; 100*5612Swnj 101*5612Swnj if (so->so_options & SO_DEBUG) { 102*5612Swnj printf("rawintr: sp=<%d,%d>, af=<%d,%x>\n", 103*5612Swnj sp->sp_family, sp->sp_protocol, sa->sa_family, 104*5612Swnj ((struct sockaddr_in *)sa)->sin_addr); 105*5612Swnj printf("pr=<%d,%d>\n", pr->pr_family, pr->pr_protocol); 106*5612Swnj } 107*5612Swnj if (pr->pr_family != sp->sp_family || 108*5612Swnj pr->pr_protocol != sp->sp_protocol) 109*5612Swnj continue; 110*5612Swnj printf("rawintr: so=<%d,%x>\n", so->so_addr.sa_family, 111*5612Swnj ((struct sockaddr_in *)&so->so_addr)->sin_addr); 112*5612Swnj if (sa->sa_family != so->so_addr.sa_family) 113*5612Swnj continue; 114*5612Swnj /* 115*5612Swnj * We assume the lower level routines have 116*5612Swnj * placed the address in a canonical format 117*5612Swnj * suitable for a structure comparison. Packets 118*5612Swnj * are duplicated for each receiving socket. 119*5612Swnj */ 120*5612Swnj if ((rp->rcb_flags & RAW_ADDR) && 121*5612Swnj bcmp(sa->sa_data, so->so_addr.sa_data, 14) != 0) 122*5612Swnj continue; 123*5612Swnj /* 124*5612Swnj * To avoid extraneous packet copies, we keep 125*5612Swnj * track of the last socket the packet should be 126*5612Swnj * placed in, and make copies only after finding a 127*5612Swnj * socket which "collides". 128*5612Swnj */ 129*5612Swnj if (last) { 130*5612Swnj struct mbuf *n; 131*5612Swnj 132*5612Swnj if (n = m_copy(m->m_next, 0, M_COPYALL)) 133*5612Swnj goto nospace; 134*5612Swnj sbappend(&last->so_rcv, n); 135*5612Swnj sorwakeup(last); 136*5612Swnj } 137*5612Swnj nospace: 138*5612Swnj last = so; 139*5612Swnj } 140*5612Swnj if (last == 0) 141*5612Swnj goto drop; 142*5612Swnj m = m_free(m); /* drop generic header */ 143*5612Swnj sbappend(&last->so_rcv, m->m_next); 144*5612Swnj sorwakeup(last); 145*5612Swnj goto next; 1465121Swnj drop: 1475121Swnj m_freem(m); 1485121Swnj goto next; 1495121Swnj } 1505121Swnj 1515121Swnj /*ARGSUSED*/ 1525121Swnj raw_usrreq(so, req, m, addr) 1535121Swnj struct socket *so; 1545121Swnj int req; 1555121Swnj struct mbuf *m; 1565121Swnj caddr_t addr; 1575121Swnj { 158*5612Swnj register struct rawcb *rp = sotorawcb(so); 159*5612Swnj int error = 0; 1605121Swnj 1615121Swnj COUNT(RAW_USRREQ); 162*5612Swnj if (so->so_options & SO_DEBUG) 163*5612Swnj printf("raw_usrreq: req=%d\n"); 164*5612Swnj if (rp == 0 && req != PRU_ATTACH) 165*5612Swnj return (EINVAL); 1665121Swnj 167*5612Swnj switch (req) { 168*5612Swnj 169*5612Swnj /* 170*5612Swnj * Allocate a raw control block and fill in the 171*5612Swnj * necessary info to allow packets to be routed to 172*5612Swnj * the appropriate raw interface routine. 173*5612Swnj */ 174*5612Swnj case PRU_ATTACH: 175*5612Swnj if (rp) 176*5612Swnj return (EINVAL);; 177*5612Swnj error = raw_attach(so, (struct sockaddr *)addr); 178*5612Swnj break; 179*5612Swnj 180*5612Swnj /* 181*5612Swnj * Destroy state just before socket deallocation. 182*5612Swnj * Flush data or not depending on the options. 183*5612Swnj */ 184*5612Swnj case PRU_DETACH: 185*5612Swnj if (rp == 0) 186*5612Swnj return (ENOTCONN); 187*5612Swnj raw_detach(rp); 188*5612Swnj break; 189*5612Swnj 190*5612Swnj /* 191*5612Swnj * If a socket isn't bound to a single address, 192*5612Swnj * the raw input routine will hand it anything 193*5612Swnj * within that protocol family (assuming there's 194*5612Swnj * nothing else around it should go to). 195*5612Swnj */ 196*5612Swnj case PRU_CONNECT: 197*5612Swnj if (rp->rcb_flags & RAW_ADDR) 198*5612Swnj return (EISCONN); 199*5612Swnj raw_connaddr(rp, (struct sockaddr *)addr); 200*5612Swnj soisconnected(so); 201*5612Swnj break; 202*5612Swnj 203*5612Swnj case PRU_DISCONNECT: 204*5612Swnj if ((rp->rcb_flags & RAW_ADDR) == 0) 205*5612Swnj return (ENOTCONN); 206*5612Swnj raw_disconnect(rp); 207*5612Swnj soisdisconnected(so); 208*5612Swnj break; 209*5612Swnj 210*5612Swnj /* 211*5612Swnj * Mark the connection as being incapable of further input. 212*5612Swnj */ 213*5612Swnj case PRU_SHUTDOWN: 214*5612Swnj socantsendmore(so); 215*5612Swnj break; 216*5612Swnj 217*5612Swnj /* 218*5612Swnj * Ship a packet out. The appropriate raw output 219*5612Swnj * routine handles any massaging necessary. 220*5612Swnj */ 221*5612Swnj case PRU_SEND: 222*5612Swnj if (addr) { 223*5612Swnj if (rp->rcb_flags & RAW_ADDR) 224*5612Swnj return (EISCONN); 225*5612Swnj raw_connaddr(rp, (struct sockaddr *)addr); 226*5612Swnj } else if ((rp->rcb_flags & RAW_ADDR) == 0) 227*5612Swnj return (ENOTCONN); 228*5612Swnj (void) (*so->so_proto->pr_output)(m, so); 229*5612Swnj if (addr) 230*5612Swnj rp->rcb_flags &= ~RAW_ADDR; 231*5612Swnj break; 232*5612Swnj 233*5612Swnj case PRU_ABORT: 234*5612Swnj raw_disconnect(rp); 235*5612Swnj sofree(so); 236*5612Swnj soisdisconnected(so); 237*5612Swnj break; 238*5612Swnj 239*5612Swnj /* 240*5612Swnj * Not supported. 241*5612Swnj */ 242*5612Swnj case PRU_ACCEPT: 243*5612Swnj case PRU_RCVD: 244*5612Swnj case PRU_CONTROL: 245*5612Swnj case PRU_SENSE: 246*5612Swnj case PRU_RCVOOB: 247*5612Swnj case PRU_SENDOOB: 248*5612Swnj error = EOPNOTSUPP; 249*5612Swnj break; 250*5612Swnj 251*5612Swnj default: 252*5612Swnj panic("raw_usrreq"); 253*5612Swnj } 254*5612Swnj return (error); 2555121Swnj } 256