MEDIUM: log-format: backend source address %Bi %Bp
%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.
diff --git a/doc/configuration.txt b/doc/configuration.txt
index 70a2539..58ceebb 100644
--- a/doc/configuration.txt
+++ b/doc/configuration.txt
@@ -8790,6 +8790,8 @@
| | %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 |
diff --git a/include/types/log.h b/include/types/log.h
index 0e78024..2f11aab 100644
--- a/include/types/log.h
+++ b/include/types/log.h
@@ -44,6 +44,8 @@
LOG_GLOBAL,
LOG_CLIENTIP,
LOG_CLIENTPORT,
+ LOG_SOURCEPORT,
+ LOG_SOURCEIP,
LOG_DATE,
LOG_DATEGMT,
LOG_MS,
diff --git a/include/types/proxy.h b/include/types/proxy.h
index 6693d82..26cdfe4 100644
--- a/include/types/proxy.h
+++ b/include/types/proxy.h
@@ -138,7 +138,9 @@
#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 */
diff --git a/include/types/session.h b/include/types/session.h
index a707aa5..5678e5c 100644
--- a/include/types/session.h
+++ b/include/types/session.h
@@ -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.
*
diff --git a/include/types/stream_interface.h b/include/types/stream_interface.h
index 4f0bfa2..5acbd57 100644
--- a/include/types/stream_interface.h
+++ b/include/types/stream_interface.h
@@ -72,6 +72,7 @@
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 */
diff --git a/src/backend.c b/src/backend.c
index 32eea68..39ee58b 100644
--- a/src/backend.c
+++ b/src/backend.c
@@ -985,6 +985,10 @@
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)
diff --git a/src/log.c b/src/log.c
index 3bcfaa5..e129c2d 100644
--- a/src/log.c
+++ b/src/log.c
@@ -57,42 +57,47 @@
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
@@ -113,6 +118,17 @@
};
/*
+ * 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
*/
int parse_logformat_var_args(char *args, struct logformat_node *node)
@@ -201,6 +217,11 @@
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 @@
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 @@
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 @@
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));
diff --git a/src/proto_tcp.c b/src/proto_tcp.c
index ea3692c..80f1e36 100644
--- a/src/proto_tcp.c
+++ b/src/proto_tcp.c
@@ -437,6 +437,14 @@
}
}
+ /* 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;