/src/openthread/third_party/tcplp/bsdtcp/tcp_usrreq.c
Line | Count | Source |
1 | | /*- |
2 | | * Copyright (c) 1982, 1986, 1988, 1993 |
3 | | * The Regents of the University of California. |
4 | | * Copyright (c) 2006-2007 Robert N. M. Watson |
5 | | * Copyright (c) 2010-2011 Juniper Networks, Inc. |
6 | | * All rights reserved. |
7 | | * |
8 | | * Portions of this software were developed by Robert N. M. Watson under |
9 | | * contract to Juniper Networks, Inc. |
10 | | * |
11 | | * Redistribution and use in source and binary forms, with or without |
12 | | * modification, are permitted provided that the following conditions |
13 | | * are met: |
14 | | * 1. Redistributions of source code must retain the above copyright |
15 | | * notice, this list of conditions and the following disclaimer. |
16 | | * 2. Redistributions in binary form must reproduce the above copyright |
17 | | * notice, this list of conditions and the following disclaimer in the |
18 | | * documentation and/or other materials provided with the distribution. |
19 | | * 4. Neither the name of the University nor the names of its contributors |
20 | | * may be used to endorse or promote products derived from this software |
21 | | * without specific prior written permission. |
22 | | * |
23 | | * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND |
24 | | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
25 | | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
26 | | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE |
27 | | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
28 | | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
29 | | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
30 | | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
31 | | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
32 | | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
33 | | * SUCH DAMAGE. |
34 | | * |
35 | | * From: @(#)tcp_usrreq.c 8.2 (Berkeley) 1/3/94 |
36 | | */ |
37 | | |
38 | | #include <errno.h> |
39 | | #include <string.h> |
40 | | #include "../tcplp.h" |
41 | | #include "../lib/cbuf.h" |
42 | | #include "tcp.h" |
43 | | #include "tcp_fsm.h" |
44 | | #include "tcp_seq.h" |
45 | | #include "tcp_var.h" |
46 | | #include "tcp_timer.h" |
47 | | #include "tcp_fastopen.h" |
48 | | #include "ip6.h" |
49 | | |
50 | | #include "tcp_const.h" |
51 | | |
52 | | #include <openthread/tcp.h> |
53 | | |
54 | | //static void tcp_disconnect(struct tcpcb *); |
55 | | static void tcp_usrclosed(struct tcpcb *); |
56 | | |
57 | | /* |
58 | | * samkumar: Removed tcp6_usr_bind, since checking if an address/port is free |
59 | | * needs to be done at the host system (along with other socket management |
60 | | * duties). TCPlp doesn't know what other sockets are in the system, or which |
61 | | * other addresses/ports are busy. |
62 | | */ |
63 | | |
64 | | /* samkumar: This is based on a function in in6_pcb.c. */ |
65 | 0 | static int in6_pcbconnect(struct tcpcb* tp, struct sockaddr_in6* nam) { |
66 | 0 | register struct sockaddr_in6 *sin6 = nam; |
67 | 0 | tp->faddr = sin6->sin6_addr; |
68 | 0 | tp->fport = sin6->sin6_port; |
69 | 0 | return 0; |
70 | 0 | } |
71 | | |
72 | | /* |
73 | | * Initiate connection to peer. |
74 | | * Create a template for use in transmissions on this connection. |
75 | | * Enter SYN_SENT state, and mark socket as connecting. |
76 | | * Start keep-alive timer, and seed output sequence space. |
77 | | * Send initial segment on connection. |
78 | | */ |
79 | | /* |
80 | | * samkumar: I removed locking, statistics, and inpcb management. The signature |
81 | | * used to be |
82 | | * |
83 | | * static int |
84 | | * tcp6_connect(struct tcpcb *tp, struct sockaddr *nam, struct thread *td) |
85 | | */ |
86 | | static int |
87 | | tcp6_connect(struct tcpcb *tp, struct sockaddr_in6 *nam) |
88 | 0 | { |
89 | 0 | int error; |
90 | |
|
91 | 0 | int sb_max = cbuf_free_space(&tp->recvbuf); // same as sendbuf |
92 | | |
93 | | /* |
94 | | * samkumar: For autobind, the original BSD code assigned the port first |
95 | | * (with logic that also looked at the address) and then the address. This |
96 | | * was done by calling into other parts of the FreeBSD network stack, |
97 | | * outside of the TCP stack. Here, we just use the tcplp_sys_autobind |
98 | | * function to do all of that work. |
99 | | */ |
100 | 0 | bool autobind_addr = IN6_IS_ADDR_UNSPECIFIED(&tp->laddr); |
101 | 0 | bool autobind_port = (tp->lport == 0); |
102 | 0 | if (autobind_addr || autobind_port) { |
103 | 0 | otSockAddr foreign; |
104 | 0 | otSockAddr local; |
105 | |
|
106 | 0 | memcpy(&foreign.mAddress, &nam->sin6_addr, sizeof(foreign.mAddress)); |
107 | 0 | foreign.mPort = ntohs(nam->sin6_port); |
108 | |
|
109 | 0 | if (!autobind_addr) { |
110 | 0 | memcpy(&local.mAddress, &tp->laddr, sizeof(local.mAddress)); |
111 | 0 | } |
112 | |
|
113 | 0 | if (!autobind_port) { |
114 | 0 | local.mPort = ntohs(tp->lport); |
115 | 0 | } |
116 | |
|
117 | 0 | if (!tcplp_sys_autobind(tp->instance, &foreign, &local, autobind_addr, autobind_port)) { |
118 | | // Autobind failed |
119 | 0 | error = EINVAL; |
120 | 0 | goto out; |
121 | 0 | } |
122 | | |
123 | 0 | if (autobind_addr) { |
124 | 0 | memcpy(&tp->laddr, &local.mAddress, sizeof(tp->laddr)); |
125 | 0 | } |
126 | |
|
127 | 0 | if (autobind_port) { |
128 | 0 | tp->lport = htons(local.mPort); |
129 | 0 | } |
130 | 0 | } |
131 | 0 | error = in6_pcbconnect(tp, nam); |
132 | 0 | if (error != 0) |
133 | 0 | goto out; |
134 | | |
135 | | /* Compute window scaling to request. */ |
136 | 0 | while (tp->request_r_scale < TCP_MAX_WINSHIFT && |
137 | 0 | (TCP_MAXWIN << tp->request_r_scale) < sb_max) |
138 | 0 | tp->request_r_scale++; |
139 | |
|
140 | 0 | tcp_state_change(tp, TCPS_SYN_SENT); |
141 | 0 | tp->iss = tcp_new_isn(tp); |
142 | 0 | tcp_sendseqinit(tp); |
143 | |
|
144 | 0 | return 0; |
145 | | |
146 | 0 | out: |
147 | 0 | return error; |
148 | 0 | } |
149 | | |
150 | | /* |
151 | | * samkumar: I removed locking, statistics, inpcb management, and debug probes. |
152 | | * I also remove codepaths that check for IPv6, since the address is assumed to |
153 | | * be IPv6. The signature used to be |
154 | | * |
155 | | * static int |
156 | | * tcp6_usr_connect(struct socket *so, struct sockaddr *nam, struct thread *td) |
157 | | */ |
158 | | int |
159 | | tcp6_usr_connect(struct tcpcb* tp, struct sockaddr_in6* sin6p) |
160 | 0 | { |
161 | 0 | int error = 0; |
162 | |
|
163 | 0 | if (tp->t_state != TCPS_CLOSED) { // samkumar: This is a check that I added |
164 | 0 | return (EISCONN); |
165 | 0 | } |
166 | | |
167 | | /* samkumar: I removed the following error check since we receive sin6p |
168 | | * in the function argument and don't need to convert a struct sockaddr to |
169 | | * a struct sockaddr_in6 anymore. |
170 | | * |
171 | | * if (nam->sa_len != sizeof (*sin6p)) |
172 | | * return (EINVAL); |
173 | | */ |
174 | | |
175 | | /* |
176 | | * Must disallow TCP ``connections'' to multicast addresses. |
177 | | */ |
178 | | /* samkumar: I commented out the check on sin6p->sin6_family. */ |
179 | 0 | if (/*sin6p->sin6_family == AF_INET6 |
180 | 0 | && */IN6_IS_ADDR_MULTICAST(&sin6p->sin6_addr)) |
181 | 0 | return (EAFNOSUPPORT); |
182 | | |
183 | | /* |
184 | | * samkumar: There was some code here that obtained the TCB (struct tcpcb*) |
185 | | * by getting the inpcb from the socket and the TCB from the inpcb. I |
186 | | * removed that code. |
187 | | */ |
188 | | |
189 | | /* |
190 | | * XXXRW: Some confusion: V4/V6 flags relate to binding, and |
191 | | * therefore probably require the hash lock, which isn't held here. |
192 | | * Is this a significant problem? |
193 | | */ |
194 | 0 | if (IN6_IS_ADDR_V4MAPPED(&sin6p->sin6_addr)) { |
195 | 0 | tcplp_sys_log("V4-Mapped Address!"); |
196 | | |
197 | | /* |
198 | | * samkumar: There used to be code that woulf handle the case of |
199 | | * v4-mapped addresses. It would call in6_sin6_2_sin to convert the |
200 | | * struct sockaddr_in6 to a struct sockaddr_in, set the INP_IPV4 flag |
201 | | * and clear the INP_IPV6 flag on inp->inp_vflag, do some other |
202 | | * processing, and finally call tcp_connect and tcplp_output. However, |
203 | | * it would first check if the IN6P_IPV6_V6ONLY flag was set in |
204 | | * inp->inp_flags, and if so, it would return with EINVAL. In TCPlp, we |
205 | | * support IPv6 only, so I removed the check for IN6P_IPV6_V6ONLY and |
206 | | * always act as if that flag is set. I kept the code in that if |
207 | | * statement making the check, and removed the other code that actually |
208 | | * handled this case. |
209 | | */ |
210 | 0 | error = EINVAL; |
211 | 0 | goto out; |
212 | 0 | } |
213 | | |
214 | | /* |
215 | | * samkumar: I removed some code here that set/cleared some flags in the` |
216 | | * inpcb and called prison_remote_ip6. |
217 | | */ |
218 | | |
219 | | /* |
220 | | * samkumar: Originally, the struct thread *td was passed along to |
221 | | * tcp6_connect. |
222 | | */ |
223 | 0 | if ((error = tcp6_connect(tp, sin6p)) != 0) |
224 | 0 | goto out; |
225 | | |
226 | 0 | tcp_timer_activate(tp, TT_KEEP, TP_KEEPINIT(tp)); |
227 | 0 | error = tcplp_output(tp); |
228 | |
|
229 | 0 | out: |
230 | 0 | return (error); |
231 | 0 | } |
232 | | |
233 | | /* |
234 | | * Do a send by putting data in output queue and updating urgent |
235 | | * marker if URG set. Possibly send more data. Unlike the other |
236 | | * pru_*() routines, the mbuf chains are our responsibility. We |
237 | | * must either enqueue them or free them. The other pru_* routines |
238 | | * generally are caller-frees. |
239 | | */ |
240 | | /* |
241 | | * samkumar: I removed locking, statistics, inpcb management, and debug probes. |
242 | | * I also removed support for the urgent pointer. |
243 | | * |
244 | | * I changed the signature of this function. It used to be |
245 | | * static int |
246 | | * tcp_usr_send(struct socket *so, int flags, struct mbuf *m, |
247 | | * struct sockaddr *nam, struct mbuf *control, struct thread *td) |
248 | | * |
249 | | * The new function signature works as follows. DATA is a new linked buffer to |
250 | | * add to the end of the send buffer. EXTENDBY is the number of bytes by which |
251 | | * to extend the final linked buffer of the send buffer. Either DATA should be |
252 | | * NULL, or EXTENDBY should be 0. |
253 | | */ |
254 | | int tcp_usr_send(struct tcpcb* tp, int moretocome, otLinkedBuffer* data, size_t extendby, struct sockaddr_in6* nam) |
255 | 0 | { |
256 | 0 | int error = 0; |
257 | 0 | int do_fastopen_implied_connect = (nam != NULL) && IS_FASTOPEN(tp->t_flags) && tp->t_state < TCPS_SYN_SENT; |
258 | | |
259 | | /* |
260 | | * samkumar: This if statement and the next are checks that I added |
261 | | */ |
262 | 0 | if (tp->t_state < TCPS_ESTABLISHED && !IS_FASTOPEN(tp->t_flags)) { |
263 | 0 | error = ENOTCONN; |
264 | 0 | goto out; |
265 | 0 | } |
266 | | |
267 | 0 | if (tpiscantsend(tp)) { |
268 | 0 | error = EPIPE; |
269 | 0 | goto out; |
270 | 0 | } |
271 | | |
272 | | /* |
273 | | * samkumar: There used to be logic here that acquired locks, dealt with |
274 | | * INP_TIMEWAIT and INP_DROPPED flags on inp->inp_flags, and handled the |
275 | | * control mbuf passed as an argument (which would result in an error since |
276 | | * TCP doesn't support control information). I've deleted that code, but |
277 | | * added the following if block based on those checks. |
278 | | */ |
279 | 0 | if ((tp->t_state == TCPS_TIME_WAIT) || (tp->t_state == TCPS_CLOSED && !do_fastopen_implied_connect)) { |
280 | 0 | error = ECONNRESET; |
281 | 0 | goto out; |
282 | 0 | } |
283 | | |
284 | | /* |
285 | | * The following code used to be wrapped in an if statement: |
286 | | * "if (!(flags & PRUS_OOB))", that only executed it if the "out of band" |
287 | | * flag was not set. In TCP, "out of band" data is conveyed via the urgent |
288 | | * pointer, and TCPlp does not support the urgent pointer. Therefore, I |
289 | | * removed the "if" check and put its body below. |
290 | | */ |
291 | | |
292 | | /* |
293 | | * samkumar: The FreeBSD code calls sbappendstream(&so->so_snd, m, flags); |
294 | | * I've replaced it with the following logic, which appends to the |
295 | | * send buffer according to TCPlp's data structures. |
296 | | */ |
297 | 0 | if (data == NULL) { |
298 | 0 | if (extendby == 0) { |
299 | 0 | goto out; |
300 | 0 | } |
301 | 0 | lbuf_extend(&tp->sendbuf, extendby); |
302 | 0 | } else { |
303 | 0 | if (data->mLength == 0) { |
304 | 0 | goto out; |
305 | 0 | } |
306 | 0 | lbuf_append(&tp->sendbuf, data); |
307 | 0 | } |
308 | | |
309 | | /* |
310 | | * samkumar: There used to be code here to handle "implied connect," |
311 | | * which initiates the TCP handshake if sending data on a socket that |
312 | | * isn't yet connected. For now, I've special-cased this code to work |
313 | | * only for TCP Fast Open for IPv6 (since implied connect is the only |
314 | | * way to initiate a connection with TCP Fast Open). |
315 | | */ |
316 | 0 | if (do_fastopen_implied_connect) { |
317 | 0 | error = tcp6_connect(tp, nam); |
318 | 0 | if (error) |
319 | 0 | goto out; |
320 | 0 | tcp_fastopen_connect(tp); |
321 | 0 | } |
322 | | |
323 | | /* |
324 | | * samkumar: There used to be code here handling the PRUS_EOF flag in |
325 | | * the former flags parameter. I've removed this code. |
326 | | */ |
327 | | |
328 | | /* |
329 | | * samkumar: The code below was previously wrapped in an if statement |
330 | | * that checked that the INP_DROPPED flag in inp->inp_flags and the |
331 | | * PRUS_NOTREADY flag in the former flags parameter were both clear. |
332 | | * If either one was set, then tcplp_output would not be called. |
333 | | * |
334 | | * The "more to come" functionality was previously triggered via the |
335 | | * PRUS_MORETOCOME flag in the flags parameter to this function. Since |
336 | | * that's the only flag that TCPlp uses here, I replaced the flags |
337 | | * parameter with a "moretocome" parameter, which we check instead. |
338 | | */ |
339 | 0 | if (moretocome) |
340 | 0 | tp->t_flags |= TF_MORETOCOME; |
341 | 0 | error = tcplp_output(tp); |
342 | 0 | if (moretocome) |
343 | 0 | tp->t_flags &= ~TF_MORETOCOME; |
344 | | |
345 | | /* |
346 | | * samkumar: This is where the "if (!(flags & PRUS_OOB))" block would end. |
347 | | * There used to be a large "else" block handling out-of-band data, but I |
348 | | * removed that entire block since we do not support the urgent pointer in |
349 | | * TCPlp. |
350 | | */ |
351 | 0 | out: |
352 | 0 | return (error); |
353 | 0 | } |
354 | | |
355 | | /* |
356 | | * After a receive, possibly send window update to peer. |
357 | | */ |
358 | | int |
359 | | tcp_usr_rcvd(struct tcpcb* tp) |
360 | 0 | { |
361 | 0 | int error = 0; |
362 | | |
363 | | /* |
364 | | * samkumar: There used to be logic here that acquired locks, dealt with |
365 | | * INP_TIMEWAIT and INP_DROPPED flags on inp->inp_flags, and added debug |
366 | | * probes I've deleted that code, but left the following if block. |
367 | | */ |
368 | 0 | if ((tp->t_state == TCPS_TIME_WAIT) || (tp->t_state == TCPS_CLOSED)) { |
369 | 0 | error = ECONNRESET; |
370 | 0 | goto out; |
371 | 0 | } |
372 | | |
373 | | /* |
374 | | * For passively-created TFO connections, don't attempt a window |
375 | | * update while still in SYN_RECEIVED as this may trigger an early |
376 | | * SYN|ACK. It is preferable to have the SYN|ACK be sent along with |
377 | | * application response data, or failing that, when the DELACK timer |
378 | | * expires. |
379 | | */ |
380 | 0 | if (IS_FASTOPEN(tp->t_flags) && |
381 | 0 | (tp->t_state == TCPS_SYN_RECEIVED)) |
382 | 0 | goto out; |
383 | | |
384 | 0 | tcplp_output(tp); |
385 | |
|
386 | 0 | out: |
387 | 0 | return (error); |
388 | 0 | } |
389 | | |
390 | | /* |
391 | | * samkumar: Removed the tcp_disconnect function. It is meant to be a |
392 | | * "friendly" disconnect to complement the unceremonious "abort" functionality |
393 | | * that is also provbided. The FreeBSD implementation called it from |
394 | | * tcp_usr_close, which we removed (see the comment below for the reason why). |
395 | | * It's not called from anywhere else, so I'm removing this function entirely. |
396 | | */ |
397 | | |
398 | | /* |
399 | | * Mark the connection as being incapable of further output. |
400 | | */ |
401 | | /* |
402 | | * samkumar: Modified to remove locking, socket/inpcb handling, and debug |
403 | | * probes. |
404 | | */ |
405 | | int |
406 | | tcp_usr_shutdown(struct tcpcb* tp) |
407 | 0 | { |
408 | 0 | int error = 0; |
409 | | |
410 | | /* |
411 | | * samkumar: replaced checks on the INP_TIMEWAIT and INP_DROPPED flags on |
412 | | * inp->inp_flags with these checks on tp->t_state. |
413 | | */ |
414 | 0 | if ((tp->t_state == TCPS_TIME_WAIT) || (tp->t_state == TCPS_CLOSED)) { |
415 | 0 | error = ECONNRESET; |
416 | 0 | goto out; |
417 | 0 | } |
418 | | |
419 | | /* samkumar: replaced socantsendmore with tpcantsendmore */ |
420 | 0 | tpcantsendmore(tp); |
421 | 0 | tcp_usrclosed(tp); |
422 | | |
423 | | /* |
424 | | * samkumar: replaced check on INP_DROPPED flag in inp->inp_flags with |
425 | | * this check on tp->t_state. |
426 | | */ |
427 | 0 | if (tp->t_state != TCPS_CLOSED) |
428 | 0 | error = tcplp_output(tp); |
429 | |
|
430 | 0 | out: |
431 | 0 | return (error); |
432 | 0 | } |
433 | | |
434 | | |
435 | | /* |
436 | | * User issued close, and wish to trail through shutdown states: |
437 | | * if never received SYN, just forget it. If got a SYN from peer, |
438 | | * but haven't sent FIN, then go to FIN_WAIT_1 state to send peer a FIN. |
439 | | * If already got a FIN from peer, then almost done; go to LAST_ACK |
440 | | * state. In all other cases, have already sent FIN to peer (e.g. |
441 | | * after PRU_SHUTDOWN), and just have to play tedious game waiting |
442 | | * for peer to send FIN or not respond to keep-alives, etc. |
443 | | * We can let the user exit from the close as soon as the FIN is acked. |
444 | | */ |
445 | | /* |
446 | | * Removed locking, TCP Offload, and socket/inpcb handling. |
447 | | */ |
448 | | static void |
449 | | tcp_usrclosed(struct tcpcb *tp) |
450 | 0 | { |
451 | 0 | switch (tp->t_state) { |
452 | 0 | case TCPS_LISTEN: |
453 | 0 | tcp_state_change(tp, TCPS_CLOSED); |
454 | | /* FALLTHROUGH */ |
455 | 0 | case TCPS_CLOSED: |
456 | 0 | tp = tcp_close_tcb(tp); |
457 | 0 | tcplp_sys_connection_lost(tp, CONN_LOST_NORMAL); |
458 | | /* |
459 | | * tcp_close_tcb() should never return NULL here as the socket is |
460 | | * still open. |
461 | | */ |
462 | 0 | KASSERT(tp != NULL, |
463 | 0 | ("tcp_usrclosed: tcp_close_tcb() returned NULL")); |
464 | 0 | break; |
465 | | |
466 | 0 | case TCPS_SYN_SENT: |
467 | 0 | case TCPS_SYN_RECEIVED: |
468 | 0 | tp->t_flags |= TF_NEEDFIN; |
469 | 0 | break; |
470 | | |
471 | 0 | case TCPS_ESTABLISHED: |
472 | 0 | tcp_state_change(tp, TCPS_FIN_WAIT_1); |
473 | 0 | break; |
474 | | |
475 | 0 | case TCPS_CLOSE_WAIT: |
476 | 0 | tcp_state_change(tp, TCPS_LAST_ACK); |
477 | 0 | break; |
478 | 0 | } |
479 | 0 | if (tp->t_state >= TCPS_FIN_WAIT_2) { |
480 | | /* samkumar: commented out the following "soisdisconnected" line. */ |
481 | | // soisdisconnected(tp->t_inpcb->inp_socket); |
482 | | /* Prevent the connection hanging in FIN_WAIT_2 forever. */ |
483 | 0 | if (tp->t_state == TCPS_FIN_WAIT_2) { |
484 | 0 | int timeout; |
485 | |
|
486 | 0 | timeout = (tcp_fast_finwait2_recycle) ? |
487 | 0 | tcp_finwait2_timeout : TP_MAXIDLE(tp); |
488 | 0 | tcp_timer_activate(tp, TT_2MSL, timeout); |
489 | 0 | } |
490 | 0 | } |
491 | 0 | } |
492 | | |
493 | | /* |
494 | | * samkumar: I removed the tcp_usr_close function. It was meant to be called in |
495 | | * case the socket is closed. It calls tcp_disconnect if the underlying TCP |
496 | | * connection is still alive when the socket is closed ("full TCP state"). |
497 | | * In TCPlp, we can't handle this because we want to free up the underlying |
498 | | * memory immediately when the user deallocates a TCP connection, making it |
499 | | * unavailable for the somewhat more ceremonious closing that tcp_disconnect |
500 | | * would allow. The host system is expected to simply abort the connection if |
501 | | * the application deallocates it. |
502 | | */ |
503 | | |
504 | | /* |
505 | | * Abort the TCP. Drop the connection abruptly. |
506 | | */ |
507 | | /* |
508 | | * samkumar: Modified to remove locking, socket/inpcb handling, and debug |
509 | | * probes. |
510 | | */ |
511 | | void |
512 | | tcp_usr_abort(struct tcpcb* tp) |
513 | 0 | { |
514 | | /* |
515 | | * If we still have full TCP state, and we're not dropped, drop. |
516 | | */ |
517 | | /* |
518 | | * I replaced the checks on inp->inp_flags (which tested for the absence of |
519 | | * INP_TIMEWAIT and INP_DROPPED flags), with the following checks on |
520 | | * tp->t_state. |
521 | | */ |
522 | 0 | if (tp->t_state != TCP6S_TIME_WAIT && |
523 | 0 | tp->t_state != TCP6S_CLOSED) { |
524 | 0 | tcp_drop(tp, ECONNABORTED); |
525 | 0 | } else if (tp->t_state == TCP6S_TIME_WAIT) { // samkumar: I added this clause |
526 | 0 | tp = tcp_close_tcb(tp); |
527 | 0 | tcplp_sys_connection_lost(tp, CONN_LOST_NORMAL); |
528 | 0 | } |
529 | 0 | } |