X-Git-Url: https://git.subgeniuskitty.com/unix-history/.git/blobdiff_plain/668cc26dbe8e6ce075ead3e3cc4590d239277fe0..2effa891d5cb8f89de1e3acc96032ce915cb6c3c:/usr/src/sys/net/raw_usrreq.c diff --git a/usr/src/sys/net/raw_usrreq.c b/usr/src/sys/net/raw_usrreq.c index 5dbdd0226a..0670f0f7e7 100644 --- a/usr/src/sys/net/raw_usrreq.c +++ b/usr/src/sys/net/raw_usrreq.c @@ -1,54 +1,55 @@ -/* raw_usrreq.c 4.9 82/03/13 */ +/* raw_usrreq.c 6.1 83/07/29 */ #include "../h/param.h" #include "../h/mbuf.h" #include "../h/protosw.h" #include "../h/socket.h" #include "../h/socketvar.h" -#include "../h/mtpr.h" -#include "../net/in.h" -#include "../net/in_systm.h" +#include "../h/errno.h" + #include "../net/if.h" +#include "../net/route.h" +#include "../net/netisr.h" #include "../net/raw_cb.h" -#include "../errno.h" + +#include "../vax/mtpr.h" /* * Initialize raw connection block q. -*/ + */ raw_init() { -COUNT(RAW_INIT); + rawcb.rcb_next = rawcb.rcb_prev = &rawcb; + rawintrq.ifq_maxlen = IFQ_MAXLEN; } /* * Raw protocol interface. */ -raw_input(m0, pf, daf, saf) +raw_input(m0, proto, src, dst) struct mbuf *m0; - struct sockproto *pf; - struct sockaddr *daf, *saf; + struct sockproto *proto; + struct sockaddr *src, *dst; { register struct mbuf *m; struct raw_header *rh; int s; -COUNT(RAW_INPUT); /* * Rip off an mbuf for a generic header. */ - m = m_get(M_DONTWAIT); + m = m_get(M_DONTWAIT, MT_HEADER); if (m == 0) { m_freem(m0); return; } m->m_next = m0; - m->m_off = MMINOFF; m->m_len = sizeof(struct raw_header); rh = mtod(m, struct raw_header *); - rh->raw_dst = *daf; - rh->raw_src = *saf; - rh->raw_protocol = *pf; + rh->raw_dst = *dst; + rh->raw_src = *src; + rh->raw_proto = *proto; /* * Header now contains enough info to decide @@ -57,9 +58,12 @@ COUNT(RAW_INPUT); * running at software interrupt level. */ s = splimp(); - IF_ENQUEUE(&rawintrq, m); + if (IF_QFULL(&rawintrq)) + m_freem(m); + else + IF_ENQUEUE(&rawintrq, m); splx(s); - setrawintr(); + schednetisr(NETISR_RAW); } /* @@ -73,105 +77,94 @@ rawintr() int s; struct mbuf *m; register struct rawcb *rp; - register struct socket *so; - register struct protosw *pr; - register struct sockproto *sp; - register struct sockaddr *sa; - struct raw_header *rawp; + register struct protosw *lproto; + register struct raw_header *rh; struct socket *last; -COUNT(RAWINTR); next: s = splimp(); IF_DEQUEUE(&rawintrq, m); splx(s); if (m == 0) return; - rawp = mtod(m, struct raw_header *); - sp = &rawp->raw_protocol; - sa = &rawp->raw_dst; - - /* - * Find the appropriate socket(s) in which to place this - * packet. This is done by matching the protocol and - * address information prepended by raw_input against - * the info stored in the control block structures. - */ + rh = mtod(m, struct raw_header *); last = 0; for (rp = rawcb.rcb_next; rp != &rawcb; rp = rp->rcb_next) { - so = rp->rcb_socket; - pr = so->so_proto; - if (pr->pr_family != sp->sp_family || - (pr->pr_protocol && pr->pr_protocol != sp->sp_protocol)) + lproto = rp->rcb_socket->so_proto; + if (lproto->pr_family != rh->raw_proto.sp_family) continue; - if (so->so_addr.sa_family && - sa->sa_family != so->so_addr.sa_family) + if (lproto->pr_protocol && + lproto->pr_protocol != rh->raw_proto.sp_protocol) continue; /* * We assume the lower level routines have * placed the address in a canonical format - * suitable for a structure comparison. Packets - * are duplicated for each receiving socket. - * - * SHOULD HAVE A NUMBER OF MECHANISMS FOR - * MATCHING BASED ON rcb_flags + * suitable for a structure comparison. */ - if ((rp->rcb_flags & RAW_ADDR) && - bcmp(sa->sa_data, so->so_addr.sa_data, 14) != 0) +#define equal(a1, a2) \ + (bcmp((caddr_t)&(a1), (caddr_t)&(a2), sizeof (struct sockaddr)) == 0) + if ((rp->rcb_flags & RAW_LADDR) && + !equal(rp->rcb_laddr, rh->raw_dst)) + continue; + if ((rp->rcb_flags & RAW_FADDR) && + !equal(rp->rcb_faddr, rh->raw_src)) continue; - /* - * To avoid extraneous packet copies, we keep - * track of the last socket the packet should be - * placed in, and make copies only after finding a - * socket which "collides". - */ if (last) { struct mbuf *n; - - if (n = m_copy(m->m_next, 0, (int)M_COPYALL)) + if ((n = m_copy(m->m_next, 0, (int)M_COPYALL)) == 0) goto nospace; - if (sbappendaddr(&last->so_rcv, &rawp->raw_src, n) == 0) { - /* - * Should drop notification of lost packet - * into this guy's queue, but... - */ + if (sbappendaddr(&last->so_rcv, &rh->raw_src, + n, (struct mbuf *)0) == 0) { + /* should notify about lost packet */ m_freem(n); goto nospace; } sorwakeup(last); } nospace: - last = so; + last = rp->rcb_socket; + } + if (last) { + m = m_free(m); /* header */ + if (sbappendaddr(&last->so_rcv, &rh->raw_src, + m, (struct mbuf *)0) == 0) + goto drop; + sorwakeup(last); + goto next; } - if (last == 0) - goto drop; - if (sbappendaddr(&last->so_rcv, &rawp->raw_src, m->m_next) == 0) -{ -printf("rawintr: sbappendaddr failed\n"); - goto drop; -} - (void) m_free(m); /* generic header */ - sorwakeup(last); - goto next; drop: m_freem(m); goto next; } /*ARGSUSED*/ -raw_usrreq(so, req, m, addr) +raw_ctlinput(cmd, arg) + int cmd; + caddr_t arg; +{ + + if (cmd < 0 || cmd > PRC_NCMDS) + return; + /* INCOMPLETE */ +} + +/*ARGSUSED*/ +raw_usrreq(so, req, m, nam, rights) struct socket *so; int req; - struct mbuf *m; - caddr_t addr; + struct mbuf *m, *nam, *rights; { register struct rawcb *rp = sotorawcb(so); - int error = 0; - -COUNT(RAW_USRREQ); - if (rp == 0 && req != PRU_ATTACH) - return (EINVAL); + register int error = 0; + if (rights && rights->m_len) { + error = EOPNOTSUPP; + goto release; + } + if (rp == 0 && req != PRU_ATTACH) { + error = EINVAL; + goto release; + } switch (req) { /* @@ -180,9 +173,15 @@ COUNT(RAW_USRREQ); * the appropriate raw interface routine. */ case PRU_ATTACH: - if (rp) - return (EINVAL);; - error = raw_attach(so, (struct sockaddr *)addr); + if ((so->so_state & SS_PRIV) == 0) { + error = EACCES; + break; + } + if (rp) { + error = EINVAL; + break; + } + error = raw_attach(so); break; /* @@ -190,8 +189,10 @@ COUNT(RAW_USRREQ); * Flush data or not depending on the options. */ case PRU_DETACH: - if (rp == 0) - return (ENOTCONN); + if (rp == 0) { + error = ENOTCONN; + break; + } raw_detach(rp); break; @@ -202,15 +203,33 @@ COUNT(RAW_USRREQ); * nothing else around it should go to). */ case PRU_CONNECT: - if (rp->rcb_flags & RAW_ADDR) - return (EISCONN); - raw_connaddr(rp, (struct sockaddr *)addr); + if (rp->rcb_flags & RAW_FADDR) { + error = EISCONN; + break; + } + raw_connaddr(rp, nam); soisconnected(so); break; + case PRU_CONNECT2: + error = EOPNOTSUPP; + goto release; + + case PRU_BIND: + if (rp->rcb_flags & RAW_LADDR) { + error = EINVAL; /* XXX */ + break; + } + error = raw_bind(so, nam); + break; + case PRU_DISCONNECT: - if ((rp->rcb_flags & RAW_ADDR) == 0) - return (ENOTCONN); + if ((rp->rcb_flags & RAW_FADDR) == 0) { + error = ENOTCONN; + break; + } + if (rp->rcb_route.ro_rt) + rtfree(rp->rcb_route.ro_rt); raw_disconnect(rp); soisdisconnected(so); break; @@ -227,15 +246,34 @@ COUNT(RAW_USRREQ); * routine handles any massaging necessary. */ case PRU_SEND: - if (addr) { - if (rp->rcb_flags & RAW_ADDR) - return (EISCONN); - raw_connaddr(rp, (struct sockaddr *)addr); - } else if ((rp->rcb_flags & RAW_ADDR) == 0) - return (ENOTCONN); - (void) (*so->so_proto->pr_output)(m, so); - if (addr) - rp->rcb_flags &= ~RAW_ADDR; + if (nam) { + if (rp->rcb_flags & RAW_FADDR) { + error = EISCONN; + break; + } + raw_connaddr(rp, nam); + } else if ((rp->rcb_flags & RAW_FADDR) == 0) { + error = ENOTCONN; + break; + } + /* + * Check for routing. If new foreign address, or + * no route presently in use, try to allocate new + * route. On failure, just hand packet to output + * routine anyway in case it can handle it. + */ + if ((rp->rcb_flags & RAW_DONTROUTE) == 0) + if (!equal(rp->rcb_faddr, rp->rcb_route.ro_dst) || + rp->rcb_route.ro_rt == 0) { + if (rp->rcb_route.ro_rt) + rtfree(rp->rcb_route.ro_rt); + rp->rcb_route.ro_dst = rp->rcb_faddr; + rtalloc(&rp->rcb_route); + } + error = (*so->so_proto->pr_output)(m, so); + m = NULL; + if (nam) + rp->rcb_flags &= ~RAW_FADDR; break; case PRU_ABORT: @@ -244,20 +282,39 @@ COUNT(RAW_USRREQ); soisdisconnected(so); break; + case PRU_CONTROL: + m = NULL; + error = EOPNOTSUPP; + break; + /* * Not supported. */ case PRU_ACCEPT: case PRU_RCVD: - case PRU_CONTROL: case PRU_SENSE: case PRU_RCVOOB: case PRU_SENDOOB: error = EOPNOTSUPP; break; + case PRU_SOCKADDR: + bcopy((caddr_t)&rp->rcb_laddr, mtod(nam, caddr_t), + sizeof (struct sockaddr)); + nam->m_len = sizeof (struct sockaddr); + break; + + case PRU_PEERADDR: + bcopy((caddr_t)&rp->rcb_faddr, mtod(nam, caddr_t), + sizeof (struct sockaddr)); + nam->m_len = sizeof (struct sockaddr); + break; + default: panic("raw_usrreq"); } +release: + if (m != NULL) + m_freem(m); return (error); }