182
* This function initiates a connection to the server assigned to this session
183
* (s->srv, s->srv_addr). It will assign a server if none is assigned yet. A
184
* source address may be pointed to by <from_addr>. Note that this is only used
185
* in case of transparent proxying. Normal source bind addresses are still
186
* determined locally (due to the possible need of a source port).
188
* It can return one of :
189
* - SN_ERR_NONE if everything's OK
190
* - SN_ERR_SRVTO if there are no more servers
191
* - SN_ERR_SRVCL if the connection was refused by the server
192
* - SN_ERR_PRXCOND if the connection has been limited by the proxy (maxconn)
193
* - SN_ERR_RESOURCE if a system resource is lacking (eg: fd limits, ports, ...)
194
* - SN_ERR_INTERNAL for any other purely internal errors
195
* Additionnally, in the case of SN_ERR_RESOURCE, an emergency log will be emitted.
197
int tcpv4_connect_server(struct stream_interface *si,
198
struct proxy *be, struct server *srv,
199
struct sockaddr *srv_addr, struct sockaddr *from_addr)
203
if ((fd = si->fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == -1) {
204
qfprintf(stderr, "Cannot get a server socket.\n");
207
send_log(be, LOG_EMERG,
208
"Proxy %s reached system FD limit at %d. Please check system tunables.\n",
210
else if (errno == EMFILE)
211
send_log(be, LOG_EMERG,
212
"Proxy %s reached process FD limit at %d. Please check 'ulimit-n' and restart.\n",
214
else if (errno == ENOBUFS || errno == ENOMEM)
215
send_log(be, LOG_EMERG,
216
"Proxy %s reached system memory limit at %d sockets. Please check system tunables.\n",
218
/* this is a resource error */
219
return SN_ERR_RESOURCE;
222
if (fd >= global.maxsock) {
223
/* do not log anything there, it's a normal condition when this option
224
* is used to serialize connections to a server !
226
Alert("socket(): not enough free sockets. Raise -n argument. Giving up.\n");
228
return SN_ERR_PRXCOND; /* it is a configuration limit */
231
if ((fcntl(fd, F_SETFL, O_NONBLOCK)==-1) ||
232
(setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, (char *) &one, sizeof(one)) == -1)) {
233
qfprintf(stderr,"Cannot set client socket to non blocking mode.\n");
235
return SN_ERR_INTERNAL;
238
if (be->options & PR_O_TCP_SRV_KA)
239
setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, (char *) &one, sizeof(one));
241
if (be->options & PR_O_TCP_NOLING)
242
setsockopt(fd, SOL_SOCKET, SO_LINGER, (struct linger *) &nolinger, sizeof(struct linger));
244
/* allow specific binding :
245
* - server-specific at first
246
* - proxy-specific next
248
if (srv != NULL && srv->state & SRV_BIND_SRC) {
251
switch (srv->state & SRV_TPROXY_MASK) {
252
case SRV_TPROXY_ADDR:
262
#ifdef SO_BINDTODEVICE
263
/* Note: this might fail if not CAP_NET_RAW */
265
setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE, srv->iface_name, srv->iface_len + 1);
268
if (srv->sport_range) {
269
int attempts = 10; /* should be more than enough to find a spare port */
270
struct sockaddr_in src;
273
src = srv->source_addr;
276
/* note: in case of retry, we may have to release a previously
277
* allocated port, hence this loop's construct.
279
port_range_release_port(fdinfo[fd].port_range, fdinfo[fd].local_port);
280
fdinfo[fd].port_range = NULL;
286
fdinfo[fd].local_port = port_range_alloc_port(srv->sport_range);
287
if (!fdinfo[fd].local_port)
290
fdinfo[fd].port_range = srv->sport_range;
291
src.sin_port = htons(fdinfo[fd].local_port);
293
ret = tcpv4_bind_socket(fd, flags, &src, (struct sockaddr_in *)from_addr);
294
} while (ret != 0); /* binding NOK */
297
ret = tcpv4_bind_socket(fd, flags, &srv->source_addr, (struct sockaddr_in *)from_addr);
301
port_range_release_port(fdinfo[fd].port_range, fdinfo[fd].local_port);
302
fdinfo[fd].port_range = NULL;
306
Alert("Cannot bind to source address before connect() for server %s/%s. Aborting.\n",
308
send_log(be, LOG_EMERG,
309
"Cannot bind to source address before connect() for server %s/%s.\n",
312
Alert("Cannot bind to tproxy source address before connect() for server %s/%s. Aborting.\n",
314
send_log(be, LOG_EMERG,
315
"Cannot bind to tproxy source address before connect() for server %s/%s.\n",
318
return SN_ERR_RESOURCE;
321
else if (be->options & PR_O_BIND_SRC) {
324
switch (be->options & PR_O_TPXY_MASK) {
335
#ifdef SO_BINDTODEVICE
336
/* Note: this might fail if not CAP_NET_RAW */
338
setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE, be->iface_name, be->iface_len + 1);
340
ret = tcpv4_bind_socket(fd, flags, &be->source_addr, (struct sockaddr_in *)from_addr);
344
Alert("Cannot bind to source address before connect() for proxy %s. Aborting.\n",
346
send_log(be, LOG_EMERG,
347
"Cannot bind to source address before connect() for proxy %s.\n",
350
Alert("Cannot bind to tproxy source address before connect() for proxy %s. Aborting.\n",
352
send_log(be, LOG_EMERG,
353
"Cannot bind to tproxy source address before connect() for proxy %s.\n",
356
return SN_ERR_RESOURCE;
360
#if defined(TCP_QUICKACK)
361
/* disabling tcp quick ack now allows the first request to leave the
362
* machine with the first ACK. We only do this if there are pending
363
* data in the buffer.
365
if ((be->options2 & PR_O2_SMARTCON) && si->ob->send_max)
366
setsockopt(fd, IPPROTO_TCP, TCP_QUICKACK, (char *) &zero, sizeof(zero));
369
if (global.tune.server_sndbuf)
370
setsockopt(fd, SOL_SOCKET, SO_SNDBUF, &global.tune.server_sndbuf, sizeof(global.tune.server_sndbuf));
372
if (global.tune.server_rcvbuf)
373
setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &global.tune.server_rcvbuf, sizeof(global.tune.server_rcvbuf));
375
if ((connect(fd, (struct sockaddr *)srv_addr, sizeof(struct sockaddr_in)) == -1) &&
376
(errno != EINPROGRESS) && (errno != EALREADY) && (errno != EISCONN)) {
378
if (errno == EAGAIN || errno == EADDRINUSE) {
380
if (errno == EAGAIN) /* no free ports left, try again later */
381
msg = "no free ports";
383
msg = "local address already in use";
385
qfprintf(stderr,"Cannot connect: %s.\n",msg);
386
port_range_release_port(fdinfo[fd].port_range, fdinfo[fd].local_port);
387
fdinfo[fd].port_range = NULL;
389
send_log(be, LOG_EMERG,
390
"Connect() failed for server %s/%s: %s.\n",
391
be->id, srv->id, msg);
392
return SN_ERR_RESOURCE;
393
} else if (errno == ETIMEDOUT) {
394
//qfprintf(stderr,"Connect(): ETIMEDOUT");
395
port_range_release_port(fdinfo[fd].port_range, fdinfo[fd].local_port);
396
fdinfo[fd].port_range = NULL;
400
// (errno == ECONNREFUSED || errno == ENETUNREACH || errno == EACCES || errno == EPERM)
401
//qfprintf(stderr,"Connect(): %d", errno);
402
port_range_release_port(fdinfo[fd].port_range, fdinfo[fd].local_port);
403
fdinfo[fd].port_range = NULL;
409
fdtab[fd].owner = si;
410
fdtab[fd].state = FD_STCONN; /* connection in progress */
411
fdtab[fd].flags = FD_FL_TCP | FD_FL_TCP_NODELAY;
412
fdtab[fd].cb[DIR_RD].f = &stream_sock_read;
413
fdtab[fd].cb[DIR_RD].b = si->ib;
414
fdtab[fd].cb[DIR_WR].f = &stream_sock_write;
415
fdtab[fd].cb[DIR_WR].b = si->ob;
417
fdinfo[fd].peeraddr = (struct sockaddr *)srv_addr;
418
fdinfo[fd].peerlen = sizeof(struct sockaddr_in);
421
EV_FD_SET(fd, DIR_WR); /* for connect status */
423
si->state = SI_ST_CON;
424
si->flags |= SI_FL_CAP_SPLTCP; /* TCP supports splicing */
425
si->exp = tick_add_ifset(now_ms, be->timeout.connect);
427
return SN_ERR_NONE; /* connection is OK */
174
431
/* This function tries to bind a TCPv4/v6 listener. It may return a warning or
175
432
* an error message in <err> if the message is at most <errlen> bytes long
176
433
* (including '\0'). The return value is composed from ERR_ABORT, ERR_WARN,
423
710
/* if we get there, it means we have no rule which matches, or
424
711
* we have an explicit accept, so we apply the default accept.
426
req->analysers &= ~AN_REQ_INSPECT;
713
req->analysers &= ~an_bit;
714
req->analyse_exp = TICK_ETERNITY;
718
/* Apply RDP cookie persistence to the current session. For this, the function
719
* tries to extract an RDP cookie from the request buffer, and look for the
720
* matching server in the list. If the server is found, it is assigned to the
721
* session. This always returns 1, and the analyser removes itself from the
722
* list. Nothing is performed if a server was already assigned.
724
int tcp_persist_rdp_cookie(struct session *s, struct buffer *req, int an_bit)
726
struct proxy *px = s->be;
728
struct acl_expr expr;
729
struct acl_test test;
730
struct server *srv = px->srv;
731
struct sockaddr_in addr;
734
DPRINTF(stderr,"[%u] %s: session=%p b=%p, exp(r,w)=%u,%u bf=%08x bl=%d analysers=%02x\n",
735
now_ms, __FUNCTION__,
743
if (s->flags & SN_ASSIGNED)
746
memset(&expr, 0, sizeof(expr));
747
memset(&test, 0, sizeof(test));
749
expr.arg.str = s->be->rdp_cookie_name;
750
expr.arg_len = s->be->rdp_cookie_len;
752
ret = acl_fetch_rdp_cookie(px, s, NULL, ACL_DIR_REQ, &expr, &test);
753
if (ret == 0 || (test.flags & ACL_TEST_F_MAY_CHANGE) || test.len == 0)
756
memset(&addr, 0, sizeof(addr));
757
addr.sin_family = AF_INET;
759
/* Considering an rdp cookie detected using acl, test.ptr ended with <cr><lf> and should return */
760
addr.sin_addr.s_addr = strtoul(test.ptr, &p, 10);
764
addr.sin_port = (unsigned short)strtoul(p, &p, 10);
769
if (memcmp(&addr, &(srv->addr), sizeof(addr)) == 0) {
770
if ((srv->state & SRV_RUNNING) || (px->options & PR_O_PERSIST)) {
771
/* we found the server and it is usable */
772
s->flags |= SN_DIRECT | SN_ASSIGNED;
781
req->analysers &= ~an_bit;
427
782
req->analyse_exp = TICK_ETERNITY;
505
860
pol = ACL_COND_NONE;
510
else if (!strcmp(args[3], "if"))
512
else if (!strcmp(args[3], "unless"))
513
pol = ACL_COND_UNLESS;
863
if (strcmp(args[3], "if") == 0 || strcmp(args[3], "unless") == 0) {
864
if ((cond = build_acl_cond(NULL, 0, curpx, (const char **)args+3)) == NULL) {
865
retlen = snprintf(err, errlen,
866
"error detected in %s '%s' while parsing '%s' condition",
867
proxy_type_str(curpx), curpx->id, args[3]);
515
872
retlen = snprintf(err, errlen,
516
873
"'%s %s %s' only accepts 'if' or 'unless', in %s '%s' (was '%s')",
517
874
args[0], args[1], args[2], proxy_type_str(curpx), curpx->id, args[3]);
521
/* Note: we consider "if TRUE" when there is no condition */
522
if (pol != ACL_COND_NONE &&
523
(cond = parse_acl_cond((const char **)args+4, &curpx->acl, pol)) == NULL) {
524
retlen = snprintf(err, errlen,
525
"error detected in %s '%s' while parsing '%s' condition",
526
proxy_type_str(curpx), curpx->id, args[3]);
530
// FIXME: how to set this ?
531
// cond->line = linenum;
532
if (cond && cond->requires & (ACL_USE_RTR_ANY | ACL_USE_L7_ANY)) {
878
if (cond && (cond->requires & ACL_USE_RTR_ANY)) {
534
880
const char *name;
536
acl = cond_find_require(cond, ACL_USE_RTR_ANY|ACL_USE_L7_ANY);
882
acl = cond_find_require(cond, ACL_USE_RTR_ANY);
537
883
name = acl ? acl->name : "(unknown)";
539
885
retlen = snprintf(err, errlen,
540
"acl '%s' involves some %s criteria which will be ignored.",
542
(acl->requires & ACL_USE_RTR_ANY) ? "response-only" : "layer 7");
886
"acl '%s' involves some response-only criteria which will be ignored.",
545
890
rule = (struct tcp_rule *)calloc(1, sizeof(*rule));
1027
acl_fetch_rdp_cookie(struct proxy *px, struct session *l4, void *l7, int dir,
1028
struct acl_expr *expr, struct acl_test *test)
1031
const unsigned char *data;
1033
if (!l4 || !l4->req)
1042
data = (const unsigned char *)l4->req->w + 11;
1048
if (strncasecmp((const char *)data, "Cookie:", 7) != 0)
1054
while (bleft > 0 && *data == ' ') {
1059
if (expr->arg_len) {
1061
if (bleft <= expr->arg_len)
1064
if ((data[expr->arg_len] != '=') ||
1065
strncasecmp(expr->arg.str, (const char *)data, expr->arg_len) != 0)
1068
data += expr->arg_len + 1;
1069
bleft -= expr->arg_len + 1;
1071
while (bleft > 0 && *data != '=') {
1072
if (*data == '\r' || *data == '\n')
1088
/* data points to cookie value */
1089
test->ptr = (char *)data;
1092
while (bleft > 0 && *data != '\r') {
1100
if (data[0] != '\r' || data[1] != '\n')
1103
test->len = (char *)data - test->ptr;
1104
test->flags = ACL_TEST_F_VOLATILE;
1108
test->flags = ACL_TEST_F_MAY_CHANGE;
1114
acl_fetch_rdp_cookie_cnt(struct proxy *px, struct session *l4, void *l7, int dir,
1115
struct acl_expr *expr, struct acl_test *test)
1119
ret = acl_fetch_rdp_cookie(px, l4, l7, dir, expr, test);
1124
if (test->flags & ACL_TEST_F_MAY_CHANGE)
1127
test->flags = ACL_TEST_F_VOLATILE;
682
1133
static struct cfg_kw_list cfg_kws = {{ },{
683
1134
{ CFG_LISTEN, "tcp-request", tcp_parse_tcp_req },