1*5637Sroot /*	raw_imp.c	4.1	82/02/01	*/
2*5637Sroot 
3*5637Sroot #include "../h/param.h"
4*5637Sroot #include "../h/mbuf.h"
5*5637Sroot #include "../h/socket.h"
6*5637Sroot #include "../h/protosw.h"
7*5637Sroot #include "../h/socketvar.h"
8*5637Sroot #include "../net/in.h"
9*5637Sroot #include "../net/in_systm.h"
10*5637Sroot #include "../net/if.h"
11*5637Sroot #include "../net/if_imp.h"
12*5637Sroot #include "../net/raw_cb.h"
13*5637Sroot #include "/usr/include/errno.h"
14*5637Sroot 
15*5637Sroot /*
16*5637Sroot  * Raw interface to IMP.
17*5637Sroot  */
18*5637Sroot 
19*5637Sroot /*ARGSUSED*/
20*5637Sroot imp_ctlinput(m)
21*5637Sroot 	struct mbuf *m;
22*5637Sroot {
23*5637Sroot COUNT(IMP_CTLINPUT);
24*5637Sroot }
25*5637Sroot 
26*5637Sroot /*
27*5637Sroot  * Generate IMP leader and pass packet to impoutput.
28*5637Sroot  * The user must create a skeletal leader in order to
29*5637Sroot  * communicate message type, message subtype, etc.
30*5637Sroot  * We fill in holes where needed and verify parameters
31*5637Sroot  * supplied by user.
32*5637Sroot  */
33*5637Sroot imp_output(m, so)		/* too close to impoutput */
34*5637Sroot 	register struct mbuf *m;
35*5637Sroot 	struct socket *so;
36*5637Sroot {
37*5637Sroot 	struct mbuf *n;
38*5637Sroot 	int len;
39*5637Sroot 	register struct imp_leader *il;
40*5637Sroot 	register struct sockaddr_in *sin;
41*5637Sroot 	register struct rawcb *rp = sotorawcb(so);
42*5637Sroot 
43*5637Sroot COUNT(IMP_OUTPUT);
44*5637Sroot 	/*
45*5637Sroot 	 * Verify user has supplied necessary space
46*5637Sroot 	 * for the leader and check parameters in it.
47*5637Sroot 	 */
48*5637Sroot 	if ((m->m_off > MMAXOFF || m->m_len < sizeof(struct imp_leader)) &&
49*5637Sroot 	    (m = m_pullup(m, sizeof(struct imp_leader))) == 0)
50*5637Sroot 		goto bad;
51*5637Sroot 	il = mtod(m, struct imp_leader *);
52*5637Sroot 	if (il->il_format != IMP_NFF)
53*5637Sroot 		goto bad;
54*5637Sroot 	if (il->il_link != IMPLINK_IP &&
55*5637Sroot 	    (il->il_link < IMPLINK_LOWEXPER || il->il_link > IMPLINK_HIGHEXPER))
56*5637Sroot 		goto bad;
57*5637Sroot 
58*5637Sroot 	/*
59*5637Sroot 	 * Fill in IMP leader -- impoutput refrains from rebuilding
60*5637Sroot 	 * the leader when it sees the protocol family PF_IMPLINK.
61*5637Sroot 	 * (message size calculated by walking through mbuf's)
62*5637Sroot 	 */
63*5637Sroot 	for (len = 0, n = m; n; n = n->m_next)
64*5637Sroot 		len += n->m_len;
65*5637Sroot 	il->il_length = len << 3;
66*5637Sroot 	sin = (struct sockaddr_in *)&rp->rcb_addr;
67*5637Sroot 	il->il_network = sin->sin_addr.s_net;
68*5637Sroot 	il->il_host = sin->sin_addr.s_host;
69*5637Sroot 	il->il_imp = sin->sin_addr.s_imp;
70*5637Sroot 
71*5637Sroot 	return (impoutput((struct ifnet *)rp->rcb_pcb, m, PF_IMPLINK));
72*5637Sroot 
73*5637Sroot bad:
74*5637Sroot 	m_freem(m);
75*5637Sroot 	return (0);
76*5637Sroot }
77*5637Sroot 
78*5637Sroot /*
79*5637Sroot  * Intercept operations required to
80*5637Sroot  * maintain interface pointer used on output.
81*5637Sroot  */
82*5637Sroot imp_usrreq(so, req, m, addr)
83*5637Sroot 	struct socket *so;
84*5637Sroot 	int req;
85*5637Sroot 	struct mbuf *m;
86*5637Sroot 	caddr_t addr;
87*5637Sroot {
88*5637Sroot 	register struct rawcb *rp = sotorawcb(so);
89*5637Sroot 
90*5637Sroot COUNT(IMP_USRREQ);
91*5637Sroot 	if (rp == 0 && req != PRU_ATTACH)
92*5637Sroot 		return (EINVAL);
93*5637Sroot 
94*5637Sroot 	switch (req) {
95*5637Sroot 
96*5637Sroot 	/*
97*5637Sroot 	 * Verify address has an interface to go with it
98*5637Sroot 	 * and record information for use in output routine.
99*5637Sroot 	 */
100*5637Sroot 	case PRU_SEND:
101*5637Sroot 	case PRU_CONNECT: {
102*5637Sroot 		register struct sockaddr_in *sin;
103*5637Sroot 		register struct ifnet *ifp;
104*5637Sroot 
105*5637Sroot 		sin = (struct sockaddr_in *)addr;
106*5637Sroot 		ifp = if_ifonnetof(sin->sin_addr);
107*5637Sroot 		if (ifp == 0) {
108*5637Sroot 			ifp = if_gatewayfor(sin->sin_addr);
109*5637Sroot 			if (ifp == 0)
110*5637Sroot 				return (EADDRNOTAVAIL);	/* XXX */
111*5637Sroot 		}
112*5637Sroot 		rp->rcb_pcb = (caddr_t)ifp;
113*5637Sroot 		break;
114*5637Sroot 		}
115*5637Sroot 
116*5637Sroot 	case PRU_DISCONNECT:
117*5637Sroot 		rp->rcb_pcb = 0;
118*5637Sroot 		break;
119*5637Sroot 
120*5637Sroot 	case PRU_CONTROL:
121*5637Sroot 		return (EOPNOTSUPP);
122*5637Sroot 	}
123*5637Sroot 	return (raw_usrreq(so, req, m, addr));
124*5637Sroot }
125