1*6509Ssam /*	raw_imp.c	4.10	82/04/10	*/
25637Sroot 
35637Sroot #include "../h/param.h"
45637Sroot #include "../h/mbuf.h"
55637Sroot #include "../h/socket.h"
65637Sroot #include "../h/protosw.h"
75637Sroot #include "../h/socketvar.h"
85637Sroot #include "../net/in.h"
95637Sroot #include "../net/in_systm.h"
105637Sroot #include "../net/if.h"
115637Sroot #include "../net/if_imp.h"
125637Sroot #include "../net/raw_cb.h"
13*6509Ssam #include <errno.h>
145637Sroot 
155637Sroot /*
165637Sroot  * Raw interface to IMP.
175637Sroot  */
185637Sroot 
195637Sroot /*
205637Sroot  * Generate IMP leader and pass packet to impoutput.
215637Sroot  * The user must create a skeletal leader in order to
225637Sroot  * communicate message type, message subtype, etc.
235637Sroot  * We fill in holes where needed and verify parameters
245637Sroot  * supplied by user.
255637Sroot  */
265847Sroot rimp_output(m, so)
275637Sroot 	register struct mbuf *m;
285637Sroot 	struct socket *so;
295637Sroot {
305637Sroot 	struct mbuf *n;
31*6509Ssam 	int len, error = 0;
325647Ssam 	register struct imp_leader *ip;
335637Sroot 	register struct sockaddr_in *sin;
345637Sroot 	register struct rawcb *rp = sotorawcb(so);
355772Swnj 	struct ifnet *ifp;
365772Swnj 	struct control_leader *cp;
375637Sroot 
385847Sroot COUNT(RIMP_OUTPUT);
395637Sroot 	/*
405637Sroot 	 * Verify user has supplied necessary space
415637Sroot 	 * for the leader and check parameters in it.
425637Sroot 	 */
435772Swnj 	if ((m->m_off > MMAXOFF || m->m_len < sizeof(struct control_leader)) &&
44*6509Ssam 	    (m = m_pullup(m, sizeof(struct control_leader))) == 0) {
45*6509Ssam 		error = EMSGSIZE;	/* XXX */
46*6509Ssam 		goto bad;
47*6509Ssam 	}
485772Swnj 	cp = mtod(m, struct control_leader *);
495772Swnj 	if (cp->dl_mtype == IMPTYPE_DATA)
505772Swnj 		if (m->m_len < sizeof(struct imp_leader) &&
51*6509Ssam 		    (m = m_pullup(m, sizeof(struct imp_leader))) == 0) {
52*6509Ssam 			error = EMSGSIZE;	/* XXX */
53*6509Ssam 			goto bad;
54*6509Ssam 		}
555647Ssam 	ip = mtod(m, struct imp_leader *);
56*6509Ssam 	if (ip->il_format != IMP_NFF) {
57*6509Ssam 		error = EMSGSIZE;		/* XXX */
585637Sroot 		goto bad;
59*6509Ssam 	}
605870Sroot #ifdef notdef
615647Ssam 	if (ip->il_link != IMPLINK_IP &&
62*6509Ssam 	    (ip->il_link<IMPLINK_LOWEXPER || ip->il_link>IMPLINK_HIGHEXPER)) {
63*6509Ssam 		error = EPERM;
645637Sroot 		goto bad;
65*6509Ssam 	}
665870Sroot #endif
675637Sroot 
685637Sroot 	/*
695637Sroot 	 * Fill in IMP leader -- impoutput refrains from rebuilding
705637Sroot 	 * the leader when it sees the protocol family PF_IMPLINK.
715637Sroot 	 * (message size calculated by walking through mbuf's)
725637Sroot 	 */
735637Sroot 	for (len = 0, n = m; n; n = n->m_next)
745637Sroot 		len += n->m_len;
756161Ssam 	ip->il_length = htons((u_short)(len << 3));
76*6509Ssam 	sin = (struct sockaddr_in *)&rp->rcb_faddr;
775647Ssam 	ip->il_network = sin->sin_addr.s_net;
785647Ssam 	ip->il_host = sin->sin_addr.s_host;
795647Ssam 	ip->il_imp = sin->sin_addr.s_imp;
806339Ssam 	/* no routing here */
816339Ssam 	ifp = if_ifonnetof(ip->il_network);
82*6509Ssam 	if (ifp)
83*6509Ssam 		return (impoutput(ifp, m, (struct sockaddr *)sin));
84*6509Ssam 	error = ENETUNREACH;
855637Sroot bad:
865637Sroot 	m_freem(m);
87*6509Ssam 	return (error);
885637Sroot }
89