]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
BUG/MEDIUM: stream_interface: restore get_src/get_dst
authorWilly Tarreau <w@1wt.eu>
Fri, 11 May 2012 14:16:40 +0000 (16:16 +0200)
committerWilly Tarreau <w@1wt.eu>
Fri, 11 May 2012 14:48:10 +0000 (16:48 +0200)
Commit e164e7a removed get_src/get_dst setting in the stream interfaces but
forgot to set it in proto_tcp. Get the feature back because we need it for
logging, transparent mode, ACLs etc... We now rely on the stream interface
direction to know what syscall to use.

One benefit of doing it this way is that we don't use getsockopt() anymore
on outgoing stream interfaces nor on UNIX sockets.

12 files changed:
include/proto/proto_tcp.h
include/proto/proto_uxst.h
include/proto/sock_raw.h
include/proto/stream_interface.h
include/types/protocols.h
src/backend.c
src/dumpstats.c
src/frontend.c
src/log.c
src/proto_http.c
src/proto_tcp.c
src/proto_uxst.c

index 947699bb42d1691e58a59d7fdf0dd801a5d5d7f9..374c7fdb20b83aa93605c54ac71b3c6e66e6deb4 100644 (file)
@@ -31,6 +31,8 @@ int tcp_bind_socket(int fd, int flags, struct sockaddr_storage *local, struct so
 void tcpv4_add_listener(struct listener *listener);
 void tcpv6_add_listener(struct listener *listener);
 int tcp_connect_server(struct stream_interface *si);
+int tcp_get_src(int fd, struct sockaddr *sa, socklen_t salen, int dir);
+int tcp_get_dst(int fd, struct sockaddr *sa, socklen_t salen, int dir);
 int tcp_inspect_request(struct session *s, struct buffer *req, int an_bit);
 int tcp_inspect_response(struct session *s, struct buffer *rep, int an_bit);
 int tcp_exec_req_rules(struct session *s);
index b412f0ad49fb09e8b3fe3f2258c110f9694f580c..9422ea7c2bcfc771946e961072ddb7bd7f9d42fc 100644 (file)
@@ -27,6 +27,8 @@
 #include <types/task.h>
 
 void uxst_add_listener(struct listener *listener);
+int uxst_get_src(int fd, struct sockaddr *sa, socklen_t salen, int dir);
+int uxst_get_dst(int fd, struct sockaddr *sa, socklen_t salen, int dir);
 
 #endif /* _PROTO_PROTO_UXST_H */
 
index 7a618872f5a857a73259fc7b08e5df31b787c8c9..a17db4dca7780c5ed307247422c9bbcd69202a61 100644 (file)
@@ -56,51 +56,6 @@ static inline int get_original_dst(int fd, struct sockaddr_in *sa, socklen_t *sa
 #endif
 }
 
-
-/*
- * Retrieves the original destination address for the stream interface. On the
- * client side, if the original destination address was translated, the original
- * address is retrieved.
- */
-static inline void stream_sock_get_to_addr(struct stream_interface *si)
-{
-       socklen_t namelen;
-
-       if (si->flags & SI_FL_TO_SET)
-               return;
-
-       namelen = sizeof(si->addr.to);
-
-#if defined(TPROXY) && defined(SO_ORIGINAL_DST)
-       if (getsockopt(si->fd, SOL_IP, SO_ORIGINAL_DST, (struct sockaddr *)&si->addr.to, &namelen) != -1) {
-               si->flags |= SI_FL_TO_SET;
-               return;
-       }
-#endif
-       if (si->proto->get_dst &&
-           si->proto->get_dst(si->fd, (struct sockaddr *)&si->addr.to, &namelen) != -1)
-               si->flags |= SI_FL_TO_SET;
-       return;
-}
-
-/*
- * Retrieves the source address for the stream interface.
- */
-static inline void stream_sock_get_from_addr(struct stream_interface *si)
-{
-       socklen_t namelen;
-
-       if (si->flags & SI_FL_FROM_SET)
-               return;
-
-       namelen = sizeof(si->addr.to);
-       if (si->proto->get_src &&
-           si->proto->get_src(si->fd, (struct sockaddr *)&si->addr.from, &namelen) != -1)
-               si->flags |= SI_FL_FROM_SET;
-       return;
-}
-
-
 #endif /* _PROTO_STREAM_SOCK_H */
 
 /*
index cbe8282573406c539b2a85e92f809bc11744d8c4..5446786bebe370d8ae23b5e7a0e7ba760ee01363 100644 (file)
@@ -109,6 +109,40 @@ static inline void stream_interface_prepare(struct stream_interface *si, const s
        memcpy(&si->sock, ops, sizeof(si->sock));
 }
 
+
+/* Retrieves the source address for the stream interface. */
+static inline void si_get_from_addr(struct stream_interface *si)
+{
+       if (si->flags & SI_FL_FROM_SET)
+               return;
+
+       if (!si->proto || !si->proto->get_src)
+               return;
+
+       if (si->proto->get_src(si->fd, (struct sockaddr *)&si->addr.from,
+                              sizeof(si->addr.from),
+                              si->target.type != TARG_TYPE_CLIENT) == -1)
+               return;
+       si->flags |= SI_FL_FROM_SET;
+}
+
+/* Retrieves the original destination address for the stream interface. */
+static inline void si_get_to_addr(struct stream_interface *si)
+{
+       if (si->flags & SI_FL_TO_SET)
+               return;
+
+       if (!si->proto || !si->proto->get_dst)
+               return;
+
+       if (si->proto->get_dst(si->fd, (struct sockaddr *)&si->addr.to,
+                              sizeof(si->addr.to),
+                              si->target.type != TARG_TYPE_CLIENT) == -1)
+               return;
+       si->flags |= SI_FL_TO_SET;
+}
+
+
 #endif /* _PROTO_STREAM_INTERFACE_H */
 
 /*
index 4112b08c88de31443fdfd9075312de8b23ca339c..bda4922684adae387e2165327ce32596155a2287 100644 (file)
@@ -157,8 +157,8 @@ struct protocol {
        int (*enable_all)(struct protocol *proto);      /* enable all bound listeners */
        int (*disable_all)(struct protocol *proto);     /* disable all bound listeners */
        int (*connect)(struct stream_interface *);      /* connect function if any */
-       int (*get_src)(int, struct sockaddr *, socklen_t *); /* syscall used to retrieve src addr */
-       int (*get_dst)(int, struct sockaddr *, socklen_t *); /* syscall used to retrieve dst addr */
+       int (*get_src)(int fd, struct sockaddr *, socklen_t, int dir); /* syscall used to retrieve src addr */
+       int (*get_dst)(int fd, struct sockaddr *, socklen_t, int dir); /* syscall used to retrieve dst addr */
 
        struct list listeners;                          /* list of listeners using this protocol */
        int nb_listeners;                               /* number of listeners */
index 95b395324d3283aebd9f433dbe825289b166a56d..928d63e2530762f1e553c50776e8817316e08337 100644 (file)
@@ -693,7 +693,7 @@ int assign_server_address(struct session *s)
                         * locally on multiple addresses at once.
                         */
                        if (!(s->be->options & PR_O_TRANSP))
-                               stream_sock_get_to_addr(s->req->prod);
+                               si_get_to_addr(s->req->prod);
 
                        if (s->req->prod->addr.to.ss_family == AF_INET) {
                                ((struct sockaddr_in *)&s->req->cons->addr.to)->sin_addr = ((struct sockaddr_in *)&s->req->prod->addr.to)->sin_addr;
@@ -708,7 +708,7 @@ int assign_server_address(struct session *s)
                        int base_port;
 
                        if (!(s->be->options & PR_O_TRANSP))
-                               stream_sock_get_to_addr(s->req->prod);
+                               si_get_to_addr(s->req->prod);
 
                        /* First, retrieve the port from the incoming connection */
                        base_port = get_host_port(&s->req->prod->addr.to);
@@ -724,7 +724,7 @@ int assign_server_address(struct session *s)
        }
        else if (s->be->options & PR_O_TRANSP) {
                /* in transparent mode, use the original dest addr if no dispatch specified */
-               stream_sock_get_to_addr(s->req->prod);
+               si_get_to_addr(s->req->prod);
 
                if (s->req->prod->addr.to.ss_family == AF_INET || s->req->prod->addr.to.ss_family == AF_INET6) {
                        memcpy(&s->req->cons->addr.to, &s->req->prod->addr.to, MIN(sizeof(s->req->cons->addr.to), sizeof(s->req->prod->addr.to)));
@@ -983,7 +983,7 @@ int connect_server(struct session *s)
        s->req->cons->send_proxy_ofs = 0;
        if (s->target.type == TARG_TYPE_SERVER && (s->target.ptr.s->state & SRV_SEND_PROXY)) {
                s->req->cons->send_proxy_ofs = 1; /* must compute size */
-               stream_sock_get_to_addr(s->req->prod);
+               si_get_to_addr(s->req->prod);
        }
 
        /* set the correct protocol on the output stream interface */
index 832534e846cf57919e235b22b71b21178ca5463f..43cc275ae8596dd88f7374aa7d1539a2a016c386 100644 (file)
@@ -3256,7 +3256,7 @@ static int stats_dump_full_sess_to_buffer(struct stream_interface *si)
                             sess->listener ? sess->listener->name ? sess->listener->name : "?" : "?",
                             sess->listener ? sess->listener->luid : 0);
 
-               stream_sock_get_to_addr(&sess->si[0]);
+               si_get_to_addr(&sess->si[0]);
                switch (addr_to_str(&sess->si[0].addr.to, pn, sizeof(pn))) {
                case AF_INET:
                case AF_INET6:
@@ -3280,7 +3280,7 @@ static int stats_dump_full_sess_to_buffer(struct stream_interface *si)
                else
                        chunk_printf(&msg, "  backend=<NONE> (id=-1 mode=-)");
 
-               stream_sock_get_from_addr(&sess->si[1]);
+               si_get_from_addr(&sess->si[1]);
                switch (addr_to_str(&sess->si[1].addr.from, pn, sizeof(pn))) {
                case AF_INET:
                case AF_INET6:
@@ -3304,7 +3304,7 @@ static int stats_dump_full_sess_to_buffer(struct stream_interface *si)
                else
                        chunk_printf(&msg, "  server=<NONE> (id=-1)");
 
-               stream_sock_get_to_addr(&sess->si[1]);
+               si_get_to_addr(&sess->si[1]);
                switch (addr_to_str(&sess->si[1].addr.to, pn, sizeof(pn))) {
                case AF_INET:
                case AF_INET6:
index a72f6b8bbf3e6b1748cad274f547c533e730f3f9..d2a9e70bf58cd2b37c2d3dd4632b31e537a7b297 100644 (file)
@@ -139,8 +139,8 @@ int frontend_accept(struct session *s)
                else {
                        char pn[INET6_ADDRSTRLEN], sn[INET6_ADDRSTRLEN];
 
-                       stream_sock_get_from_addr(s->req->prod);
-                       stream_sock_get_to_addr(s->req->prod);
+                       si_get_from_addr(s->req->prod);
+                       si_get_to_addr(s->req->prod);
 
                        switch (addr_to_str(&s->req->prod->addr.from, pn, sizeof(pn))) {
                        case AF_INET:
@@ -165,7 +165,7 @@ int frontend_accept(struct session *s)
                char pn[INET6_ADDRSTRLEN];
                int len = 0;
 
-               stream_sock_get_from_addr(s->req->prod);
+               si_get_from_addr(s->req->prod);
 
                switch (addr_to_str(&s->req->prod->addr.from, pn, sizeof(pn))) {
                case AF_INET:
index 9fa1b82858739dab5961242d2e6fb770d95dc004..74af1c6804853428adbb1e08b431110c833be181 100644 (file)
--- a/src/log.c
+++ b/src/log.c
@@ -859,7 +859,7 @@ int build_logline(struct session *s, char *dst, size_t maxsize, struct list *lis
                                break;
 
                        case LOG_FMT_FRONTENDIP: // %Fi
-                               stream_sock_get_to_addr(s->req->prod);
+                               si_get_to_addr(s->req->prod);
                                ret = lf_ip(tmplog, (struct sockaddr *)&s->req->prod->addr.to,
                                            dst + maxsize - tmplog, tmp);
                                if (ret == NULL)
@@ -869,7 +869,7 @@ int build_logline(struct session *s, char *dst, size_t maxsize, struct list *lis
                                break;
 
                        case  LOG_FMT_FRONTENDPORT: // %Fp
-                               stream_sock_get_to_addr(s->req->prod);
+                               si_get_to_addr(s->req->prod);
                                if (s->req->prod->addr.to.ss_family == AF_UNIX) {
                                        ret = ltoa_o(s->listener->luid,
                                                     tmplog, dst + maxsize - tmplog);
index 4a3de8fdf2525b392f6b2713b30ad09dea48e29d..6cc9c9fbe9c902999b2455b14eef813d5b059052 100644 (file)
@@ -3335,7 +3335,7 @@ int http_process_request(struct session *s, struct buffer *req, int an_bit)
                        /* Add an X-Original-To header unless the destination IP is
                         * in the 'except' network range.
                         */
-                       stream_sock_get_to_addr(s->req->prod);
+                       si_get_to_addr(s->req->prod);
 
                        if (s->req->prod->addr.to.ss_family == AF_INET &&
                            ((!s->fe->except_mask_to.s_addr ||
index 29aa32355456f18621aab4ef8acb29a18af2ecf6..5d5ede6820db545ee82d339a89718fa65889b81e 100644 (file)
@@ -50,6 +50,7 @@
 #include <proto/session.h>
 #include <proto/sock_raw.h>
 #include <proto/stick_table.h>
+#include <proto/stream_interface.h>
 #include <proto/task.h>
 #include <proto/buffers.h>
 
@@ -75,6 +76,8 @@ static struct protocol proto_tcpv4 = {
        .bind_all = tcp_bind_listeners,
        .unbind_all = unbind_all_listeners,
        .enable_all = enable_all_listeners,
+       .get_src = tcp_get_src,
+       .get_dst = tcp_get_dst,
        .listeners = LIST_HEAD_INIT(proto_tcpv4.listeners),
        .nb_listeners = 0,
 };
@@ -94,6 +97,8 @@ static struct protocol proto_tcpv6 = {
        .bind_all = tcp_bind_listeners,
        .unbind_all = unbind_all_listeners,
        .enable_all = enable_all_listeners,
+       .get_src = tcp_get_src,
+       .get_dst = tcp_get_dst,
        .listeners = LIST_HEAD_INIT(proto_tcpv6.listeners),
        .nb_listeners = 0,
 };
@@ -439,7 +444,7 @@ int tcp_connect_server(struct stream_interface *si)
 
        /* needs src ip/port for logging */
        if (si->flags & SI_FL_SRC_ADDR)
-               stream_sock_get_from_addr(si);
+               si_get_from_addr(si);
 
        fdtab[fd].owner = si;
        fdtab[fd].state = FD_STCONN; /* connection in progress */
@@ -463,6 +468,41 @@ int tcp_connect_server(struct stream_interface *si)
 }
 
 
+/*
+ * Retrieves the source address for the socket <fd>, with <dir> indicating
+ * if we're a listener (=0) or an initiator (!=0). It returns 0 in case of
+ * success, -1 in case of error. The socket's source address is stored in
+ * <sa> for <salen> bytes.
+ */
+int tcp_get_src(int fd, struct sockaddr *sa, socklen_t salen, int dir)
+{
+       if (dir)
+               return getsockname(fd, sa, &salen);
+       else
+               return getpeername(fd, sa, &salen);
+}
+
+
+/*
+ * Retrieves the original destination address for the socket <fd>, with <dir>
+ * indicating if we're a listener (=0) or an initiator (!=0). In the case of a
+ * listener, if the original destination address was translated, the original
+ * address is retrieved. It returns 0 in case of success, -1 in case of error.
+ * The socket's source address is stored in <sa> for <salen> bytes.
+ */
+int tcp_get_dst(int fd, struct sockaddr *sa, socklen_t salen, int dir)
+{
+       if (dir)
+               return getpeername(fd, sa, &salen);
+#if defined(TPROXY) && defined(SO_ORIGINAL_DST)
+       else if (getsockopt(fd, SOL_IP, SO_ORIGINAL_DST, sa, &salen) == 0)
+               return 0;
+#endif
+       else
+               return getsockname(fd, sa, &salen);
+}
+
+
 /* This function tries to bind a TCPv4/v6 listener. It may return a warning or
  * an error message in <err> if the message is at most <errlen> bytes long
  * (including '\0'). The return value is composed from ERR_ABORT, ERR_WARN,
@@ -1417,7 +1457,7 @@ static int
 smp_fetch_dst(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
               const struct arg *args, struct sample *smp)
 {
-       stream_sock_get_to_addr(&l4->si[0]);
+       si_get_to_addr(&l4->si[0]);
 
        switch (l4->si[0].addr.to.ss_family) {
        case AF_INET:
@@ -1441,7 +1481,7 @@ static int
 smp_fetch_dport(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
                 const struct arg *args, struct sample *smp)
 {
-       stream_sock_get_to_addr(&l4->si[0]);
+       si_get_to_addr(&l4->si[0]);
 
        smp->type = SMP_T_UINT;
        if (!(smp->data.uint = get_host_port(&l4->si[0].addr.to)))
index ace1e448f53ee6154c361d8177d0d704f1bd8ec5..08259920177287fb20ae2101798afca7f8c1b6b0 100644 (file)
@@ -61,6 +61,8 @@ static struct protocol proto_unix = {
        .unbind_all = uxst_unbind_listeners,
        .enable_all = enable_all_listeners,
        .disable_all = disable_all_listeners,
+       .get_src = uxst_get_src,
+       .get_dst = uxst_get_dst,
        .listeners = LIST_HEAD_INIT(proto_unix.listeners),
        .nb_listeners = 0,
 };
@@ -69,6 +71,35 @@ static struct protocol proto_unix = {
  * 1) low-level socket functions
  ********************************/
 
+/*
+ * Retrieves the source address for the socket <fd>, with <dir> indicating
+ * if we're a listener (=0) or an initiator (!=0). It returns 0 in case of
+ * success, -1 in case of error. The socket's source address is stored in
+ * <sa> for <salen> bytes.
+ */
+int uxst_get_src(int fd, struct sockaddr *sa, socklen_t salen, int dir)
+{
+       if (dir)
+               return getsockname(fd, sa, &salen);
+       else
+               return getpeername(fd, sa, &salen);
+}
+
+
+/*
+ * Retrieves the original destination address for the socket <fd>, with <dir>
+ * indicating if we're a listener (=0) or an initiator (!=0). It returns 0 in
+ * case of success, -1 in case of error. The socket's source address is stored
+ * in <sa> for <salen> bytes.
+ */
+int uxst_get_dst(int fd, struct sockaddr *sa, socklen_t salen, int dir)
+{
+       if (dir)
+               return getpeername(fd, sa, &salen);
+       else
+               return getsockname(fd, sa, &salen);
+}
+
 
 /* Tries to destroy the UNIX stream socket <path>. The socket must not be used
  * anymore. It practises best effort, and no error is returned.