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