]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
[MEDIUM] store the original destination address in the session
authorWilly Tarreau <w@1wt.eu>
Tue, 8 May 2007 17:46:30 +0000 (19:46 +0200)
committerWilly Tarreau <w@1wt.eu>
Tue, 8 May 2007 21:24:20 +0000 (23:24 +0200)
There are multiple places where the client's destination address is
required. Let's store it in the session when needed, and add a flag
to inform that it has been retrieved.

include/proto/client.h
include/types/session.h
src/backend.c
src/client.c

index 3065b616d2995956528f6305b81a009b805ed1bf..6540d096fba456d7dd76380ce793b83337d15926 100644 (file)
@@ -2,7 +2,7 @@
   include/proto/client.h
   This file contains client-side definitions.
 
-  Copyright (C) 2000-2006 Willy Tarreau - w@1wt.eu
+  Copyright (C) 2000-2007 Willy Tarreau - w@1wt.eu
   
   This library is free software; you can redistribute it and/or
   modify it under the terms of the GNU Lesser General Public
@@ -24,7 +24,9 @@
 
 #include <common/config.h>
 #include <types/client.h>
+#include <types/session.h>
 
+void get_frt_addr(struct session *s);
 int event_accept(int fd);
 
 
index 1011c9a02325132e28d1c61b7411c1632f5b9122..7ef138f105cc5920526b2549b7b766510b83b567 100644 (file)
@@ -47,7 +47,7 @@
 #define SN_CONN_CLOSED 0x00000010      /* "Connection: close" was present or added */
 #define SN_MONITOR     0x00000020      /* this session comes from a monitoring system */
 #define SN_SELF_GEN    0x00000040      /* the proxy generates data for the client (eg: stats) */
-/* unused:              0x00000080 */
+#define SN_FRT_ADDR_SET        0x00000080      /* set if the frontend address has been filled */
 
 /* session termination conditions, bits values 0x100 to 0x700 (0-7 shift 8) */
 #define SN_ERR_NONE     0x00000000
