1 /*-
2  * Copyright (c) 1982, 1986, 1988, 1990, 1993, 1995
3  *	The Regents of the University of California.  All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  * 4. Neither the name of the University nor the names of its contributors
14  *    may be used to endorse or promote products derived from this software
15  *    without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
18  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
21  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27  * SUCH DAMAGE.
28  *
29  *	@(#)tcp_subr.c	8.2 (Berkeley) 5/24/95
30  */
31 
32 #include <errno.h>
33 #include <stddef.h>
34 #include <string.h>
35 
36 #include "../tcplp.h"
37 #include "ip.h"
38 #include "ip6.h"
39 #include "tcp.h"
40 #include "tcp_fsm.h"
41 #include "tcp_var.h"
42 #include "tcp_seq.h"
43 #include "tcp_timer.h"
44 #include "sys/queue.h"
45 #include "../lib/bitmap.h"
46 #include "../lib/cbuf.h"
47 #include "cc.h"
48 #include "tcp_fastopen.h"
49 
50 #include "tcp_const.h"
51 
52 /*
53  * samkumar: This is rewritten to have the host network stack to generate the
54  * ISN with appropriate randomness.
55  */
tcp_new_isn(struct tcpcb * tp)56 tcp_seq tcp_new_isn(struct tcpcb* tp) {
57 	return (uint32_t) tcplp_sys_generate_isn();
58 }
59 
60 /*
61  * samkumar: There used to be a function, void tcp_init(void), that would
62  * initialize global state for TCP, including a hash table to store TCBs,
63  * allocating memory zones for sockets, and setting global configurable state.
64  * In FreeBSD 12.0, it also makes a call to the function tcp_fastopen_init.
65  * None of that is needed for TCPlp: TCB allocation and matching is done by
66  * the host system and global configurable state is removed with hardcoded
67  * values in order to save memory, for example. Thus, I've removed the function
68  * entirely.
69  */
70 
71 /*
72  * A subroutine which makes it easy to track TCP state changes with DTrace.
73  * This function shouldn't be called for t_state initializations that don't
74  * correspond to actual TCP state transitions.
75  */
76 void
tcp_state_change(struct tcpcb * tp,int newstate)77 tcp_state_change(struct tcpcb *tp, int newstate)
78 {
79 #if 0
80 #if defined(KDTRACE_HOOKS)
81 	int pstate = tp->t_state;
82 #endif
83 #endif
84 	tcplp_sys_log("Socket %p: %s --> %s", tp, tcpstates[tp->t_state], tcpstates[newstate]);
85 	tp->t_state = newstate;
86 
87 	// samkumar: may need to do other actions too, so call into the host
88 	tcplp_sys_on_state_change(tp, newstate);
89 #if 0
90 	TCP_PROBE6(state__change, NULL, tp, NULL, tp, NULL, pstate);
91 #endif
92 }
93 
94  /* samkumar: Based on tcp_newtcb in tcp_subr.c, and tcp_usr_attach in tcp_usrreq.c. */
initialize_tcb(struct tcpcb * tp)95 __attribute__((used)) void initialize_tcb(struct tcpcb* tp) {
96 	uint32_t ticks = tcplp_sys_get_ticks();
97 
98 	/* samkumar: Clear all fields starting laddr; rest are initialized by the host. */
99 	memset(((uint8_t*) tp) + offsetof(struct tcpcb, laddr), 0x00, sizeof(struct tcpcb) - offsetof(struct tcpcb, laddr));
100 	tp->reass_fin_index = -1;
101 
102 	/*
103 	 * samkumar: Only New Reno congestion control is implemented at the moment,
104 	 * so there's no need to record the congestion control algorithm used for
105 	 * each TCB.
106 	 */
107 	// CC_ALGO(tp) = CC_DEFAULT();
108 	// tp->ccv->type = IPPROTO_TCP;
109 	tp->ccv->ccvc.tcp = tp;
110 
111 	/*
112 	 * samkumar: The original code used to choose a different constant
113 	 * depending on whether it's an IPv4 or IPv6 connection. In TCPlp, we
114 	 * unconditionally choose the IPv6 branch.
115 	 */
116 	tp->t_maxseg = tp->t_maxopd =
117 //#ifdef INET6
118 		/*isipv6 ? */V_tcp_v6mssdflt /*:*/
119 //#endif /* INET6 */
120 		/*V_tcp_mssdflt*/;
121 
122 	if (V_tcp_do_rfc1323)
123 		tp->t_flags = (TF_REQ_SCALE|TF_REQ_TSTMP);
124 	if (V_tcp_do_sack)
125 		tp->t_flags |= TF_SACK_PERMIT;
126 	TAILQ_INIT(&tp->snd_holes);
127 
128 	/*
129 	 * Init srtt to TCPTV_SRTTBASE (0), so we can tell that we have no
130 	 * rtt estimate.  Set rttvar so that srtt + 4 * rttvar gives
131 	 * reasonable initial retransmit time.
132 	 */
133 	tp->t_srtt = TCPTV_SRTTBASE;
134 	tp->t_rttvar = ((TCPTV_RTOBASE - TCPTV_SRTTBASE) << TCP_RTTVAR_SHIFT) / 4;
135 	tp->t_rttmin = TCPTV_MIN < 1 ? 1 : TCPTV_MIN; /* samkumar: used to be tcp_rexmit_min, which was set in tcp_init */
136 	tp->t_rxtcur = TCPTV_RTOBASE;
137 	tp->snd_cwnd = TCP_MAXWIN << TCP_MAX_WINSHIFT;
138 	tp->snd_ssthresh = TCP_MAXWIN << TCP_MAX_WINSHIFT;
139 	tp->t_rcvtime = ticks;
140 
141 	/* samkumar: Taken from tcp_usr_attach in tcp_usrreq.c. */
142 	tp->t_state = TCP6S_CLOSED;
143 
144 	/* samkumar: Added to initialize the per-TCP sackhole pool. */
145 	tcp_sack_init(tp);
146 }
147 
148 
149 /*
150  * samkumar: Most of this function was no longer needed. It did things like
151  * reference-counting for the TCB, updating host cache stats for better
152  * starting values of, e.g., ssthresh, for new connections, freeing resources
153  * for TCP offloading, etc. There's no host cache in TCPlp and the host system
154  * is responsible for managing TCB memory, so much of this isn't needed. I just
155  * kept (and adpated) the few parts of the function that appeared to be needed
156  * for TCPlp.
157  */
158 void
tcp_discardcb(struct tcpcb * tp)159 tcp_discardcb(struct tcpcb *tp)
160 {
161 	tcp_cancel_timers(tp);
162 
163 	/* Allow the CC algorithm to clean up after itself. */
164 	if (CC_ALGO(tp)->cb_destroy != NULL)
165 		CC_ALGO(tp)->cb_destroy(tp->ccv);
166 
167 	tcp_free_sackholes(tp);
168 }
169 
170 
171  /*
172  * Attempt to close a TCP control block, marking it as dropped, and freeing
173  * the socket if we hold the only reference.
174  */
175 /*
176  * samkumar: Most of this function has to do with dropping the reference to
177  * the inpcb, freeing resources at the socket layer and marking it as
178  * disconnected, and miscellaneous cleanup. I've rewritten this to do what is
179  * needed for TCP.
180  */
181 struct tcpcb *
tcp_close(struct tcpcb * tp)182 tcp_close(struct tcpcb *tp)
183 {
184 	/* samkumar: Eliminate the TFO pending counter. */
185 	/*
186 	if (tp->t_tfo_pending) {
187 		tcp_fastopen_decrement_counter(tp->t_tfo_pending);
188 		tp->t_tfo_pending = NULL;
189 	}
190 	*/
191 	tcp_state_change(tp, TCP6S_CLOSED); // for the print statement
192 	tcp_discardcb(tp);
193 	// Don't reset the TCB by calling initialize_tcb, since that overwrites the buffer contents.
194 	return tp;
195 }
196 
197 /*
198  * Create template to be used to send tcp packets on a connection.
199  * Allocates an mbuf and fills in a skeletal tcp/ip header.  The only
200  * use for this function is in keepalives, which use tcp_respond.
201  */
202 /*
203  * samkumar: I changed the signature of this function. Instead of allocating
204  * the struct tcptemp using malloc, populating it, and then returning it, I
205  * have the caller allocate it. This function merely populates it now.
206  */
207 void
tcpip_maketemplate(struct tcpcb * tp,struct tcptemp * t)208 tcpip_maketemplate(struct tcpcb* tp, struct tcptemp* t)
209 {
210 	tcpip_fillheaders(tp, (void *)&t->tt_ipgen, (void *)&t->tt_t);
211 }
212 
213 /*
214  * Fill in the IP and TCP headers for an outgoing packet, given the tcpcb.
215  * tcp_template used to store this data in mbufs, but we now recopy it out
216  * of the tcpcb each time to conserve mbufs.
217  */
218 /*
219  * samkumar: This has a different signature from the original function in
220  * tcp_subr.c. In particular, IP header information is filled into an
221  * otMessageInfo rather than into a struct representing the on-wire header
222  * format. Additionally, I have changed it to always assume IPv6; I removed the
223  * code for IPv4.
224  */
225 void
tcpip_fillheaders(struct tcpcb * tp,otMessageInfo * ip_ptr,void * tcp_ptr)226 tcpip_fillheaders(struct tcpcb* tp, otMessageInfo* ip_ptr, void *tcp_ptr)
227 {
228 	struct tcphdr *th = (struct tcphdr *)tcp_ptr;
229 
230 	/* Fill in the IP header */
231 
232     /* samkumar: The old IPv6 code, for reference. */
233 	// ip6 = (struct ip6_hdr *)ip_ptr;
234 	// ip6->ip6_flow = (ip6->ip6_flow & ~IPV6_FLOWINFO_MASK) |
235 	//     (inp->inp_flow & IPV6_FLOWINFO_MASK);
236 	// ip6->ip6_vfc = (ip6->ip6_vfc & ~IPV6_VERSION_MASK) |
237 	//     (IPV6_VERSION & IPV6_VERSION_MASK);
238 	// ip6->ip6_nxt = IPPROTO_TCP;
239 	// ip6->ip6_plen = htons(sizeof(struct tcphdr));
240 	// ip6->ip6_src = inp->in6p_laddr;
241 	// ip6->ip6_dst = inp->in6p_faddr;
242 
243 	memset(ip_ptr, 0x00, sizeof(otMessageInfo));
244 	memcpy(&ip_ptr->mSockAddr, &tp->laddr, sizeof(ip_ptr->mSockAddr));
245 	memcpy(&ip_ptr->mPeerAddr, &tp->faddr, sizeof(ip_ptr->mPeerAddr));
246 
247 	/* Fill in the TCP header */
248 	/* samkumar: I kept the old code commented out, for reference. */
249 	//th->th_sport = inp->inp_lport;
250 	//th->th_dport = inp->inp_fport;
251 	th->th_sport = tp->lport;
252 	th->th_dport = tp->fport;
253 	th->th_seq = 0;
254 	th->th_ack = 0;
255 	// th->th_x2 = 0;
256 	// th->th_off = 5;
257 	th->th_off_x2 = (5 << TH_OFF_SHIFT);
258 	th->th_flags = 0;
259 	th->th_win = 0;
260 	th->th_urp = 0;
261 	th->th_sum = 0;		/* in_pseudo() is called later for ipv4 */
262 }
263 
264 /*
265  * Send a single message to the TCP at address specified by
266  * the given TCP/IP header.  If m == NULL, then we make a copy
267  * of the tcpiphdr at th and send directly to the addressed host.
268  * This is used to force keep alive messages out using the TCP
269  * template for a connection.  If flags are given then we send
270  * a message back to the TCP which originated the segment th,
271  * and discard the mbuf containing it and any other attached mbufs.
272  *
273  * In any case the ack and sequence number of the transmitted
274  * segment are as specified by the parameters.
275  *
276  * NOTE: If m != NULL, then th must point to *inside* the mbuf.
277  */
278 /* samkumar: Original signature was
279 void
280 tcp_respond(struct tcpcb *tp, void *ipgen, struct tcphdr *th, struct mbuf *m,
281 	tcp_seq ack, tcp_seq seq, int flags)
282 */
283 /*
284  * samkumar: Essentially all of the code had to be discarded/rewritten since I
285  * have to send out packets by allocating buffers from the host system,
286  * populating them, and passing them back to the host system to send out. I
287  * simplified the code by only using the logic that was fully necessary,
288  * eliminating the code for IPv4 packets and keeping only the code for IPv6
289  * packets. I also removed all of the mbuf logic, instead using the logic for
290  * using the host system's buffering (in particular, the code to reuse the
291  * provided mbuf is no longer there).
292  */
293 void
tcp_respond(struct tcpcb * tp,otInstance * instance,struct ip6_hdr * ip6gen,struct tcphdr * thgen,tcp_seq ack,tcp_seq seq,int flags)294 tcp_respond(struct tcpcb *tp, otInstance* instance, struct ip6_hdr* ip6gen, struct tcphdr *thgen,
295 	tcp_seq ack, tcp_seq seq, int flags)
296 {
297 	otMessage* message = tcplp_sys_new_message(instance);
298 	if (message == NULL) {
299 		return;
300 	}
301 	if (otMessageSetLength(message, sizeof(struct tcphdr)) != OT_ERROR_NONE) {
302 		tcplp_sys_free_message(instance, message);
303 		return;
304 	}
305 
306 	struct tcphdr th;
307 	struct tcphdr* nth = &th;
308 	otMessageInfo ip6info;
309 	int win = 0;
310 	if (tp != NULL) {
311 		if (!(flags & TH_RST)) {
312 			win = cbuf_free_space(&tp->recvbuf);
313 			if (win > (long)TCP_MAXWIN << tp->rcv_scale)
314 				win = (long)TCP_MAXWIN << tp->rcv_scale;
315 		}
316 	}
317 	memset(&ip6info, 0x00, sizeof(otMessageInfo));
318 	memcpy(&ip6info.mSockAddr, &ip6gen->ip6_dst, sizeof(ip6info.mSockAddr));
319 	memcpy(&ip6info.mPeerAddr, &ip6gen->ip6_src, sizeof(ip6info.mPeerAddr));
320 	nth->th_sport = thgen->th_dport;
321 	nth->th_dport = thgen->th_sport;
322 	nth->th_seq = htonl(seq);
323 	nth->th_ack = htonl(ack);
324 	/* samkumar: original code for setting th_x2 and th_off, for reference. */
325 	// nth->th_x2 = 0;
326 	// nth->th_off = (sizeof (struct tcphdr) + optlen) >> 2;
327 	nth->th_off_x2 = (sizeof(struct tcphdr) >> 2) << TH_OFF_SHIFT;
328 	nth->th_flags = flags;
329 	if (tp != NULL)
330 		nth->th_win = htons((uint16_t) (win >> tp->rcv_scale));
331 	else
332 		nth->th_win = htons((uint16_t)win);
333 	nth->th_urp = 0;
334 	nth->th_sum = 0;
335 
336 	otMessageWrite(message, 0, &th, sizeof(struct tcphdr));
337 
338 	tcplp_sys_send_message(instance, message, &ip6info);
339 }
340 
341 /*
342  * Drop a TCP connection, reporting
343  * the specified error.  If connection is synchronized,
344  * then send a RST to peer.
345  */
346 /*
347  * samkumar: I changed the parameter "errno" to "errnum" since it caused
348  * problems during compilation. I also the code for asserting locks,
349  * incermenting stats, and managing the sockets layer.
350  */
351 struct tcpcb *
tcp_drop(struct tcpcb * tp,int errnum)352 tcp_drop(struct tcpcb *tp, int errnum)
353 {
354 	if (TCPS_HAVERCVDSYN(tp->t_state)) {
355 		tcp_state_change(tp, TCPS_CLOSED);
356 		(void) tcp_output(tp);
357 	}
358 	if (errnum == ETIMEDOUT && tp->t_softerror)
359 		errnum = tp->t_softerror;
360 	tp = tcp_close(tp);
361 	tcplp_sys_connection_lost(tp, errnum);
362 	return tp;
363 }
364 
365 /*
366  * Look-up the routing entry to the peer of this inpcb.  If no route
367  * is found and it cannot be allocated, then return 0.  This routine
368  * is called by TCP routines that access the rmx structure and by
369  * tcp_mss_update to get the peer/interface MTU.
370  */
371 /*
372  * samkumar: In TCPlp, we don't bother with keeping track of the MTU for each
373  * route. The MSS we choose for the 6LoWPAN/802.15.4 network is probably the
374  * bottleneck, so we just use that. (I also removed the struct in_conninfo *
375  * that was formerly the first argument).
376  */
377 uint64_t
tcp_maxmtu6(struct tcpcb * tp,struct tcp_ifcap * cap)378 tcp_maxmtu6(struct tcpcb* tp, struct tcp_ifcap *cap)
379 {
380 	uint64_t maxmtu = 0;
381 
382 	KASSERT (tp != NULL, ("tcp_maxmtu6 with NULL tcpcb pointer"));
383 	if (!IN6_IS_ADDR_UNSPECIFIED(&tp->faddr)) {
384 		maxmtu = FRAMES_PER_SEG * FRAMECAP_6LOWPAN;
385 	}
386 
387 	return (maxmtu);
388 }
389