1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3 * Based on net/ipv4/inet_connection_sock.c
4 * Authors: See the TCP sources
5 *
6 * NewIP INET
7 * An implementation of the TCP/IP protocol suite for the LINUX
8 * operating system. NewIP INET is implemented using the BSD Socket
9 * interface as the means of communication with the user level.
10 *
11 * Support for NewIP INET connection oriented protocols.
12 */
13 #define pr_fmt(fmt) KBUILD_MODNAME ": [%s:%d] " fmt, __func__, __LINE__
14
15 #include <linux/module.h>
16 #include <linux/nip.h>
17 #include <linux/jhash.h>
18
19 #include <net/tcp.h>
20 #include <net/nip_addrconf.h>
21 #include <net/inet_connection_sock.h>
22 #include <net/inet_hashtables.h>
23 #include <net/nip_route.h>
24 #include <net/sock.h>
25 #include <net/ninet_connection_sock.h>
26 #include <net/tcp_nip.h>
27 #include "tcp_nip_parameter.h"
28
29 /* Function
30 * Timeout handler for request processing, used to retransmit SYN+ACK
31 * Parameter
32 * t: Request control block
33 */
ninet_reqsk_timer_handler(struct timer_list * t)34 static void ninet_reqsk_timer_handler(struct timer_list *t)
35 {
36 struct request_sock *req = from_timer(req, t, rsk_timer);
37 struct sock *sk_listener = req->rsk_listener;
38 struct net *net = sock_net(sk_listener);
39 struct inet_connection_sock *icsk = inet_csk(sk_listener);
40 struct request_sock_queue *queue = &icsk->icsk_accept_queue;
41 int max_retries, thresh;
42
43 /* Defines the maximum number of retransmissions. Thresh defaults to 5 */
44 max_retries = icsk->icsk_syn_retries ? : net->ipv4.sysctl_tcp_synack_retries;
45 thresh = max_retries;
46
47 /* Check timeout times. SYN+ACK retransmission times +1 */
48 if (req->num_timeout <= thresh) {
49 unsigned long timeo;
50
51 req->rsk_ops->rtx_syn_ack(sk_listener, req);
52 req->num_retrans++;
53 /* If the number of times out is still 0, the number is increased by 1
54 * to determine whether it is the first time out
55 */
56 if (req->num_timeout++ == 0)
57 atomic_dec(&queue->young);
58 timeo = min(TCP_TIMEOUT_INIT, TCP_RTO_MAX);
59 mod_timer(&req->rsk_timer, jiffies + timeo);
60 return;
61 }
62
63 inet_csk_reqsk_queue_drop_and_put(sk_listener, req);
64 }
65
66 /* Function
67 * Add request_SOCK to the connection queue and ehash table,
68 * and set the SYNACK timeout retransmission timer
69 * Parameter
70 * sk: Transmission control block
71 * req: Connection request block
72 * timeout: The initial timeout period
73 */
ninet_csk_reqsk_queue_hash_add(struct sock * sk,struct request_sock * req,unsigned long timeout)74 void ninet_csk_reqsk_queue_hash_add(struct sock *sk, struct request_sock *req,
75 unsigned long timeout)
76 {
77 req->num_retrans = 0;
78 req->num_timeout = 0;
79 req->sk = NULL;
80
81 timer_setup(&req->rsk_timer, ninet_reqsk_timer_handler,
82 TIMER_PINNED);
83 mod_timer(&req->rsk_timer, jiffies + timeout);
84
85 inet_ehash_insert(req_to_sk(req), NULL, NULL);
86
87 smp_wmb(); /* memory barrier */
88 refcount_set(&req->rsk_refcnt, TCP_NUM_2 + 1);
89
90 inet_csk_reqsk_queue_added(sk);
91 }
92
93