@@ -92,6 +92,7 @@ struct session {
        struct buffer *req;                     /* request buffer */
        struct buffer *rep;                     /* response buffer */
        struct sockaddr_storage cli_addr;       /* the client address */
+       struct sockaddr_storage frt_addr;       /* the frontend address reached by the client if SN_FRT_ADDR_SET is set */
        struct sockaddr_in srv_addr;            /* the address to connect to */
        struct server *srv;                     /* the server being used */
        struct pendconn *pend_pos;              /* if not NULL, points to the position in the pending queue */
index bb5705008bc3caeb924f43e948fad6b7081385f1..69e79d408d7745bd441c3407752c615f5634529c 100644 (file)
@@ -29,6 +29,7 @@
 #include <types/session.h>
 
 #include <proto/backend.h>
+#include <proto/client.h>
 #include <proto/fd.h>
 #include <proto/httperr.h>
 #include <proto/log.h>
@@ -235,13 +236,15 @@ int assign_server_address(struct session *s)
                /* if this server remaps proxied ports, we'll use
                 * the port the client connected to with an offset. */
                if (s->srv->state & SRV_MAPPORTS) {
-                       struct sockaddr_in sockname;
-                       socklen_t namelen = sizeof(sockname);
-
-                       if (!(s->fe->options & PR_O_TRANSP) ||
-                           get_original_dst(s->cli_fd, (struct sockaddr_in *)&sockname, &namelen) == -1)
-                               getsockname(s->cli_fd, (struct sockaddr *)&sockname, &namelen);
-                       s->srv_addr.sin_port = htons(ntohs(s->srv_addr.sin_port) + ntohs(sockname.sin_port));
+                       if (!(s->fe->options & PR_O_TRANSP) && !(s->flags & SN_FRT_ADDR_SET))
+                               get_frt_addr(s);
+                       if (s->frt_addr.ss_family == AF_INET) {
+                               s->srv_addr.sin_port = htons(ntohs(s->srv_addr.sin_port) +
+                                                            ntohs(((struct sockaddr_in *)&s->frt_addr)->sin_port));
+                       } else {
+                               s->srv_addr.sin_port = htons(ntohs(s->srv_addr.sin_port) +
+                                                            ntohs(((struct sockaddr_in6 *)&s->frt_addr)->sin6_port));
+                       }
                }
        }
        else if (*(int *)&s->be->dispatch_addr.sin_addr) {
index 650db1fd7ff19c5784267fbbf0e256f461a4c8ae..2754b91f7220ce32d16eba2c1ae120f6158fb0ab 100644 (file)
 #include <proto/task.h>
 
 
+/* Retrieves the original destination address used by the client, and sets the
+ * SN_FRT_ADDR_SET flag.
+ */
+void get_frt_addr(struct session *s)
+{
+       socklen_t namelen = sizeof(s->frt_addr);
+
+       if (get_original_dst(s->cli_fd, (struct sockaddr_in *)&s->frt_addr, &namelen) == -1)
+               getsockname(s->cli_fd, (struct sockaddr *)&s->frt_addr, &namelen);
+       s->flags |= SN_FRT_ADDR_SET;
+}
 
 /*
  * FIXME: This should move to the STREAM_SOCK code then split into TCP and HTTP.
@@ -263,14 +274,6 @@ int event_accept(int fd) {
 
                if ((p->mode == PR_MODE_TCP || p->mode == PR_MODE_HTTP)
                    && (p->logfac1 >= 0 || p->logfac2 >= 0)) {
-                       struct sockaddr_storage sockname;
-                       socklen_t namelen = sizeof(sockname);
-
-                       if (addr.ss_family != AF_INET ||
-                           !(s->fe->options & PR_O_TRANSP) ||
-                           get_original_dst(cfd, (struct sockaddr_in *)&sockname, &namelen) == -1)
-                               getsockname(cfd, (struct sockaddr *)&sockname, &namelen);
-
                        if (p->to_log) {
                                /* we have the client ip */
                                if (s->logs.logwait & LW_CLIP)
@@ -279,38 +282,43 @@ int event_accept(int fd) {
                        }
                        else if (s->cli_addr.ss_family == AF_INET) {
                                char pn[INET_ADDRSTRLEN], sn[INET_ADDRSTRLEN];
-                               if (inet_ntop(AF_INET, (const void *)&((struct sockaddr_in *)&sockname)->sin_addr,
+
+                               if (!(s->flags & SN_FRT_ADDR_SET))
+                                       get_frt_addr(s);
+
+                               if (inet_ntop(AF_INET, (const void *)&((struct sockaddr_in *)&s->frt_addr)->sin_addr,
                                              sn, sizeof(sn)) &&
                                    inet_ntop(AF_INET, (const void *)&((struct sockaddr_in *)&s->cli_addr)->sin_addr,
                                              pn, sizeof(pn))) {
                                        send_log(p, LOG_INFO, "Connect from %s:%d to %s:%d (%s/%s)\n",
                                                 pn, ntohs(((struct sockaddr_in *)&s->cli_addr)->sin_port),
-                                                sn, ntohs(((struct sockaddr_in *)&sockname)->sin_port),
+                                                sn, ntohs(((struct sockaddr_in *)&s->frt_addr)->sin_port),
                                                 p->id, (p->mode == PR_MODE_HTTP) ? "HTTP" : "TCP");
                                }
                        }
                        else {
                                char pn[INET6_ADDRSTRLEN], sn[INET6_ADDRSTRLEN];
-                               if (inet_ntop(AF_INET6, (const void *)&((struct sockaddr_in6 *)&sockname)->sin6_addr,
+
+                               if (!(s->flags & SN_FRT_ADDR_SET))
+                                       get_frt_addr(s);
+
+                               if (inet_ntop(AF_INET6, (const void *)&((struct sockaddr_in6 *)&s->frt_addr)->sin6_addr,
                                              sn, sizeof(sn)) &&
                                    inet_ntop(AF_INET6, (const void *)&((struct sockaddr_in6 *)&s->cli_addr)->sin6_addr,
                                              pn, sizeof(pn))) {
                                        send_log(p, LOG_INFO, "Connect from %s:%d to %s:%d (%s/%s)\n",
                                                 pn, ntohs(((struct sockaddr_in6 *)&s->cli_addr)->sin6_port),
-                                                sn, ntohs(((struct sockaddr_in6 *)&sockname)->sin6_port),
+                                                sn, ntohs(((struct sockaddr_in6 *)&s->frt_addr)->sin6_port),
                                                 p->id, (p->mode == PR_MODE_HTTP) ? "HTTP" : "TCP");
                                }
                        }
                }
 
                if ((global.mode & MODE_DEBUG) && (!(global.mode & MODE_QUIET) || (global.mode & MODE_VERBOSE))) {
-                       struct sockaddr_in sockname;
-                       socklen_t namelen = sizeof(sockname);
                        int len;
-                       if (addr.ss_family != AF_INET ||
-                           !(s->fe->options & PR_O_TRANSP) ||
-                           get_original_dst(cfd, (struct sockaddr_in *)&sockname, &namelen) == -1)
-                               getsockname(cfd, (struct sockaddr *)&sockname, &namelen);
+
+                       if (!(s->flags & SN_FRT_ADDR_SET))
+                               get_frt_addr(s);
 
                        if (s->cli_addr.ss_family == AF_INET) {
                                char pn[INET_ADDRSTRLEN];