123170Smckusick /*
234853Sbostic  * Copyright (c) 1982, 1986, 1988 Regents of the University of California.
333453Skarels  * All rights reserved.
423170Smckusick  *
544469Sbostic  * %sccs.include.redist.c%
633453Skarels  *
7*56528Sbostic  *	@(#)raw_imp.c	7.7 (Berkeley) 10/11/92
823170Smckusick  */
95637Sroot 
10*56528Sbostic #include <sys/param.h>
11*56528Sbostic #include <sys/mbuf.h>
12*56528Sbostic #include <sys/socket.h>
13*56528Sbostic #include <sys/protosw.h>
14*56528Sbostic #include <sys/socketvar.h>
15*56528Sbostic #include <sys/errno.h>
1610900Ssam 
17*56528Sbostic #include <net/if.h>
18*56528Sbostic #include <net/route.h>
19*56528Sbostic #include <net/raw_cb.h>
2010900Ssam 
21*56528Sbostic #include <netinet/in.h>
22*56528Sbostic #include <netinet/in_systm.h>
23*56528Sbostic #include <netinet/in_var.h>
24*56528Sbostic #include <netinet/in_pcb.h>
25*56528Sbostic #include <netimp/if_imp.h>
265637Sroot 
275637Sroot /*
285637Sroot  * Raw interface to IMP.
295637Sroot  */
305637Sroot 
315637Sroot /*
325637Sroot  * Generate IMP leader and pass packet to impoutput.
335637Sroot  * The user must create a skeletal leader in order to
345637Sroot  * communicate message type, message subtype, etc.
355637Sroot  * We fill in holes where needed and verify parameters
365637Sroot  * supplied by user.
375637Sroot  */
rimp_output(m,so)385847Sroot rimp_output(m, so)
395637Sroot 	register struct mbuf *m;
405637Sroot 	struct socket *so;
415637Sroot {
425637Sroot 	struct mbuf *n;
436509Ssam 	int len, error = 0;
445647Ssam 	register struct imp_leader *ip;
455637Sroot 	register struct sockaddr_in *sin;
4637477Ssklower 	register struct raw_inpcb *rp = sotorawinpcb(so);
4718414Skarels 	struct in_ifaddr *ia;
485772Swnj 	struct control_leader *cp;
495637Sroot 
505637Sroot 	/*
515637Sroot 	 * Verify user has supplied necessary space
525637Sroot 	 * for the leader and check parameters in it.
535637Sroot 	 */
5437477Ssklower 	if ((m->m_len < sizeof(struct control_leader)) &&
556509Ssam 	    (m = m_pullup(m, sizeof(struct control_leader))) == 0) {
566509Ssam 		error = EMSGSIZE;	/* XXX */
576509Ssam 		goto bad;
586509Ssam 	}
595772Swnj 	cp = mtod(m, struct control_leader *);
605772Swnj 	if (cp->dl_mtype == IMPTYPE_DATA)
615772Swnj 		if (m->m_len < sizeof(struct imp_leader) &&
626509Ssam 		    (m = m_pullup(m, sizeof(struct imp_leader))) == 0) {
636509Ssam 			error = EMSGSIZE;	/* XXX */
646509Ssam 			goto bad;
656509Ssam 		}
665647Ssam 	ip = mtod(m, struct imp_leader *);
676509Ssam 	if (ip->il_format != IMP_NFF) {
686509Ssam 		error = EMSGSIZE;		/* XXX */
695637Sroot 		goto bad;
706509Ssam 	}
715870Sroot #ifdef notdef
725647Ssam 	if (ip->il_link != IMPLINK_IP &&
736509Ssam 	    (ip->il_link<IMPLINK_LOWEXPER || ip->il_link>IMPLINK_HIGHEXPER)) {
746509Ssam 		error = EPERM;
755637Sroot 		goto bad;
766509Ssam 	}
775870Sroot #endif
785637Sroot 
795637Sroot 	/*
805637Sroot 	 * Fill in IMP leader -- impoutput refrains from rebuilding
815637Sroot 	 * the leader when it sees the protocol family PF_IMPLINK.
825637Sroot 	 * (message size calculated by walking through mbuf's)
835637Sroot 	 */
845637Sroot 	for (len = 0, n = m; n; n = n->m_next)
855637Sroot 		len += n->m_len;
866161Ssam 	ip->il_length = htons((u_short)(len << 3));
8737477Ssklower 	sin = (struct sockaddr_in *)rp->rinp_rcb.rcb_faddr;
8834509Skarels 	imp_addr_to_leader((struct control_leader *)ip, sin->sin_addr.s_addr);
896339Ssam 	/* no routing here */
9018414Skarels 	ia = in_iaonnetof(in_netof(sin->sin_addr));
9118414Skarels 	if (ia)
9218414Skarels 		return (impoutput(ia->ia_ifp, m, (struct sockaddr *)sin));
936509Ssam 	error = ENETUNREACH;
945637Sroot bad:
955637Sroot 	m_freem(m);
966509Ssam 	return (error);
975637Sroot }
98