xref: /original-bsd/sys/netiso/tuba_subr.c (revision 3705696b)
1 /*
2  * Copyright (c) 1992, 1993
3  *	The Regents of the University of California.  All rights reserved.
4  *
5  * %sccs.include.redist.c%
6  *
7  *	@(#)tuba_subr.c	8.1 (Berkeley) 06/10/93
8  */
9 
10 #include <sys/param.h>
11 #include <sys/proc.h>
12 #include <sys/systm.h>
13 #include <sys/malloc.h>
14 #include <sys/mbuf.h>
15 #include <sys/socket.h>
16 #include <sys/socketvar.h>
17 #include <sys/protosw.h>
18 #include <sys/errno.h>
19 
20 #include <net/route.h>
21 #include <net/if.h>
22 
23 #include <netinet/in.h>
24 #include <netinet/in_systm.h>
25 #include <netinet/ip.h>
26 #include <netinet/in_pcb.h>
27 #include <netinet/ip_var.h>
28 #include <netinet/ip_icmp.h>
29 #include <netinet/tcp.h>
30 #include <netinet/tcp_fsm.h>
31 #include <netinet/tcp_seq.h>
32 #include <netinet/tcp_timer.h>
33 #include <netinet/tcp_var.h>
34 #include <netinet/tcpip.h>
35 #include <netinet/tcp_debug.h>
36 
37 #include <netiso/argo_debug.h>
38 #include <netiso/iso.h>
39 #include <netiso/clnp.h>
40 #include <netiso/iso_pcb.h>
41 #include <netiso/iso_var.h>
42 #include <netiso/tuba_table.h>
43 
44 static	struct	sockaddr_iso null_siso = { sizeof(null_siso), AF_ISO, };
45 extern	int	tuba_table_size, tcp_keepidle, tcp_keepintvl, tcp_maxidle;
46 extern	int	tcppcbcachemiss, tcppredack, tcppreddat, tcprexmtthresh;
47 extern	struct	tcpiphdr tcp_saveti;
48 struct	inpcb	tuba_inpcb;
49 struct	inpcb	*tuba_last_inpcb = &tuba_inpcb;
50 struct	isopcb	tuba_isopcb;
51 /*
52  * Tuba initialization
53  */
54 tuba_init()
55 {
56 #define TUBAHDRSIZE (3 /*LLC*/ + 9 /*CLNP Fixed*/ + 42 /*Addresses*/ \
57 		     + 6 /*CLNP Segment*/ + 20 /*TCP*/)
58 
59 	tuba_inpcb.inp_next = tuba_inpcb.inp_prev = &tuba_inpcb;
60 	tuba_isopcb.isop_next = tuba_isopcb.isop_prev = &tuba_isopcb;
61 	tuba_isopcb.isop_faddr = &tuba_isopcb.isop_sfaddr;
62 	tuba_isopcb.isop_laddr = &tuba_isopcb.isop_sladdr;
63 	if (max_protohdr < TUBAHDRSIZE)
64 		max_protohdr = TUBAHDRSIZE;
65 	if (max_linkhdr + TUBAHDRSIZE > MHLEN)
66 		panic("tuba_init");
67 }
68 
69 struct addr_arg {
70 	int	error;
71 	int	offset;
72 	u_long	sum;
73 };
74 
75 /*
76  * Calculate contribution to fudge factor for TCP checksum,
77  * and coincidentally set pointer for convenience of clnp_output
78  * if we are are responding when there is no isopcb around.
79  */
80 static void
81 tuba_getaddr(arg, siso, index)
82 	register struct addr_arg *arg;
83 	struct sockaddr_iso **siso;
84 	u_long index;
85 {
86 	register struct tuba_cache *tc;
87 	if (index <= tuba_table_size && (tc = tuba_table[index])) {
88 		if (siso)
89 			*siso = &tc->tc_siso;
90 		arg->sum += (arg->offset & 1 ? tc->tc_ssum : tc->tc_sum)
91 				+ (0xffff ^ index);
92 		arg->offset += tc->tc_siso.siso_nlen + 1;
93 	} else
94 		arg->error = 1;
95 }
96 
97 tuba_output(m, tp)
98 	register struct mbuf *m;
99 	struct tcpcb *tp;
100 {
101 	register struct tcpiphdr *n;
102 	struct	isopcb *isop;
103 	struct	addr_arg arg;
104 
105 	if (tp == 0 || (n = tp->t_template) == 0 ||
106 	    (isop = (struct isopcb *)tp->t_tuba_pcb) == 0) {
107 		isop = &tuba_isopcb;
108 		n = mtod(m, struct tcpiphdr *);
109 		arg.error = arg.sum = arg.offset = 0;
110 		tuba_getaddr(&arg, &tuba_isopcb.isop_faddr, n->ti_dst.s_addr);
111 		tuba_getaddr(&arg, &tuba_isopcb.isop_laddr, n->ti_src.s_addr);
112 		REDUCE(arg.sum, arg.sum);
113 		goto adjust;
114 	}
115 	if (n->ti_sum == 0) {
116 		arg.error = arg.sum = arg.offset = 0;
117 		tuba_getaddr(&arg, (struct sockaddr_iso **)0, n->ti_dst.s_addr);
118 		tuba_getaddr(&arg, (struct sockaddr_iso **)0, n->ti_src.s_addr);
119 		REDUCE(arg.sum, arg.sum);
120 		n->ti_sum = arg.sum;
121 		n = mtod(m, struct tcpiphdr *);
122 	adjust:
123 		if (arg.error) {
124 			m_freem(m);
125 			return (EADDRNOTAVAIL);
126 		}
127 		REDUCE(n->ti_sum, n->ti_sum + (0xffff ^ arg.sum));
128 	}
129 	m->m_len -= sizeof (struct ip);
130 	m->m_pkthdr.len -= sizeof (struct ip);
131 	m->m_data += sizeof (struct ip);
132 	return (clnp_output(m, isop, m->m_pkthdr.len, 0));
133 }
134 
135 tuba_refcnt(isop, delta)
136 	struct isopcb *isop;
137 {
138 	register struct tuba_cache *tc;
139 	unsigned index, sum;
140 
141 	if (delta != 1)
142 		delta = -1;
143 	if (isop == 0 || isop->isop_faddr == 0 || isop->isop_laddr == 0 ||
144 	    (delta == -1 && isop->isop_tuba_cached == 0) ||
145 	    (delta == 1 && isop->isop_tuba_cached != 0))
146 		return;
147 	isop->isop_tuba_cached = (delta == 1);
148 	if ((index = tuba_lookup(isop->isop_faddr, M_DONTWAIT)) != 0 &&
149 	    (tc = tuba_table[index]) != 0 && (delta == 1 || tc->tc_refcnt > 0))
150 		tc->tc_refcnt += delta;
151 	if ((index = tuba_lookup(isop->isop_laddr, M_DONTWAIT)) != 0 &&
152 	    (tc = tuba_table[index]) != 0 && (delta == 1 || tc->tc_refcnt > 0))
153 		tc->tc_refcnt += delta;
154 }
155 
156 tuba_pcbdetach(isop)
157 	struct isopcb *isop;
158 {
159 	if (isop == 0)
160 		return;
161 	tuba_refcnt(isop, -1);
162 	isop->isop_socket = 0;
163 	iso_pcbdetach(isop);
164 }
165 
166 /*
167  * Avoid  in_pcbconnect in faked out tcp_input()
168  */
169 tuba_pcbconnect(inp, nam)
170 	register struct inpcb *inp;
171 	struct mbuf *nam;
172 {
173 	register struct sockaddr_iso *siso;
174 	struct sockaddr_in *sin = mtod(nam, struct sockaddr_in *);
175 	struct tcpcb *tp = intotcpcb(inp);
176 	struct isopcb *isop = (struct isopcb *)tp->t_tuba_pcb;
177 	int error;
178 
179 	/* hardwire iso_pcbbind() here */
180 	siso = isop->isop_laddr = &isop->isop_sladdr;
181 	*siso = tuba_table[inp->inp_laddr.s_addr]->tc_siso;
182 	siso->siso_tlen = sizeof(inp->inp_lport);
183 	bcopy((caddr_t)&inp->inp_lport, TSEL(siso), sizeof(inp->inp_lport));
184 
185 	/* hardwire in_pcbconnect() here without assigning route */
186 	inp->inp_fport = sin->sin_port;
187 	inp->inp_faddr = sin->sin_addr;
188 
189 	/* reuse nam argument to call iso_pcbconnect() */
190 	nam->m_len = sizeof(*siso);
191 	siso = mtod(nam, struct sockaddr_iso *);
192 	*siso = tuba_table[inp->inp_faddr.s_addr]->tc_siso;
193 	siso->siso_tlen = sizeof(inp->inp_fport);
194 	bcopy((caddr_t)&inp->inp_fport, TSEL(siso), sizeof(inp->inp_fport));
195 
196 	if ((error = iso_pcbconnect(isop, nam)) == 0)
197 		tuba_refcnt(isop, 1);
198 	return (error);
199 }
200 
201 /*
202  * CALLED FROM:
203  * 	clnp's input routine, indirectly through the protosw.
204  * FUNCTION and ARGUMENTS:
205  * Take a packet (m) from clnp, strip off the clnp header
206  * and do tcp input processing.
207  * No return value.
208  */
209 tuba_tcpinput(m, src, dst)
210 	register struct mbuf *m;
211 	struct sockaddr_iso *src, *dst;
212 {
213 	unsigned long sum, lindex, findex;
214 	register struct tcpiphdr *ti;
215 	register struct inpcb *inp;
216 	caddr_t optp = NULL;
217 	int optlen;
218 	int len, tlen, off;
219 	register struct tcpcb *tp = 0;
220 	int tiflags;
221 	struct socket *so;
222 	int todrop, acked, ourfinisacked, needoutput = 0;
223 	short ostate;
224 	struct in_addr laddr;
225 	int dropsocket = 0, iss = 0;
226 	u_long tiwin, ts_val, ts_ecr;
227 	int ts_present = 0;
228 
229 	if ((m->m_flags & M_PKTHDR) == 0)
230 		panic("tuba_tcpinput");
231 	/*
232 	 * Do some housekeeping looking up CLNP addresses.
233 	 * If we are out of space might as well drop the packet now.
234 	 */
235 	tcpstat.tcps_rcvtotal++;
236 	lindex = tuba_lookup(dst, M_DONTWAIT);
237 	findex = tuba_lookup(src, M_DONTWAIT);
238 	if (lindex == 0 || findex == 0)
239 		goto drop;
240 	/*
241 	 * CLNP gave us an mbuf chain WITH the clnp header pulled up,
242 	 * but the data pointer pushed past it.
243 	 */
244 	len = m->m_len;
245 	tlen = m->m_pkthdr.len;
246 	m->m_data -= sizeof(struct ip);
247 	m->m_len += sizeof(struct ip);
248 	m->m_pkthdr.len += sizeof(struct ip);
249 	m->m_flags &= ~(M_MCAST|M_BCAST); /* XXX should do this in clnp_input */
250 	/*
251 	 * The reassembly code assumes it will be overwriting a useless
252 	 * part of the packet, which is why we need to have it point
253 	 * into the packet itself.
254 	 *
255 	 * Check to see if the data is properly alligned
256 	 * so that we can save copying the tcp header.
257 	 * This code knows way too much about the structure of mbufs!
258 	 */
259 	off = ((sizeof (long) - 1) & ((m->m_flags & M_EXT) ?
260 		(m->m_data - m->m_ext.ext_buf) :  (m->m_data - m->m_pktdat)));
261 	if (off || len < sizeof(struct tcphdr)) {
262 		struct mbuf *m0 = m;
263 
264 		MGETHDR(m, M_DONTWAIT, MT_DATA);
265 		if (m == 0) {
266 			m = m0;
267 			goto drop;
268 		}
269 		m->m_next = m0;
270 		m->m_data += max_linkhdr;
271 		m->m_pkthdr = m0->m_pkthdr;
272 		m->m_flags = m0->m_flags & M_COPYFLAGS;
273 		if (len < sizeof(struct tcphdr)) {
274 			m->m_len = 0;
275 			if ((m = m_pullup(m, sizeof(struct tcpiphdr))) == 0) {
276 				tcpstat.tcps_rcvshort++;
277 				return;
278 			}
279 		} else {
280 			bcopy(mtod(m0, caddr_t) + sizeof(struct ip),
281 			      mtod(m, caddr_t) + sizeof(struct ip),
282 			      sizeof(struct tcphdr));
283 			m0->m_len -= sizeof(struct tcpiphdr);
284 			m0->m_data += sizeof(struct tcpiphdr);
285 			m->m_len = sizeof(struct tcpiphdr);
286 		}
287 	}
288 	/*
289 	 * Calculate checksum of extended TCP header and data,
290 	 * replacing what would have been IP addresses by
291 	 * the IP checksum of the CLNP addresses.
292 	 */
293 	ti = mtod(m, struct tcpiphdr *);
294 	ti->ti_dst.s_addr = tuba_table[lindex]->tc_sum;
295 	if (dst->siso_nlen & 1)
296 		ti->ti_src.s_addr = tuba_table[findex]->tc_sum;
297 	else
298 		ti->ti_src.s_addr = tuba_table[findex]->tc_ssum;
299 	ti->ti_prev = ti->ti_next = 0;
300 	ti->ti_x1 = 0; ti->ti_pr = ISOPROTO_TCP;
301 	ti->ti_len = htons((u_short)tlen);
302 	if (ti->ti_sum = in_cksum(m, m->m_pkthdr.len)) {
303 		tcpstat.tcps_rcvbadsum++;
304 		goto drop;
305 	}
306 	ti->ti_src.s_addr = findex;
307 	ti->ti_dst.s_addr = lindex;
308 	/*
309 	 * Now include the rest of TCP input
310 	 */
311 #define TUBA_INCLUDE
312 #define	in_pcbconnect	tuba_pcbconnect
313 #define	tcb		tuba_inpcb
314 #define tcp_last_inpcb	tuba_last_inpcb
315 
316 #include <netinet/tcp_input.c>
317 }
318 
319 #define tcp_slowtimo	tuba_slowtimo
320 #define tcp_fasttimo	tuba_fasttimo
321 
322 #include <netinet/tcp_timer.c>
323