-/* raw_usrreq.c 4.6 82/02/01 */
+/* 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 "/usr/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;
/*
* 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
* 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);
}
/*
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 != sp->sp_protocol)
+ lproto = rp->rcb_socket->so_proto;
+ if (lproto->pr_family != rh->raw_proto.sp_family)
continue;
- if (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.
+ * 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, 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)
- 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) {
/*
* 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;
/*
* 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;
* 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;
* 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:
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);
}