bda77f1c95244ad16cb7d5d11a94ac6473156eba
[oweals/openwrt.git] /
1 From 608aa9fcfca2ffeba40d78c7c4e0dcb50e0d5704 Mon Sep 17 00:00:00 2001
2 From: Simon Kelley <simon@thekelleys.org.uk>
3 Date: Sun, 10 Mar 2019 22:44:15 +0000
4 Subject: [PATCH 44/57] Support TCP fastopen on incoming and outgoing
5  connections.
6
7 Signed-off-by: Kevin Darbyshire-Bryant <ldir@darbyshire-bryant.me.uk>
8 ---
9  CHANGELOG     |  5 ++++-
10  src/dnsmasq.h |  1 +
11  src/forward.c | 50 +++++++++++++++++++++++++++++++++++++++++---------
12  src/network.c |  5 +++++
13  4 files changed, 51 insertions(+), 10 deletions(-)
14
15 --- a/CHANGELOG
16 +++ b/CHANGELOG
17 @@ -26,7 +26,10 @@ version 2.81
18         Thanks to Norman Rasmussen, Sven Mueller and Maciej Żenczykowski
19         for spotting and diagnosing the bug and providing patches.
20  
21 -
22 +       Support TCP-fastopen (RFC-7413) on both incoming and
23 +       outgoing TCP connections, if supported and enabled in the OS.
24 +       
25 +       
26  version 2.80
27         Add support for RFC 4039 DHCP rapid commit. Thanks to Ashram Method
28         for the initial patch and motivation.
29 --- a/src/dnsmasq.h
30 +++ b/src/dnsmasq.h
31 @@ -128,6 +128,7 @@ typedef unsigned long long u64;
32  #include <netinet/ip.h>
33  #include <netinet/ip6.h>
34  #include <netinet/ip_icmp.h>
35 +#include <netinet/tcp.h>
36  #include <sys/uio.h>
37  #include <syslog.h>
38  #include <dirent.h>
39 --- a/src/forward.c
40 +++ b/src/forward.c
41 @@ -1635,6 +1635,8 @@ static int tcp_key_recurse(time_t now, i
42         
43        while (1)
44         {
45 +         int data_sent = 0;
46 +         
47           if (!firstsendto)
48             firstsendto = server;
49           else
50 @@ -1667,8 +1669,22 @@ static int tcp_key_recurse(time_t now, i
51                 setsockopt(server->tcpfd, SOL_SOCKET, SO_MARK, &mark, sizeof(unsigned int));
52  #endif 
53               
54 -             if (!local_bind(server->tcpfd,  &server->source_addr, server->interface, 0, 1) ||
55 -                 connect(server->tcpfd, &server->addr.sa, sa_len(&server->addr)) == -1)
56 +             if (!local_bind(server->tcpfd,  &server->source_addr, server->interface, 0, 1))
57 +               {
58 +                 close(server->tcpfd);
59 +                 server->tcpfd = -1;
60 +                 continue; /* No good, next server */
61 +               }
62 +             
63 +#ifdef MSG_FASTOPEN
64 +             while(retry_send(sendto(server->tcpfd, packet, m + sizeof(u16),
65 +                                     MSG_FASTOPEN, &server->addr.sa, sa_len(&server->addr))));
66 +             
67 +             if (errno == 0)
68 +               data_sent = 1;
69 +#endif
70 +             
71 +             if (!data_sent && connect(server->tcpfd, &server->addr.sa, sa_len(&server->addr)) == -1)
72                 {
73                   close(server->tcpfd);
74                   server->tcpfd = -1;
75 @@ -1678,7 +1694,7 @@ static int tcp_key_recurse(time_t now, i
76               server->flags &= ~SERV_GOT_TCP;
77             }
78           
79 -         if (!read_write(server->tcpfd, packet, m + sizeof(u16), 0) ||
80 +         if ((!data_sent && !read_write(server->tcpfd, packet, m + sizeof(u16), 0)) ||
81               !read_write(server->tcpfd, &c1, 1, 1) ||
82               !read_write(server->tcpfd, &c2, 1, 1) ||
83               !read_write(server->tcpfd, payload, (c1 << 8) | c2, 1))
84 @@ -1951,6 +1967,8 @@ unsigned char *tcp_request(int confd, ti
85                      which can go to the same server, do so. */
86                   while (1) 
87                     {
88 +                     int data_sent = 0;
89 +
90                       if (!firstsendto)
91                         firstsendto = last_server;
92                       else
93 @@ -1969,6 +1987,8 @@ unsigned char *tcp_request(int confd, ti
94                         continue;
95  
96                     retry:
97 +                     *length = htons(size);
98 +
99                       if (last_server->tcpfd == -1)
100                         {
101                           if ((last_server->tcpfd = socket(last_server->addr.sa.sa_family, SOCK_STREAM, 0)) == -1)
102 @@ -1978,10 +1998,24 @@ unsigned char *tcp_request(int confd, ti
103                           /* Copy connection mark of incoming query to outgoing connection. */
104                           if (have_mark)
105                             setsockopt(last_server->tcpfd, SOL_SOCKET, SO_MARK, &mark, sizeof(unsigned int));
106 -#endif 
107 +#endif                   
108                       
109 -                         if ((!local_bind(last_server->tcpfd,  &last_server->source_addr, last_server->interface, 0, 1) ||
110 -                              connect(last_server->tcpfd, &last_server->addr.sa, sa_len(&last_server->addr)) == -1))
111 +                         if ((!local_bind(last_server->tcpfd,  &last_server->source_addr, last_server->interface, 0, 1)))
112 +                           {
113 +                             close(last_server->tcpfd);
114 +                             last_server->tcpfd = -1;
115 +                             continue;
116 +                           }
117 +                         
118 +#ifdef MSG_FASTOPEN
119 +                           while(retry_send(sendto(last_server->tcpfd, packet, size + sizeof(u16),
120 +                                                   MSG_FASTOPEN, &last_server->addr.sa, sa_len(&last_server->addr))));
121 +                           
122 +                           if (errno == 0)
123 +                             data_sent = 1;
124 +#endif
125 +                           
126 +                           if (!data_sent && connect(last_server->tcpfd, &last_server->addr.sa, sa_len(&last_server->addr)) == -1)
127                             {
128                               close(last_server->tcpfd);
129                               last_server->tcpfd = -1;
130 @@ -1991,13 +2025,11 @@ unsigned char *tcp_request(int confd, ti
131                           last_server->flags &= ~SERV_GOT_TCP;
132                         }
133                       
134 -                     *length = htons(size);
135 -
136                       /* get query name again for logging - may have been overwritten */
137                       if (!(gotname = extract_request(header, (unsigned int)size, daemon->namebuff, &qtype)))
138                         strcpy(daemon->namebuff, "query");
139                       
140 -                     if (!read_write(last_server->tcpfd, packet, size + sizeof(u16), 0) ||
141 +                     if ((!data_sent && !read_write(last_server->tcpfd, packet, size + sizeof(u16), 0)) ||
142                           !read_write(last_server->tcpfd, &c1, 1, 1) ||
143                           !read_write(last_server->tcpfd, &c2, 1, 1) ||
144                           !read_write(last_server->tcpfd, payload, (c1 << 8) | c2, 1))
145 --- a/src/network.c
146 +++ b/src/network.c
147 @@ -726,6 +726,11 @@ static int make_sock(union mysockaddr *a
148    
149    if (type == SOCK_STREAM)
150      {
151 +#ifdef TCP_FASTOPEN
152 +      int qlen = 5;                           
153 +      setsockopt(fd, SOL_TCP, TCP_FASTOPEN, &qlen, sizeof(qlen));
154 +#endif
155 +      
156        if (listen(fd, TCP_BACKLOG) == -1)
157         goto err;
158      }