1*5671Ssam /*	raw_pup.c	4.1	82/02/02	*/
2*5671Ssam 
3*5671Ssam #include "../h/param.h"
4*5671Ssam #include "../h/mbuf.h"
5*5671Ssam #include "../h/socket.h"
6*5671Ssam #include "../h/protosw.h"
7*5671Ssam #include "../h/socketvar.h"
8*5671Ssam #include "../net/in.h"
9*5671Ssam #include "../net/in_systm.h"
10*5671Ssam #include "../net/pup.h"
11*5671Ssam #include "../net/raw_cb.h"
12*5671Ssam #include "/usr/include/errno.h"
13*5671Ssam 
14*5671Ssam /*
15*5671Ssam  * Raw PUP protocol interface.
16*5671Ssam  */
17*5671Ssam 
18*5671Ssam static struct sockaddr_pup pupaddr = { AF_PUP };
19*5671Ssam static struct sockproto pupproto = { PF_PUP };
20*5671Ssam 
21*5671Ssam /*
22*5671Ssam  * Setup generic address and protocol structures
23*5671Ssam  * for raw_input routine, then pass them along with
24*5671Ssam  * mbuf chain.
25*5671Ssam  */
26*5671Ssam rawpup_input(m)
27*5671Ssam 	struct mbuf *m;
28*5671Ssam {
29*5671Ssam 	register struct pup_header *pup = mtod(m, struct pup_header *);
30*5671Ssam 
31*5671Ssam COUNT(RAWPUP_INPUT);
32*5671Ssam 	pupproto.sp_protocol = pup->pup_type;
33*5671Ssam 	pupaddr.spup_addr = pup->pup_daddr;
34*5671Ssam 	raw_input(m, pupproto, pupaddr);
35*5671Ssam }
36*5671Ssam 
37*5671Ssam /*ARGSUSED*/
38*5671Ssam rawpup_ctlinput(m)
39*5671Ssam 	struct mbuf *m;
40*5671Ssam {
41*5671Ssam COUNT(RAWPUP_CTLINPUT);
42*5671Ssam }
43*5671Ssam 
44*5671Ssam /*
45*5671Ssam  * Encapsulate packet in PUP header which is supplied by the
46*5671Ssam  * user.  This is done to allow user to specify PUP identifier.
47*5671Ssam  */
48*5671Ssam rawpup_output(m0, so)
49*5671Ssam 	struct mbuf *m0;
50*5671Ssam 	struct socket *so;
51*5671Ssam {
52*5671Ssam 	register struct rawcb *rp = sotorawcb(so);
53*5671Ssam 	register struct pup_header *pup;
54*5671Ssam 	int len;
55*5671Ssam 	struct mbuf *n;
56*5671Ssam 	struct sockaddr_pup *spup;
57*5671Ssam 
58*5671Ssam COUNT(RAWPUP_OUTPUT);
59*5671Ssam 	/*
60*5671Ssam 	 * Verify user has supplied necessary space
61*5671Ssam 	 * for the header and check parameters in it.
62*5671Ssam 	 */
63*5671Ssam 	if ((m->m_off > MMAXOFF || m->m_len < sizeof(struct pup_header)) &&
64*5671Ssam 	    (m = m_pullup(m, sizeof(struct pup_header)) == 0) {
65*5671Ssam 		goto bad;
66*5671Ssam 	pup = mtod(m, struct pup_header *);
67*5671Ssam 	if (pup->pup_type == 0)
68*5671Ssam 		goto bad;
69*5671Ssam 	if (pup->pup_tcontrol && (pup->pup_tcontrol & ~PUP_TRACE))
70*5671Ssam 		goto bad;
71*5671Ssam 	for (len = 0, n = m; n; n = n->m_next)
72*5671Ssam 		len += n->m_len;
73*5671Ssam 	pup->pup_length = len;
74*5671Ssam 	spup = (struct sockaddr_pup *)&rp->rcb_addr;
75*5671Ssam 	pup->pup_dport = spup->spup_addr;
76*5671Ssam 
77*5671Ssam 	/*
78*5671Ssam 	 * Insure proper source address is included.
79*5671Ssam 	 */
80*5671Ssam 	spup = (struct sockadrr_pup *)rp->rcb_socket->so_addr;
81*5671Ssam 	pup->pup_sport = spup->spup_addr;
82*5671Ssam 	/* for now, assume user generates PUP checksum. */
83*5671Ssam 
84*5671Ssam 	if (rp->rcb_pcb == 0)			/* XXX */
85*5671Ssam 		panic("rawpup_output");
86*5671Ssam 	return (enoutput((struct ifnet *)rp->rcb_pcb, m, PF_PUP));
87*5671Ssam 
88*5671Ssam bad:
89*5671Ssam 	m_freem(m);
90*5671Ssam 	return (0);
91*5671Ssam }
92*5671Ssam 
93*5671Ssam /*
94*5671Ssam  * Intercept connects and sends to verify interface
95*5671Ssam  * exists for destination address.  Disconnects are
96*5671Ssam  * also looked at to insure pointer is invalidated.
97*5671Ssam  */
98*5671Ssam rawpup_usrreq(so, req, m, addr)
99*5671Ssam 	struct socket *so;
100*5671Ssam 	int req;
101*5671Ssam 	struct mbuf *m;
102*5671Ssam 	caddr_t addr;
103*5671Ssam {
104*5671Ssam 	register struct rawcb *rp = sotorawcb(so);
105*5671Ssam 
106*5671Ssam COUNT(RAWPUP_USRREQ);
107*5671Ssam 	if (rp == 0 && req != PRU_ATTACH)
108*5671Ssam 		return (EINVAL);
109*5671Ssam 
110*5671Ssam 	switch (req) {
111*5671Ssam 
112*5671Ssam 	/*
113*5671Ssam 	 * Verify address has an interface to go with it
114*5671Ssam 	 * and record information for use in output routine.
115*5671Ssam 	 */
116*5671Ssam 	case PRU_SEND:
117*5671Ssam 	case PRU_CONNECT: {
118*5671Ssam 		register struct sockaddr_pup *spup;
119*5671Ssam 		register struct ifnet *ifp;
120*5671Ssam 
121*5671Ssam 		spup = (struct sockaddr_pup *)addr;
122*5671Ssam 		ifp = if_ifonnetof(spup->spup_addr);
123*5671Ssam 		if (ifp == 0) {
124*5671Ssam 			ifp = if_gatewayfor(spup->spup_addr);
125*5671Ssam 			if (ifp == 0)
126*5671Ssam 				return (EADDRNOTAVAIL);	/* XXX */
127*5671Ssam 		}
128*5671Ssam 		rp->rcb_pcb = (caddr_t)ifp;
129*5671Ssam 		break;
130*5671Ssam 		}
131*5671Ssam 
132*5671Ssam 	case PRU_DISCONNECT:
133*5671Ssam 		rp->rcb_pcb = 0;
134*5671Ssam 		break;
135*5671Ssam 
136*5671Ssam 	case PRU_CONTROL:
137*5671Ssam 		return (EOPNOTSUPP);
138*5671Ssam 	}
139*5671Ssam 	return (raw_usrreq(so, req, m, addr));
140*5671Ssam }
141