]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MEDIUM: log-format: backend source address %Bi %Bp
authorWilliam Lallemand <wlallemand@exceliance.fr>
Fri, 2 Mar 2012 13:35:21 +0000 (14:35 +0100)
committerWilly Tarreau <w@1wt.eu>
Mon, 12 Mar 2012 14:50:52 +0000 (15:50 +0100)
%Bi return the backend source IP
%Bp return the backend source port

Add a function pointer in logformat_type to do additional configuration
during the log-format variable parsing.

doc/configuration.txt
include/types/log.h
include/types/proxy.h
include/types/session.h
include/types/stream_interface.h
src/backend.c
src/log.c
src/proto_tcp.c

index 70a25391e74eb86bee18f30115bacf697ba5e5ff..58ceebbe87f11a07a0542cf2035c3c4d5cf2e625 100644 (file)
@@ -8790,6 +8790,8 @@ Please refer to the table below for currently defined variables :
   |   | %B   | bytes_read                                    | numeric     |
   |   | %Ci  | client_ip                                     | string      |
   |   | %Cp  | client_port                                   | numeric     |
+  |   | %Bi  | backend_source_ip                             | string      |
+  |   | %Bp  | backend_source_port                           | numeric     |
   |   | %Tc  | Tc                                            | numeric     |
   | * | %Tq  | Tq                                            | numeric     |
   | * | %Tr  | Tr                                            | numeric     |
