1*5847Sroot /*	raw_imp.c	4.4	82/02/15	*/
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*/
20*5847Sroot rimp_ctlinput(m)
215637Sroot 	struct mbuf *m;
225637Sroot {
23*5847Sroot COUNT(RIMP_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  */
33*5847Sroot rimp_output(m, so)
345637Sroot 	register struct mbuf *m;
355637Sroot 	struct socket *so;
365637Sroot {
375637Sroot 	struct mbuf *n;
385637Sroot 	int len;
395647Ssam 	register struct imp_leader *ip;
405637Sroot 	register struct sockaddr_in *sin;
415637Sroot 	register struct rawcb *rp = sotorawcb(so);
425772Swnj 	struct ifnet *ifp;
435772Swnj 	struct control_leader *cp;
445637Sroot 
45*5847Sroot COUNT(RIMP_OUTPUT);
465637Sroot 	/*
475637Sroot 	 * Verify user has supplied necessary space
485637Sroot 	 * for the leader and check parameters in it.
495637Sroot 	 */
505772Swnj 	if ((m->m_off > MMAXOFF || m->m_len < sizeof(struct control_leader)) &&
515772Swnj 	    (m = m_pullup(m, sizeof(struct control_leader))) == 0)
525772Swnj 		return (0);
535772Swnj 	cp = mtod(m, struct control_leader *);
545772Swnj 	if (cp->dl_mtype == IMPTYPE_DATA)
555772Swnj 		if (m->m_len < sizeof(struct imp_leader) &&
565772Swnj 		    (m = m_pullup(m, sizeof(struct imp_leader))) == 0)
575772Swnj 			return (0);
585647Ssam 	ip = mtod(m, struct imp_leader *);
595647Ssam 	if (ip->il_format != IMP_NFF)
605637Sroot 		goto bad;
615647Ssam 	if (ip->il_link != IMPLINK_IP &&
625647Ssam 	    (ip->il_link < IMPLINK_LOWEXPER || ip->il_link > IMPLINK_HIGHEXPER))
635637Sroot 		goto bad;
645637Sroot 
655637Sroot 	/*
665637Sroot 	 * Fill in IMP leader -- impoutput refrains from rebuilding
675637Sroot 	 * the leader when it sees the protocol family PF_IMPLINK.
685637Sroot 	 * (message size calculated by walking through mbuf's)
695637Sroot 	 */
705637Sroot 	for (len = 0, n = m; n; n = n->m_next)
715637Sroot 		len += n->m_len;
725772Swnj 	ip->il_length = htons(len << 3);
735637Sroot 	sin = (struct sockaddr_in *)&rp->rcb_addr;
745647Ssam 	ip->il_network = sin->sin_addr.s_net;
755647Ssam 	ip->il_host = sin->sin_addr.s_host;
765647Ssam 	ip->il_imp = sin->sin_addr.s_imp;
775772Swnj printf("imp_output: net=%x, host=%x, imp=%x\n", ip->il_network, ip->il_host,
785772Swnj ip->il_impno);
795772Swnj 	ifp = if_ifonnetof(sin->sin_addr);
805772Swnj 	if (ifp == 0) {
815772Swnj 		ifp = if_gatewayfor(sin->sin_addr);
825772Swnj 		if (ifp == 0)
835772Swnj 			goto bad;
845772Swnj 	}
855772Swnj 	return (impoutput(ifp, m, PF_IMPLINK));
865637Sroot 
875637Sroot bad:
885637Sroot 	m_freem(m);
895637Sroot 	return (0);
905637Sroot }
915637Sroot 
925637Sroot /*
935637Sroot  * Intercept operations required to
945637Sroot  * maintain interface pointer used on output.
955637Sroot  */
96*5847Sroot rimp_usrreq(so, req, m, addr)
975637Sroot 	struct socket *so;
985637Sroot 	int req;
995637Sroot 	struct mbuf *m;
1005637Sroot 	caddr_t addr;
1015637Sroot {
1025637Sroot 	register struct rawcb *rp = sotorawcb(so);
1035772Swnj 	register struct sockaddr_in *sin;
1045772Swnj 	register struct ifnet *ifp;
1055637Sroot 
106*5847Sroot COUNT(RIMP_USRREQ);
1075637Sroot 	if (rp == 0 && req != PRU_ATTACH)
1085637Sroot 		return (EINVAL);
1095637Sroot 
1105637Sroot 	switch (req) {
1115637Sroot 
1125637Sroot 	/*
1135772Swnj 	 * Verify address has an interface to go with it.
1145637Sroot 	 */
1155772Swnj 	case PRU_CONNECT:
1165772Swnj 		if (rp->rcb_pcb)
1175772Swnj 			return (EISCONN);
1185637Sroot 		sin = (struct sockaddr_in *)addr;
1195637Sroot 		ifp = if_ifonnetof(sin->sin_addr);
1205637Sroot 		if (ifp == 0) {
1215637Sroot 			ifp = if_gatewayfor(sin->sin_addr);
1225637Sroot 			if (ifp == 0)
1235637Sroot 				return (EADDRNOTAVAIL);	/* XXX */
1245637Sroot 		}
1255637Sroot 		rp->rcb_pcb = (caddr_t)ifp;
1265637Sroot 		break;
1275637Sroot 
1285637Sroot 	case PRU_DISCONNECT:
1295637Sroot 		rp->rcb_pcb = 0;
1305637Sroot 		break;
1315637Sroot 
1325637Sroot 	case PRU_CONTROL:
1335637Sroot 		return (EOPNOTSUPP);
1345637Sroot 	}
1355637Sroot 	return (raw_usrreq(so, req, m, addr));
1365637Sroot }
137