1 /*
2  * Copyright (c) 1982, 1986, 1988 Regents of the University of California.
3  * All rights reserved.
4  *
5  * %sccs.include.redist.c%
6  *
7  *	@(#)raw_imp.c	7.6 (Berkeley) 06/28/90
8  */
9 
10 #include "param.h"
11 #include "mbuf.h"
12 #include "socket.h"
13 #include "protosw.h"
14 #include "socketvar.h"
15 #include "errno.h"
16 
17 #include "../net/if.h"
18 #include "../net/route.h"
19 #include "../net/raw_cb.h"
20 
21 #include "../netinet/in.h"
22 #include "../netinet/in_systm.h"
23 #include "../netinet/in_var.h"
24 #include "../netinet/in_pcb.h"
25 #include "if_imp.h"
26 
27 /*
28  * Raw interface to IMP.
29  */
30 
31 /*
32  * Generate IMP leader and pass packet to impoutput.
33  * The user must create a skeletal leader in order to
34  * communicate message type, message subtype, etc.
35  * We fill in holes where needed and verify parameters
36  * supplied by user.
37  */
38 rimp_output(m, so)
39 	register struct mbuf *m;
40 	struct socket *so;
41 {
42 	struct mbuf *n;
43 	int len, error = 0;
44 	register struct imp_leader *ip;
45 	register struct sockaddr_in *sin;
46 	register struct raw_inpcb *rp = sotorawinpcb(so);
47 	struct in_ifaddr *ia;
48 	struct control_leader *cp;
49 
50 	/*
51 	 * Verify user has supplied necessary space
52 	 * for the leader and check parameters in it.
53 	 */
54 	if ((m->m_len < sizeof(struct control_leader)) &&
55 	    (m = m_pullup(m, sizeof(struct control_leader))) == 0) {
56 		error = EMSGSIZE;	/* XXX */
57 		goto bad;
58 	}
59 	cp = mtod(m, struct control_leader *);
60 	if (cp->dl_mtype == IMPTYPE_DATA)
61 		if (m->m_len < sizeof(struct imp_leader) &&
62 		    (m = m_pullup(m, sizeof(struct imp_leader))) == 0) {
63 			error = EMSGSIZE;	/* XXX */
64 			goto bad;
65 		}
66 	ip = mtod(m, struct imp_leader *);
67 	if (ip->il_format != IMP_NFF) {
68 		error = EMSGSIZE;		/* XXX */
69 		goto bad;
70 	}
71 #ifdef notdef
72 	if (ip->il_link != IMPLINK_IP &&
73 	    (ip->il_link<IMPLINK_LOWEXPER || ip->il_link>IMPLINK_HIGHEXPER)) {
74 		error = EPERM;
75 		goto bad;
76 	}
77 #endif
78 
79 	/*
80 	 * Fill in IMP leader -- impoutput refrains from rebuilding
81 	 * the leader when it sees the protocol family PF_IMPLINK.
82 	 * (message size calculated by walking through mbuf's)
83 	 */
84 	for (len = 0, n = m; n; n = n->m_next)
85 		len += n->m_len;
86 	ip->il_length = htons((u_short)(len << 3));
87 	sin = (struct sockaddr_in *)rp->rinp_rcb.rcb_faddr;
88 	imp_addr_to_leader((struct control_leader *)ip, sin->sin_addr.s_addr);
89 	/* no routing here */
90 	ia = in_iaonnetof(in_netof(sin->sin_addr));
91 	if (ia)
92 		return (impoutput(ia->ia_ifp, m, (struct sockaddr *)sin));
93 	error = ENETUNREACH;
94 bad:
95 	m_freem(m);
96 	return (error);
97 }
98