index 0e780241164414513ed92eb16e8ce83214a980ec..2f11aabb7f88254b58dd537003a29c610c16fc74 100644 (file)
@@ -44,6 +44,8 @@ enum {
        LOG_GLOBAL,
        LOG_CLIENTIP,
        LOG_CLIENTPORT,
+       LOG_SOURCEPORT,
+       LOG_SOURCEIP,
        LOG_DATE,
        LOG_DATEGMT,
        LOG_MS,
index 6693d8288dd0f4ba25e9a7098a2b106512cb2290..26cdfe4650927f9aca394e4d8071e802e87440db 100644 (file)
@@ -138,7 +138,9 @@ enum {
 #define PR_O2_NODELAY   0x00020000      /* fully interactive mode, never delay outgoing data */
 #define PR_O2_USE_PXHDR 0x00040000      /* use Proxy-Connection for proxy requests */
 #define PR_O2_CHK_SNDST 0x00080000      /* send the state of each server along with HTTP health checks */
-/* unused: 0x00100000 */
+
+#define PR_O2_SRC_ADDR 0x00100000      /* get the source ip and port for logs */
+
 #define PR_O2_FAKE_KA   0x00200000      /* pretend we do keep-alive with server eventhough we close */
 /* unused: 0x00400000 */
 #define PR_O2_EXP_NONE  0x00000000      /* http-check : no expect rule */
index a707aa52e145ef81cbddbc4fbde6f779d95b20cb..5678e5c069a1df42f154bb825deb3c71d5ecc713 100644 (file)
@@ -84,6 +84,7 @@
 #define SN_IGNORE_PRST 0x00080000      /* ignore persistence */
 #define SN_BE_TRACK_SC1 0x00100000     /* backend tracks stick-counter 1 */
 #define SN_BE_TRACK_SC2 0x00200000     /* backend tracks stick-counter 2 */
+#define SN_BCK_ADDR_SET 0x00400000     /* set if the backend address has been filled */
 
 /* Termination sequence tracing.
  *
index 4f0bfa2d25c8e7eaa9d24d891bd435b9c894fe16..5acbd5743c3b6b855627a46d3cd9859a1e8261d2 100644 (file)
@@ -72,6 +72,7 @@ enum {
        SI_FL_DONT_WAKE  = 0x0020,  /* resync in progress, don't wake up */
        SI_FL_INDEP_STR  = 0x0040,  /* independant streams = don't update rex on write */
        SI_FL_NOLINGER   = 0x0080,  /* may close without lingering. One-shot. */
+       SI_FL_SRC_ADDR   = 0x1000,  /* get the source ip/port with getsockname */
 };
 
 /* target types */
index 32eea68b4cf6534f97fbbc117cf10dda0a43e4b0..39ee58bce7385bf0aa8395164ee7f0fc1aba016b 100644 (file)
@@ -985,6 +985,10 @@ int connect_server(struct session *s)
 
        assign_tproxy_address(s);
 
+       /* flag for logging source ip/port */
+       if (s->fe->options2 & PR_O2_SRC_ADDR)
+               s->req->cons->flags |= SI_FL_SRC_ADDR;
+
        err = s->req->cons->connect(s->req->cons);
 
        if (err != SN_ERR_NONE)
index 3bcfaa56b9bdf63ac9de93cab8039deb458b47b2..e129c2d12f7aaa3895266463c876cf84453a71d2 100644 (file)
--- a/src/log.c
+++ b/src/log.c
@@ -57,42 +57,47 @@ struct logformat_type {
        char *name;
        int type;
        int mode;
+       int (*config_callback)(struct logformat_node *node, struct proxy *curproxy);
 };
 
+int prepare_addrsource(struct logformat_node *node, struct proxy *curproxy);
+
 /* log_format variable names */
 static const struct logformat_type logformat_keywords[] = {
-       { "o", LOG_GLOBAL, PR_MODE_TCP },  /* global option */
-       { "Ci", LOG_CLIENTIP, PR_MODE_TCP },  /* client ip */
-       { "Cp", LOG_CLIENTPORT, PR_MODE_TCP }, /* client port */
-       { "t", LOG_DATE, PR_MODE_TCP },      /* date */
-       { "T", LOG_DATEGMT, PR_MODE_TCP },   /* date GMT */
-       { "ms", LOG_MS, PR_MODE_TCP },       /* accept date millisecond */
-       { "f", LOG_FRONTEND, PR_MODE_TCP },  /* frontend */
-       { "b", LOG_BACKEND, PR_MODE_TCP },   /* backend */
-       { "s", LOG_SERVER, PR_MODE_TCP },    /* server */
-       { "B", LOG_BYTES, PR_MODE_TCP },     /* bytes read */
-       { "Tq", LOG_TQ, PR_MODE_HTTP },       /* Tq */
-       { "Tw", LOG_TW, PR_MODE_TCP },       /* Tw */
-       { "Tc", LOG_TC, PR_MODE_TCP },       /* Tc */
-       { "Tr", LOG_TR, PR_MODE_HTTP },       /* Tr */
-       { "Tt", LOG_TT, PR_MODE_TCP },       /* Tt */
-       { "st", LOG_STATUS, PR_MODE_HTTP },   /* status code */
-       { "cc", LOG_CCLIENT, PR_MODE_HTTP },  /* client cookie */
-       { "cs", LOG_CSERVER, PR_MODE_HTTP },  /* server cookie */
-       { "ts", LOG_TERMSTATE, PR_MODE_TCP },/* terminaison state */
-       { "ac", LOG_ACTCONN, PR_MODE_TCP },  /* actconn */
-       { "fc", LOG_FECONN, PR_MODE_TCP },   /* feconn */
-       { "bc", LOG_BECONN, PR_MODE_TCP },   /* beconn */
-       { "sc", LOG_SRVCONN, PR_MODE_TCP },  /* srv_conn */
-       { "rc", LOG_RETRIES, PR_MODE_TCP },  /* retries */
-       { "sq", LOG_SRVQUEUE, PR_MODE_TCP  }, /* srv_queue */
-       { "bq", LOG_BCKQUEUE, PR_MODE_TCP }, /* backend_queue */
-       { "hr", LOG_HDRREQUEST, PR_MODE_HTTP }, /* header request */
-       { "hs", LOG_HDRRESPONS, PR_MODE_HTTP },  /* header response */
-       { "hrl", LOG_HDRREQUESTLIST, PR_MODE_HTTP }, /* header request list */
-       { "hsl", LOG_HDRRESPONSLIST, PR_MODE_HTTP },  /* header response list */
-       { "r", LOG_REQ, PR_MODE_HTTP },  /* request */
-       { 0, 0 }
+       { "o", LOG_GLOBAL, PR_MODE_TCP, NULL },  /* global option */
+       { "Ci", LOG_CLIENTIP, PR_MODE_TCP, NULL },  /* client ip */
+       { "Cp", LOG_CLIENTPORT, PR_MODE_TCP, NULL }, /* client port */
+       { "Bp", LOG_SOURCEPORT, PR_MODE_TCP, prepare_addrsource }, /* backend source port */
+       { "Bi", LOG_SOURCEIP, PR_MODE_TCP, prepare_addrsource }, /* backend source ip */
+       { "t", LOG_DATE, PR_MODE_TCP, NULL },      /* date */
+       { "T", LOG_DATEGMT, PR_MODE_TCP, NULL },   /* date GMT */
+       { "ms", LOG_MS, PR_MODE_TCP, NULL },       /* accept date millisecond */
+       { "f", LOG_FRONTEND, PR_MODE_TCP, NULL },  /* frontend */
+       { "b", LOG_BACKEND, PR_MODE_TCP, NULL },   /* backend */
+       { "s", LOG_SERVER, PR_MODE_TCP, NULL },    /* server */
+       { "B", LOG_BYTES, PR_MODE_TCP, NULL },     /* bytes read */
+       { "Tq", LOG_TQ, PR_MODE_HTTP, NULL },       /* Tq */
+       { "Tw", LOG_TW, PR_MODE_TCP, NULL },       /* Tw */
+       { "Tc", LOG_TC, PR_MODE_TCP, NULL },       /* Tc */
+       { "Tr", LOG_TR, PR_MODE_HTTP, NULL },       /* Tr */
+       { "Tt", LOG_TT, PR_MODE_TCP, NULL },       /* Tt */
+       { "st", LOG_STATUS, PR_MODE_HTTP, NULL },   /* status code */
+       { "cc", LOG_CCLIENT, PR_MODE_HTTP, NULL },  /* client cookie */
+       { "cs", LOG_CSERVER, PR_MODE_HTTP, NULL },  /* server cookie */
+       { "ts", LOG_TERMSTATE, PR_MODE_TCP, NULL },/* terminaison state */
+       { "ac", LOG_ACTCONN, PR_MODE_TCP, NULL },  /* actconn */
+       { "fc", LOG_FECONN, PR_MODE_TCP, NULL },   /* feconn */
+       { "bc", LOG_BECONN, PR_MODE_TCP, NULL },   /* beconn */
+       { "sc", LOG_SRVCONN, PR_MODE_TCP, NULL },  /* srv_conn */
+       { "rc", LOG_RETRIES, PR_MODE_TCP, NULL },  /* retries */
+       { "sq", LOG_SRVQUEUE, PR_MODE_TCP, NULL  }, /* srv_queue */
+       { "bq", LOG_BCKQUEUE, PR_MODE_TCP, NULL }, /* backend_queue */
+       { "hr", LOG_HDRREQUEST, PR_MODE_HTTP, NULL }, /* header request */
+       { "hs", LOG_HDRRESPONS, PR_MODE_HTTP, NULL },  /* header response */
+       { "hrl", LOG_HDRREQUESTLIST, PR_MODE_HTTP, NULL }, /* header request list */
+       { "hsl", LOG_HDRRESPONSLIST, PR_MODE_HTTP, NULL },  /* header response list */
+       { "r", LOG_REQ, PR_MODE_HTTP, NULL },  /* request */
+       { 0, 0, 0, NULL }
 };
 
 char default_http_log_format[] = "%Ci:%Cp [%t] %f %b/%s %Tq/%Tw/%Tc/%Tr/%Tt %st %B %cc %cs %ts %ac/%fc/%bc/%sc/%rc %sq/%bq %hr %hs %{+Q}r"; // default format
@@ -112,6 +117,17 @@ struct logformat_var_args var_args_list[] = {
        {  0,  0 }
 };
 
+/*
+ * callback used to configure addr source retrieval
+ */
+int prepare_addrsource(struct logformat_node *node, struct proxy *curproxy)
+{
+       curproxy->options2 |= PR_O2_SRC_ADDR;
+
+       return 0;
+}
+
+
 /*
  * Parse args in a logformat_var
  */
@@ -201,6 +217,11 @@ int parse_logformat_var(char *str, size_t len, struct proxy *curproxy)
                                                        logformat_options = node->options;
                                                        free(node);
                                                } else {
+                                                       if (logformat_keywords[j].config_callback != NULL) {
+                                                               if (logformat_keywords[j].config_callback(node, curproxy) != 0) {
+                                                                       return -1;
+                                                                }
+                                                       }
                                                        LIST_ADDQ(&curproxy->logformat, &node->list);
                                                }
                                                return 0;
