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.
This commit is contained in:
William Lallemand 2012-03-02 14:35:21 +01:00 committed by Willy Tarreau
parent bddd4fd93b
commit b7ff6a3a36
8 changed files with 97 additions and 33 deletions

View File

@ -8790,6 +8790,8 @@ Please refer to the table below for currently defined variables :
| | %B | bytes_read | numeric | | | %B | bytes_read | numeric |
| | %Ci | client_ip | string | | | %Ci | client_ip | string |
| | %Cp | client_port | numeric | | | %Cp | client_port | numeric |
| | %Bi | backend_source_ip | string |
| | %Bp | backend_source_port | numeric |
| | %Tc | Tc | numeric | | | %Tc | Tc | numeric |
| * | %Tq | Tq | numeric | | * | %Tq | Tq | numeric |
| * | %Tr | Tr | numeric | | * | %Tr | Tr | numeric |

View File

@ -44,6 +44,8 @@ enum {
LOG_GLOBAL, LOG_GLOBAL,
LOG_CLIENTIP, LOG_CLIENTIP,
LOG_CLIENTPORT, LOG_CLIENTPORT,
LOG_SOURCEPORT,
LOG_SOURCEIP,
LOG_DATE, LOG_DATE,
LOG_DATEGMT, LOG_DATEGMT,
LOG_MS, LOG_MS,

View File

@ -138,7 +138,9 @@ enum {
#define PR_O2_NODELAY 0x00020000 /* fully interactive mode, never delay outgoing data */ #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_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 */ #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 */ #define PR_O2_FAKE_KA 0x00200000 /* pretend we do keep-alive with server eventhough we close */
/* unused: 0x00400000 */ /* unused: 0x00400000 */
#define PR_O2_EXP_NONE 0x00000000 /* http-check : no expect rule */ #define PR_O2_EXP_NONE 0x00000000 /* http-check : no expect rule */

View File

@ -84,6 +84,7 @@
#define SN_IGNORE_PRST 0x00080000 /* ignore persistence */ #define SN_IGNORE_PRST 0x00080000 /* ignore persistence */
#define SN_BE_TRACK_SC1 0x00100000 /* backend tracks stick-counter 1 */ #define SN_BE_TRACK_SC1 0x00100000 /* backend tracks stick-counter 1 */
#define SN_BE_TRACK_SC2 0x00200000 /* backend tracks stick-counter 2 */ #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. /* Termination sequence tracing.
* *

View File

@ -72,6 +72,7 @@ enum {
SI_FL_DONT_WAKE = 0x0020, /* resync in progress, don't wake up */ 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_INDEP_STR = 0x0040, /* independant streams = don't update rex on write */
SI_FL_NOLINGER = 0x0080, /* may close without lingering. One-shot. */ SI_FL_NOLINGER = 0x0080, /* may close without lingering. One-shot. */
SI_FL_SRC_ADDR = 0x1000, /* get the source ip/port with getsockname */
}; };
/* target types */ /* target types */

View File

@ -985,6 +985,10 @@ int connect_server(struct session *s)
assign_tproxy_address(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); err = s->req->cons->connect(s->req->cons);
if (err != SN_ERR_NONE) if (err != SN_ERR_NONE)

108
src/log.c
View File

@ -57,42 +57,47 @@ struct logformat_type {
char *name; char *name;
int type; int type;
int mode; 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 */ /* log_format variable names */
static const struct logformat_type logformat_keywords[] = { static const struct logformat_type logformat_keywords[] = {
{ "o", LOG_GLOBAL, PR_MODE_TCP }, /* global option */ { "o", LOG_GLOBAL, PR_MODE_TCP, NULL }, /* global option */
{ "Ci", LOG_CLIENTIP, PR_MODE_TCP }, /* client ip */ { "Ci", LOG_CLIENTIP, PR_MODE_TCP, NULL }, /* client ip */
{ "Cp", LOG_CLIENTPORT, PR_MODE_TCP }, /* client port */ { "Cp", LOG_CLIENTPORT, PR_MODE_TCP, NULL }, /* client port */
{ "t", LOG_DATE, PR_MODE_TCP }, /* date */ { "Bp", LOG_SOURCEPORT, PR_MODE_TCP, prepare_addrsource }, /* backend source port */
{ "T", LOG_DATEGMT, PR_MODE_TCP }, /* date GMT */ { "Bi", LOG_SOURCEIP, PR_MODE_TCP, prepare_addrsource }, /* backend source ip */
{ "ms", LOG_MS, PR_MODE_TCP }, /* accept date millisecond */ { "t", LOG_DATE, PR_MODE_TCP, NULL }, /* date */
{ "f", LOG_FRONTEND, PR_MODE_TCP }, /* frontend */ { "T", LOG_DATEGMT, PR_MODE_TCP, NULL }, /* date GMT */
{ "b", LOG_BACKEND, PR_MODE_TCP }, /* backend */ { "ms", LOG_MS, PR_MODE_TCP, NULL }, /* accept date millisecond */
{ "s", LOG_SERVER, PR_MODE_TCP }, /* server */ { "f", LOG_FRONTEND, PR_MODE_TCP, NULL }, /* frontend */
{ "B", LOG_BYTES, PR_MODE_TCP }, /* bytes read */ { "b", LOG_BACKEND, PR_MODE_TCP, NULL }, /* backend */
{ "Tq", LOG_TQ, PR_MODE_HTTP }, /* Tq */ { "s", LOG_SERVER, PR_MODE_TCP, NULL }, /* server */
{ "Tw", LOG_TW, PR_MODE_TCP }, /* Tw */ { "B", LOG_BYTES, PR_MODE_TCP, NULL }, /* bytes read */
{ "Tc", LOG_TC, PR_MODE_TCP }, /* Tc */ { "Tq", LOG_TQ, PR_MODE_HTTP, NULL }, /* Tq */
{ "Tr", LOG_TR, PR_MODE_HTTP }, /* Tr */ { "Tw", LOG_TW, PR_MODE_TCP, NULL }, /* Tw */
{ "Tt", LOG_TT, PR_MODE_TCP }, /* Tt */ { "Tc", LOG_TC, PR_MODE_TCP, NULL }, /* Tc */
{ "st", LOG_STATUS, PR_MODE_HTTP }, /* status code */ { "Tr", LOG_TR, PR_MODE_HTTP, NULL }, /* Tr */
{ "cc", LOG_CCLIENT, PR_MODE_HTTP }, /* client cookie */ { "Tt", LOG_TT, PR_MODE_TCP, NULL }, /* Tt */
{ "cs", LOG_CSERVER, PR_MODE_HTTP }, /* server cookie */ { "st", LOG_STATUS, PR_MODE_HTTP, NULL }, /* status code */
{ "ts", LOG_TERMSTATE, PR_MODE_TCP },/* terminaison state */ { "cc", LOG_CCLIENT, PR_MODE_HTTP, NULL }, /* client cookie */
{ "ac", LOG_ACTCONN, PR_MODE_TCP }, /* actconn */ { "cs", LOG_CSERVER, PR_MODE_HTTP, NULL }, /* server cookie */
{ "fc", LOG_FECONN, PR_MODE_TCP }, /* feconn */ { "ts", LOG_TERMSTATE, PR_MODE_TCP, NULL },/* terminaison state */
{ "bc", LOG_BECONN, PR_MODE_TCP }, /* beconn */ { "ac", LOG_ACTCONN, PR_MODE_TCP, NULL }, /* actconn */
{ "sc", LOG_SRVCONN, PR_MODE_TCP }, /* srv_conn */ { "fc", LOG_FECONN, PR_MODE_TCP, NULL }, /* feconn */
{ "rc", LOG_RETRIES, PR_MODE_TCP }, /* retries */ { "bc", LOG_BECONN, PR_MODE_TCP, NULL }, /* beconn */
{ "sq", LOG_SRVQUEUE, PR_MODE_TCP }, /* srv_queue */ { "sc", LOG_SRVCONN, PR_MODE_TCP, NULL }, /* srv_conn */
{ "bq", LOG_BCKQUEUE, PR_MODE_TCP }, /* backend_queue */ { "rc", LOG_RETRIES, PR_MODE_TCP, NULL }, /* retries */
{ "hr", LOG_HDRREQUEST, PR_MODE_HTTP }, /* header request */ { "sq", LOG_SRVQUEUE, PR_MODE_TCP, NULL }, /* srv_queue */
{ "hs", LOG_HDRRESPONS, PR_MODE_HTTP }, /* header response */ { "bq", LOG_BCKQUEUE, PR_MODE_TCP, NULL }, /* backend_queue */
{ "hrl", LOG_HDRREQUESTLIST, PR_MODE_HTTP }, /* header request list */ { "hr", LOG_HDRREQUEST, PR_MODE_HTTP, NULL }, /* header request */
{ "hsl", LOG_HDRRESPONSLIST, PR_MODE_HTTP }, /* header response list */ { "hs", LOG_HDRRESPONS, PR_MODE_HTTP, NULL }, /* header response */
{ "r", LOG_REQ, PR_MODE_HTTP }, /* request */ { "hrl", LOG_HDRREQUESTLIST, PR_MODE_HTTP, NULL }, /* header request list */
{ 0, 0 } { "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 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 } { 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 * 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; logformat_options = node->options;
free(node); free(node);
} else { } 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); LIST_ADDQ(&curproxy->logformat, &node->list);
} }
return 0; 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) void sess_log(struct session *s)
{ {
char pn[INET6_ADDRSTRLEN]; char pn[INET6_ADDRSTRLEN];
char sn[INET6_ADDRSTRLEN];
struct proxy *fe = s->fe; struct proxy *fe = s->fe;
struct proxy *be = s->be; struct proxy *be = s->be;
struct proxy *prx_log; 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) if (addr_to_str(&s->req->prod->addr.from, pn, sizeof(pn)) == AF_UNIX)
snprintf(pn, sizeof(pn), "unix:%d", s->listener->luid); 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. */ /* FIXME: let's limit ourselves to frontend logging for now. */
tolog = fe->to_log; tolog = fe->to_log;
@ -774,6 +801,23 @@ void sess_log(struct session *s)
last_isspace = 0; last_isspace = 0;
break; 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 case LOG_DATE: // %t
get_localtime(s->logs.accept_date.tv_sec, &tm); get_localtime(s->logs.accept_date.tv_sec, &tm);
tmplog = date2str_log(tmplog, &tm, &(s->logs.accept_date), MAX_SYSLOG_LEN - (tmplog - logline)); tmplog = date2str_log(tmplog, &tm, &(s->logs.accept_date), MAX_SYSLOG_LEN - (tmplog - logline));

View 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].owner = si;
fdtab[fd].state = FD_STCONN; /* connection in progress */ fdtab[fd].state = FD_STCONN; /* connection in progress */
fdtab[fd].flags = FD_FL_TCP | FD_FL_TCP_NODELAY; fdtab[fd].flags = FD_FL_TCP | FD_FL_TCP_NODELAY;