1*5647Ssam /*	raw_imp.c	4.2	82/02/01	*/
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"
135637Sroot #include "/usr/include/errno.h"
145637Sroot 
155637Sroot /*
165637Sroot  * Raw interface to IMP.
175637Sroot  */
185637Sroot 
195637Sroot /*ARGSUSED*/
205637Sroot imp_ctlinput(m)
215637Sroot 	struct mbuf *m;
225637Sroot {
235637Sroot COUNT(IMP_CTLINPUT);
245637Sroot }
255637Sroot 
265637Sroot /*
275637Sroot  * Generate IMP leader and pass packet to impoutput.
285637Sroot  * The user must create a skeletal leader in order to
295637Sroot  * communicate message type, message subtype, etc.
305637Sroot  * We fill in holes where needed and verify parameters
315637Sroot  * supplied by user.
325637Sroot  */
335637Sroot imp_output(m, so)		/* too close to impoutput */
345637Sroot 	register struct mbuf *m;
355637Sroot 	struct socket *so;
365637Sroot {
375637Sroot 	struct mbuf *n;
385637Sroot 	int len;
39*5647Ssam 	register struct imp_leader *ip;
405637Sroot 	register struct sockaddr_in *sin;
415637Sroot 	register struct rawcb *rp = sotorawcb(so);
425637Sroot 
435637Sroot COUNT(IMP_OUTPUT);
445637Sroot 	/*
455637Sroot 	 * Verify user has supplied necessary space
465637Sroot 	 * for the leader and check parameters in it.
475637Sroot 	 */
485637Sroot 	if ((m->m_off > MMAXOFF || m->m_len < sizeof(struct imp_leader)) &&
495637Sroot 	    (m = m_pullup(m, sizeof(struct imp_leader))) == 0)
505637Sroot 		goto bad;
51*5647Ssam 	ip = mtod(m, struct imp_leader *);
52*5647Ssam 	if (ip->il_format != IMP_NFF)
535637Sroot 		goto bad;
54*5647Ssam 	if (ip->il_link != IMPLINK_IP &&
55*5647Ssam 	    (ip->il_link < IMPLINK_LOWEXPER || ip->il_link > IMPLINK_HIGHEXPER))
565637Sroot 		goto bad;
575637Sroot 
585637Sroot 	/*
595637Sroot 	 * Fill in IMP leader -- impoutput refrains from rebuilding
605637Sroot 	 * the leader when it sees the protocol family PF_IMPLINK.
615637Sroot 	 * (message size calculated by walking through mbuf's)
625637Sroot 	 */
635637Sroot 	for (len = 0, n = m; n; n = n->m_next)
645637Sroot 		len += n->m_len;
65*5647Ssam 	ip->il_length = len << 3;
665637Sroot 	sin = (struct sockaddr_in *)&rp->rcb_addr;
67*5647Ssam 	ip->il_network = sin->sin_addr.s_net;
68*5647Ssam 	ip->il_host = sin->sin_addr.s_host;
69*5647Ssam 	ip->il_imp = sin->sin_addr.s_imp;
705637Sroot 
715637Sroot 	return (impoutput((struct ifnet *)rp->rcb_pcb, m, PF_IMPLINK));
725637Sroot 
735637Sroot bad:
745637Sroot 	m_freem(m);
755637Sroot 	return (0);
765637Sroot }
775637Sroot 
785637Sroot /*
795637Sroot  * Intercept operations required to
805637Sroot  * maintain interface pointer used on output.
815637Sroot  */
825637Sroot imp_usrreq(so, req, m, addr)
835637Sroot 	struct socket *so;
845637Sroot 	int req;
855637Sroot 	struct mbuf *m;
865637Sroot 	caddr_t addr;
875637Sroot {
885637Sroot 	register struct rawcb *rp = sotorawcb(so);
895637Sroot 
905637Sroot COUNT(IMP_USRREQ);
915637Sroot 	if (rp == 0 && req != PRU_ATTACH)
925637Sroot 		return (EINVAL);
935637Sroot 
945637Sroot 	switch (req) {
955637Sroot 
965637Sroot 	/*
975637Sroot 	 * Verify address has an interface to go with it
985637Sroot 	 * and record information for use in output routine.
995637Sroot 	 */
1005637Sroot 	case PRU_SEND:
1015637Sroot 	case PRU_CONNECT: {
1025637Sroot 		register struct sockaddr_in *sin;
1035637Sroot 		register struct ifnet *ifp;
1045637Sroot 
1055637Sroot 		sin = (struct sockaddr_in *)addr;
1065637Sroot 		ifp = if_ifonnetof(sin->sin_addr);
1075637Sroot 		if (ifp == 0) {
1085637Sroot 			ifp = if_gatewayfor(sin->sin_addr);
1095637Sroot 			if (ifp == 0)
1105637Sroot 				return (EADDRNOTAVAIL);	/* XXX */
1115637Sroot 		}
1125637Sroot 		rp->rcb_pcb = (caddr_t)ifp;
1135637Sroot 		break;
1145637Sroot 		}
1155637Sroot 
1165637Sroot 	case PRU_DISCONNECT:
1175637Sroot 		rp->rcb_pcb = 0;
1185637Sroot 		break;
1195637Sroot 
1205637Sroot 	case PRU_CONTROL:
1215637Sroot 		return (EOPNOTSUPP);
1225637Sroot 	}
1235637Sroot 	return (raw_usrreq(so, req, m, addr));
1245637Sroot }
125