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