@@ -678,6 +699,7 @@ const char sess_set_cookie[8] = "NPDIRU67"; /* No set-cookie, Set-cookie found a
 void sess_log(struct session *s)
 {
        char pn[INET6_ADDRSTRLEN];
+       char sn[INET6_ADDRSTRLEN];
        struct proxy *fe = s->fe;
        struct proxy *be = s->be;
        struct proxy *prx_log;
@@ -707,6 +729,11 @@ void sess_log(struct session *s)
        if (addr_to_str(&s->req->prod->addr.from, pn, sizeof(pn)) == AF_UNIX)
                snprintf(pn, sizeof(pn), "unix:%d", s->listener->luid);
 
+       if (be->options2 & PR_O2_SRC_ADDR) {
+             if (addr_to_str(&s->req->cons->addr.from, sn, sizeof(sn)) == AF_UNIX)
+               snprintf(sn, sizeof(sn), "unix:%d", s->listener->luid);
+       }
+
        /* FIXME: let's limit ourselves to frontend logging for now. */
        tolog = fe->to_log;
 
@@ -774,6 +801,23 @@ void sess_log(struct session *s)
                                last_isspace = 0;
                                break;
 
+                       case LOG_SOURCEIP:  // Bi
+                               src = (s->req->cons->addr.from.ss_family == AF_UNIX) ? "unix" : sn;
+                               tmplog = logformat_write_string(tmplog, src, MAX_SYSLOG_LEN - (tmplog - logline), tmp);
+
+                               if (!tmplog)
+                                       goto out;
+                               last_isspace = 0;
+                               break;
+
+                       case LOG_SOURCEPORT:  // %Bp
+                               tmplog = ltoa_o((s->req->cons->addr.from.ss_family == AF_UNIX) ? s->listener->luid : get_host_port(&s->req->cons->addr.from),
+                                               tmplog, MAX_SYSLOG_LEN - (tmplog - logline));
+                               if (!tmplog)
+                                       goto out;
+                               last_isspace = 0;
+                               break;
+
                        case LOG_DATE: // %t
                                get_localtime(s->logs.accept_date.tv_sec, &tm);
                                tmplog = date2str_log(tmplog, &tm, &(s->logs.accept_date), MAX_SYSLOG_LEN - (tmplog - logline));
index ea3692cbbcc0f21144bdf71149d695ecfd573257..80f1e36eb04be5fa9d977e49338ebcea2480a9ba 100644 (file)
@@ -437,6 +437,14 @@ int tcp_connect_server(struct stream_interface *si)
                }
        }
 
+       /* needs src ip/port for logging */
+       if (si->flags & SI_FL_SRC_ADDR) {
+               socklen_t addrlen = sizeof(si->addr.to);
+               if (getsockname(fd, (struct sockaddr *)&si->addr.from, &addrlen) == -1) {
+                       Warning("Cannot get source address for logging.\n");
+               }
+       }
+
        fdtab[fd].owner = si;
        fdtab[fd].state = FD_STCONN; /* connection in progress */
        fdtab[fd].flags = FD_FL_TCP | FD_FL_TCP_NODELAY;