blob: a4f6f29af5d5934e60ef460fbf9f8aefe8472a63 [file] [log] [blame]
Willy Tarreaude70ca52020-08-28 11:49:31 +02001/*
2 * Configuration parsing for TCP (bind and server keywords)
3 *
4 * Copyright 2000-2020 Willy Tarreau <w@1wt.eu>
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version
9 * 2 of the License, or (at your option) any later version.
10 *
11 */
12
13#include <ctype.h>
14#include <errno.h>
Willy Tarreaude70ca52020-08-28 11:49:31 +020015#include <stdio.h>
16#include <stdlib.h>
17#include <string.h>
18#include <time.h>
19
20#include <sys/param.h>
21#include <sys/socket.h>
22#include <sys/types.h>
23
24#include <netinet/tcp.h>
25#include <netinet/in.h>
26
27#include <haproxy/api.h>
28#include <haproxy/arg.h>
29#include <haproxy/errors.h>
30#include <haproxy/list.h>
31#include <haproxy/listener.h>
32#include <haproxy/namespace.h>
33#include <haproxy/proxy-t.h>
34#include <haproxy/server.h>
35#include <haproxy/tools.h>
36
37
38#ifdef IPV6_V6ONLY
39/* parse the "v4v6" bind keyword */
40static int bind_parse_v4v6(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
41{
Willy Tarreau3fd3bdc2020-09-01 15:12:08 +020042 conf->settings.options |= RX_O_V4V6;
Willy Tarreaude70ca52020-08-28 11:49:31 +020043 return 0;
44}
45
46/* parse the "v6only" bind keyword */
47static int bind_parse_v6only(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
48{
Willy Tarreau3fd3bdc2020-09-01 15:12:08 +020049 conf->settings.options |= RX_O_V6ONLY;
Willy Tarreaude70ca52020-08-28 11:49:31 +020050 return 0;
51}
52#endif
53
54#ifdef CONFIG_HAP_TRANSPARENT
55/* parse the "transparent" bind keyword */
56static int bind_parse_transparent(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
57{
Willy Tarreau3fd3bdc2020-09-01 15:12:08 +020058 conf->settings.options |= RX_O_FOREIGN;
Willy Tarreaude70ca52020-08-28 11:49:31 +020059 return 0;
60}
61#endif
62
David Carlier1eb595b2021-02-06 12:11:11 +000063#if defined(TCP_DEFER_ACCEPT) || defined(SO_ACCEPTFILTER)
Willy Tarreaude70ca52020-08-28 11:49:31 +020064/* parse the "defer-accept" bind keyword */
65static int bind_parse_defer_accept(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
66{
Willy Tarreaud9b4d212023-01-12 19:42:48 +010067 conf->options |= BC_O_DEF_ACCEPT;
Willy Tarreaude70ca52020-08-28 11:49:31 +020068 return 0;
69}
70#endif
71
72#ifdef TCP_FASTOPEN
73/* parse the "tfo" bind keyword */
74static int bind_parse_tfo(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
75{
Willy Tarreauc492f1b2023-01-12 19:45:58 +010076 conf->options |= BC_O_TCP_FO;
Willy Tarreaude70ca52020-08-28 11:49:31 +020077 return 0;
78}
79#endif
80
81#ifdef TCP_MAXSEG
82/* parse the "mss" bind keyword */
83static int bind_parse_mss(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
84{
Willy Tarreaude70ca52020-08-28 11:49:31 +020085 int mss;
86
87 if (!*args[cur_arg + 1]) {
88 memprintf(err, "'%s' : missing MSS value", args[cur_arg]);
89 return ERR_ALERT | ERR_FATAL;
90 }
91
92 mss = atoi(args[cur_arg + 1]);
93 if (!mss || abs(mss) > 65535) {
94 memprintf(err, "'%s' : expects an MSS with and absolute value between 1 and 65535", args[cur_arg]);
95 return ERR_ALERT | ERR_FATAL;
96 }
97
Willy Tarreauee378162023-01-12 18:42:49 +010098 conf->maxseg = mss;
Willy Tarreaude70ca52020-08-28 11:49:31 +020099 return 0;
100}
101#endif
102
103#ifdef TCP_USER_TIMEOUT
104/* parse the "tcp-ut" bind keyword */
105static int bind_parse_tcp_ut(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
106{
107 const char *ptr = NULL;
Willy Tarreaude70ca52020-08-28 11:49:31 +0200108 unsigned int timeout;
109
110 if (!*args[cur_arg + 1]) {
111 memprintf(err, "'%s' : missing TCP User Timeout value", args[cur_arg]);
112 return ERR_ALERT | ERR_FATAL;
113 }
114
115 ptr = parse_time_err(args[cur_arg + 1], &timeout, TIME_UNIT_MS);
116 if (ptr == PARSE_TIME_OVER) {
117 memprintf(err, "timer overflow in argument '%s' to '%s' (maximum value is 2147483647 ms or ~24.8 days)",
118 args[cur_arg+1], args[cur_arg]);
119 return ERR_ALERT | ERR_FATAL;
120 }
121 else if (ptr == PARSE_TIME_UNDER) {
122 memprintf(err, "timer underflow in argument '%s' to '%s' (minimum non-null value is 1 ms)",
123 args[cur_arg+1], args[cur_arg]);
124 return ERR_ALERT | ERR_FATAL;
125 }
126 else if (ptr) {
127 memprintf(err, "'%s' : expects a positive delay in milliseconds", args[cur_arg]);
128 return ERR_ALERT | ERR_FATAL;
129 }
130
Willy Tarreauee378162023-01-12 18:42:49 +0100131 conf->tcp_ut = timeout;
Willy Tarreaude70ca52020-08-28 11:49:31 +0200132 return 0;
133}
134#endif
135
136#ifdef SO_BINDTODEVICE
137/* parse the "interface" bind keyword */
138static int bind_parse_interface(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
139{
Willy Tarreaude70ca52020-08-28 11:49:31 +0200140 if (!*args[cur_arg + 1]) {
141 memprintf(err, "'%s' : missing interface name", args[cur_arg]);
142 return ERR_ALERT | ERR_FATAL;
143 }
144
Aurelien DARRAGON4c6adb02023-06-01 09:57:15 +0200145 ha_free(&conf->settings.interface);
Willy Tarreau7e307212020-09-03 07:23:34 +0200146 conf->settings.interface = strdup(args[cur_arg + 1]);
Willy Tarreaude70ca52020-08-28 11:49:31 +0200147 return 0;
148}
149#endif
150
151#ifdef USE_NS
152/* parse the "namespace" bind keyword */
153static int bind_parse_namespace(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
154{
Willy Tarreaude70ca52020-08-28 11:49:31 +0200155 char *namespace = NULL;
156
157 if (!*args[cur_arg + 1]) {
158 memprintf(err, "'%s' : missing namespace id", args[cur_arg]);
159 return ERR_ALERT | ERR_FATAL;
160 }
161 namespace = args[cur_arg + 1];
162
Willy Tarreaube56c102020-09-03 07:27:34 +0200163 conf->settings.netns = netns_store_lookup(namespace, strlen(namespace));
Willy Tarreaude70ca52020-08-28 11:49:31 +0200164
Willy Tarreaube56c102020-09-03 07:27:34 +0200165 if (conf->settings.netns == NULL)
166 conf->settings.netns = netns_store_insert(namespace);
Willy Tarreaude70ca52020-08-28 11:49:31 +0200167
Willy Tarreaube56c102020-09-03 07:27:34 +0200168 if (conf->settings.netns == NULL) {
169 ha_alert("Cannot open namespace '%s'.\n", args[cur_arg + 1]);
170 return ERR_ALERT | ERR_FATAL;
Willy Tarreaude70ca52020-08-28 11:49:31 +0200171 }
172 return 0;
173}
174#endif
175
176#ifdef TCP_USER_TIMEOUT
177/* parse the "tcp-ut" server keyword */
178static int srv_parse_tcp_ut(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
179{
180 const char *ptr = NULL;
181 unsigned int timeout;
182
183 if (!*args[*cur_arg + 1]) {
184 memprintf(err, "'%s' : missing TCP User Timeout value", args[*cur_arg]);
185 return ERR_ALERT | ERR_FATAL;
186 }
187
188 ptr = parse_time_err(args[*cur_arg + 1], &timeout, TIME_UNIT_MS);
189 if (ptr == PARSE_TIME_OVER) {
190 memprintf(err, "timer overflow in argument '%s' to '%s' (maximum value is 2147483647 ms or ~24.8 days)",
191 args[*cur_arg+1], args[*cur_arg]);
192 return ERR_ALERT | ERR_FATAL;
193 }
194 else if (ptr == PARSE_TIME_UNDER) {
195 memprintf(err, "timer underflow in argument '%s' to '%s' (minimum non-null value is 1 ms)",
196 args[*cur_arg+1], args[*cur_arg]);
197 return ERR_ALERT | ERR_FATAL;
198 }
199 else if (ptr) {
200 memprintf(err, "'%s' : expects a positive delay in milliseconds", args[*cur_arg]);
201 return ERR_ALERT | ERR_FATAL;
202 }
203
204 if (newsrv->addr.ss_family == AF_INET || newsrv->addr.ss_family == AF_INET6)
205 newsrv->tcp_ut = timeout;
206
207 return 0;
208}
209#endif
210
211
212/************************************************************************/
213/* All supported bind keywords must be declared here. */
214/************************************************************************/
215
216/* Note: must not be declared <const> as its list will be overwritten.
217 * Please take care of keeping this list alphabetically sorted, doing so helps
218 * all code contributors.
219 * Optional keywords are also declared with a NULL ->parse() function so that
220 * the config parser can report an appropriate error when a known keyword was
221 * not enabled.
222 */
223static struct bind_kw_list bind_kws = { "TCP", { }, {
David Carlier1eb595b2021-02-06 12:11:11 +0000224#if defined(TCP_DEFER_ACCEPT) || defined(SO_ACCEPTFILTER)
Willy Tarreaude70ca52020-08-28 11:49:31 +0200225 { "defer-accept", bind_parse_defer_accept, 0 }, /* wait for some data for 1 second max before doing accept */
226#endif
227#ifdef SO_BINDTODEVICE
228 { "interface", bind_parse_interface, 1 }, /* specifically bind to this interface */
229#endif
230#ifdef TCP_MAXSEG
231 { "mss", bind_parse_mss, 1 }, /* set MSS of listening socket */
232#endif
233#ifdef TCP_USER_TIMEOUT
234 { "tcp-ut", bind_parse_tcp_ut, 1 }, /* set User Timeout on listening socket */
235#endif
236#ifdef TCP_FASTOPEN
237 { "tfo", bind_parse_tfo, 0 }, /* enable TCP_FASTOPEN of listening socket */
238#endif
239#ifdef CONFIG_HAP_TRANSPARENT
240 { "transparent", bind_parse_transparent, 0 }, /* transparently bind to the specified addresses */
241#endif
242#ifdef IPV6_V6ONLY
243 { "v4v6", bind_parse_v4v6, 0 }, /* force socket to bind to IPv4+IPv6 */
244 { "v6only", bind_parse_v6only, 0 }, /* force socket to bind to IPv6 only */
245#endif
246#ifdef USE_NS
247 { "namespace", bind_parse_namespace, 1 },
248#endif
249 /* the versions with the NULL parse function*/
250 { "defer-accept", NULL, 0 },
251 { "interface", NULL, 1 },
252 { "mss", NULL, 1 },
253 { "transparent", NULL, 0 },
254 { "v4v6", NULL, 0 },
255 { "v6only", NULL, 0 },
256 { NULL, NULL, 0 },
257}};
258
259INITCALL1(STG_REGISTER, bind_register_keywords, &bind_kws);
260
261static struct srv_kw_list srv_kws = { "TCP", { }, {
262#ifdef TCP_USER_TIMEOUT
Amaury Denoyelle76e10e72021-03-08 17:08:01 +0100263 { "tcp-ut", srv_parse_tcp_ut, 1, 1, 0 }, /* set TCP user timeout on server */
Willy Tarreaude70ca52020-08-28 11:49:31 +0200264#endif
265 { NULL, NULL, 0 },
266}};
267
268INITCALL1(STG_REGISTER, srv_register_keywords, &srv_kws);
269
Willy Tarreaude70ca52020-08-28 11:49:31 +0200270/*
271 * Local variables:
272 * c-indent-level: 8
273 * c-basic-offset: 8
274 * End:
275 */