goto out;
}
}
+ else if (!strcmp(args[0], "log") && kwm == KWM_NO) { /* no log */
+ /* delete previous herited or defined syslog servers */
+ struct logsrv *back;
+ struct logsrv *tmp;
+
+ if (*(args[1]) != 0) {
+ Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
+ err_code |= ERR_ALERT | ERR_FATAL;
+ goto out;
+ }
+
+ list_for_each_entry_safe(tmp, back, &global.logsrvs, list) {
+ LIST_DEL(&tmp->list);
+ free(tmp);
+ }
+ }
else if (!strcmp(args[0], "log")) { /* syslog server address */
- struct logsrv logsrv;
- int facility, level, minlvl;
-
+ struct logsrv *logsrv;
+
if (*(args[1]) == 0 || *(args[2]) == 0) {
Alert("parsing [%s:%d] : '%s' expects <address> and <facility> as arguments.\n", file, linenum, args[0]);
err_code |= ERR_ALERT | ERR_FATAL;
goto out;
}
-
- facility = get_log_facility(args[2]);
- if (facility < 0) {
+
+ logsrv = calloc(1, sizeof(struct logsrv));
+
+ logsrv->facility = get_log_facility(args[2]);
+ if (logsrv->facility < 0) {
Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
err_code |= ERR_ALERT | ERR_FATAL;
- facility = 0;
+ logsrv->facility = 0;
}
- level = 7; /* max syslog level = debug */
+ logsrv->level = 7; /* max syslog level = debug */
if (*(args[3])) {
- level = get_log_level(args[3]);
- if (level < 0) {
+ logsrv->level = get_log_level(args[3]);
+ if (logsrv->level < 0) {
Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
err_code |= ERR_ALERT | ERR_FATAL;
- level = 0;
+ logsrv->level = 0;
}
}
- minlvl = 0; /* limit syslog level to this level (emerg) */
+ logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
if (*(args[4])) {
- minlvl = get_log_level(args[4]);
- if (minlvl < 0) {
+ logsrv->minlvl = get_log_level(args[4]);
+ if (logsrv->minlvl < 0) {
Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[4]);
err_code |= ERR_ALERT | ERR_FATAL;
- minlvl = 0;
+ logsrv->minlvl = 0;
}
}
Alert("parsing [%s:%d] : Socket path '%s' too long (max %d)\n", file, linenum,
args[1], (int)sizeof(((struct sockaddr_un *)&sk)->sun_path) - 1);
err_code |= ERR_ALERT | ERR_FATAL;
+ free(logsrv);
goto out;
}
- logsrv.addr = *sk;
+ logsrv->addr = *sk;
} else {
struct sockaddr_storage *sk = str2sa(args[1]);
if (!sk) {
Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
err_code |= ERR_ALERT | ERR_FATAL;
+ free(logsrv);
goto out;
}
- logsrv.addr = *sk;
- if (!get_host_port(&logsrv.addr))
- set_host_port(&logsrv.addr, SYSLOG_PORT);
+ logsrv->addr = *sk;
+ if (!get_host_port(&logsrv->addr))
+ set_host_port(&logsrv->addr, SYSLOG_PORT);
}
- if (global.logfac1 == -1) {
- global.logsrv1 = logsrv;
- global.logfac1 = facility;
- global.loglev1 = level;
- global.minlvl1 = minlvl;
- }
- else if (global.logfac2 == -1) {
- global.logsrv2 = logsrv;
- global.logfac2 = facility;
- global.loglev2 = level;
- global.minlvl2 = minlvl;
- }
- else {
- Alert("parsing [%s:%d] : too many syslog servers\n", file, linenum);
- err_code |= ERR_ALERT | ERR_FATAL;
- }
+ LIST_ADDQ(&global.logsrvs, &logsrv->list);
}
else if (!strcmp(args[0], "log-send-hostname")) { /* set the hostname in syslog header */
char *name;
unsigned val;
int err_code = 0;
struct acl_cond *cond = NULL;
+ struct logsrv *tmp;
if (!strcmp(args[0], "listen"))
rc = PR_CAP_LISTEN;
}
curproxy->mode = defproxy.mode;
- curproxy->logfac1 = defproxy.logfac1;
- curproxy->logsrv1 = defproxy.logsrv1;
- curproxy->loglev1 = defproxy.loglev1;
- curproxy->minlvl1 = defproxy.minlvl1;
- curproxy->logfac2 = defproxy.logfac2;
- curproxy->logsrv2 = defproxy.logsrv2;
- curproxy->loglev2 = defproxy.loglev2;
- curproxy->minlvl2 = defproxy.minlvl2;
+
+ /* copy default logsrvs to curproxy */
+ list_for_each_entry(tmp, &defproxy.logsrvs, list) {
+ struct logsrv *node = malloc(sizeof(struct logsrv));
+ memcpy(node, tmp, sizeof(struct logsrv));
+ LIST_INIT(&node->list);
+ LIST_ADDQ(&curproxy->logsrvs, &node->list);
+ }
+
curproxy->grace = defproxy.grace;
curproxy->conf.used_listener_id = EB_ROOT;
curproxy->conf.used_server_id = EB_ROOT;
newsrv->prev_state = newsrv->state;
}
}
+ else if (!strcmp(args[0], "log") && kwm == KWM_NO) {
+ /* delete previous herited or defined syslog servers */
+ struct logsrv *back;
+
+ if (*(args[1]) != 0) {
+ Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
+ err_code |= ERR_ALERT | ERR_FATAL;
+ goto out;
+ }
+
+ list_for_each_entry_safe(tmp, back, &curproxy->logsrvs, list) {
+ LIST_DEL(&tmp->list);
+ free(tmp);
+ }
+ }
else if (!strcmp(args[0], "log")) { /* syslog server address */
- struct logsrv logsrv;
- int facility;
-
+ struct logsrv *logsrv;
+
if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
- curproxy->logfac1 = global.logfac1;
- curproxy->logsrv1 = global.logsrv1;
- curproxy->loglev1 = global.loglev1;
- curproxy->minlvl1 = global.minlvl1;
- curproxy->logfac2 = global.logfac2;
- curproxy->logsrv2 = global.logsrv2;
- curproxy->loglev2 = global.loglev2;
- curproxy->minlvl2 = global.minlvl2;
+ /* copy global.logrsvs linked list to the end of curproxy->logsrvs */
+ list_for_each_entry(tmp, &global.logsrvs, list) {
+ struct logsrv *node = malloc(sizeof(struct logsrv));
+ memcpy(node, tmp, sizeof(struct logsrv));
+ LIST_INIT(&node->list);
+ LIST_ADDQ(&curproxy->logsrvs, &node->list);
+ }
}
else if (*(args[1]) && *(args[2])) {
- int level, minlvl;
- facility = get_log_facility(args[2]);
- if (facility < 0) {
+ logsrv = calloc(1, sizeof(struct logsrv));
+
+ logsrv->facility = get_log_facility(args[2]);
+ if (logsrv->facility < 0) {
Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
- exit(1);
+ err_code |= ERR_ALERT | ERR_FATAL;
+ goto out;
+
}
- level = 7; /* max syslog level = debug */
+ logsrv->level = 7; /* max syslog level = debug */
if (*(args[3])) {
- level = get_log_level(args[3]);
- if (level < 0) {
+ logsrv->level = get_log_level(args[3]);
+ if (logsrv->level < 0) {
Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
- exit(1);
+ err_code |= ERR_ALERT | ERR_FATAL;
+ goto out;
+
}
}
- minlvl = 0; /* limit syslog level to this level (emerg) */
+ logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
if (*(args[4])) {
- minlvl = get_log_level(args[4]);
- if (level < 0) {
+ logsrv->minlvl = get_log_level(args[4]);
+ if (logsrv->level < 0) {
Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[4]);
- exit(1);
+ err_code |= ERR_ALERT | ERR_FATAL;
+ goto out;
+
}
}
err_code |= ERR_ALERT | ERR_FATAL;
goto out;
}
- logsrv.addr = *sk;
+ logsrv->addr = *sk;
} else {
struct sockaddr_storage *sk = str2sa(args[1]);
if (!sk) {
err_code |= ERR_ALERT | ERR_FATAL;
goto out;
}
- logsrv.addr = *sk;
- if (!get_host_port(&logsrv.addr))
- set_host_port(&logsrv.addr, SYSLOG_PORT);
- }
-
- if (curproxy->logfac1 == -1) {
- curproxy->logsrv1 = logsrv;
- curproxy->logfac1 = facility;
- curproxy->loglev1 = level;
- curproxy->minlvl1 = minlvl;
- }
- else if (curproxy->logfac2 == -1) {
- curproxy->logsrv2 = logsrv;
- curproxy->logfac2 = facility;
- curproxy->loglev2 = level;
- curproxy->minlvl2 = minlvl;
- }
- else {
- Alert("parsing [%s:%d] : too many syslog servers\n", file, linenum);
- err_code |= ERR_ALERT | ERR_FATAL;
- goto out;
+ logsrv->addr = *sk;
+ if (!get_host_port(&logsrv->addr))
+ set_host_port(&logsrv->addr, SYSLOG_PORT);
}
+
+ LIST_ADDQ(&curproxy->logsrvs, &logsrv->list);
}
else {
Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
/* check for keyword modifiers "no" and "default" */
if (!strcmp(args[0], "no")) {
+ char *tmp;
+
kwm = KWM_NO;
+ tmp = args[0];
for (arg=0; *args[arg+1]; arg++)
args[arg] = args[arg+1]; // shift args after inversion
+ *tmp = '\0'; // fix the next arg to \0
+ args[arg] = tmp;
}
else if (!strcmp(args[0], "default")) {
kwm = KWM_DEF;
args[arg] = args[arg+1]; // shift args after inversion
}
- if (kwm != KWM_STD && strcmp(args[0], "option") != 0) {
- Alert("parsing [%s:%d]: negation/default currently supported only for options.\n", file, linenum);
+ if (kwm != KWM_STD && strcmp(args[0], "option") != 0 && \
+ strcmp(args[0], "log") != 0) {
+ Alert("parsing [%s:%d]: negation/default currently supported only for options and log.\n", file, linenum);
err_code |= ERR_ALERT | ERR_FATAL;
}
curproxy->to_log &= ~LW_BYTES;
if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
- (curproxy->cap & PR_CAP_FE) && curproxy->to_log && curproxy->logfac1 < 0) {
+ (curproxy->cap & PR_CAP_FE) && curproxy->to_log && LIST_ISEMPTY(&curproxy->logsrvs)) {
Warning("config : log format ignored for %s '%s' since it has no log address.\n",
proxy_type_str(curproxy), curproxy->id);
err_code |= ERR_WARN;
static char *dataptr = NULL;
int fac_level;
int hdr_len, data_len;
- struct logsrv *logsrvs[2];
- int facilities[2], loglevel[2], minlvl[2];
+ struct list *logsrvs = NULL;
+ struct logsrv *tmp = NULL;
int nblogger;
- int nbloggers = 0;
char *log_ptr;
if (level < 0 || message == NULL)
dataptr[data_len - 1] = '\n'; /* force a break on ultra-long lines */
if (p == NULL) {
- if (global.logfac1 >= 0) {
- logsrvs[nbloggers] = &global.logsrv1;
- facilities[nbloggers] = global.logfac1;
- loglevel[nbloggers] = global.loglev1;
- minlvl[nbloggers] = global.minlvl1;
- nbloggers++;
- }
- if (global.logfac2 >= 0) {
- logsrvs[nbloggers] = &global.logsrv2;
- facilities[nbloggers] = global.logfac2;
- loglevel[nbloggers] = global.loglev2;
- minlvl[nbloggers] = global.minlvl2;
- nbloggers++;
+ if (!LIST_ISEMPTY(&global.logsrvs)) {
+ logsrvs = &global.logsrvs;
}
} else {
- if (p->logfac1 >= 0) {
- logsrvs[nbloggers] = &p->logsrv1;
- facilities[nbloggers] = p->logfac1;
- loglevel[nbloggers] = p->loglev1;
- minlvl[nbloggers] = p->minlvl1;
- nbloggers++;
- }
- if (p->logfac2 >= 0) {
- logsrvs[nbloggers] = &p->logsrv2;
- facilities[nbloggers] = p->logfac2;
- loglevel[nbloggers] = p->loglev2;
- minlvl[nbloggers] = p->minlvl2;
- nbloggers++;
+ if (!LIST_ISEMPTY(&p->logsrvs)) {
+ logsrvs = &p->logsrvs;
}
}
+ if (!logsrvs)
+ return;
+
/* Lazily set up syslog sockets for protocol families of configured
* syslog servers. */
- for (nblogger = 0; nblogger < nbloggers; nblogger++) {
- const struct logsrv *logsrv = logsrvs[nblogger];
+ nblogger = 0;
+ list_for_each_entry(tmp, logsrvs, list) {
+ const struct logsrv *logsrv = tmp;
int proto, *plogfd;
+
if (logsrv->addr.ss_family == AF_UNIX) {
proto = 0;
plogfd = &logfdunix;
setsockopt(*plogfd, SOL_SOCKET, SO_RCVBUF, &zero, sizeof(zero));
/* does nothing under Linux, maybe needed for others */
shutdown(*plogfd, SHUT_RD);
+ nblogger++;
}
/* Send log messages to syslog server. */
- for (nblogger = 0; nblogger < nbloggers; nblogger++) {
- const struct logsrv *logsrv = logsrvs[nblogger];
+ nblogger = 0;
+ list_for_each_entry(tmp, logsrvs, list) {
+ const struct logsrv *logsrv = tmp;
int *plogfd = logsrv->addr.ss_family == AF_UNIX ?
&logfdunix : &logfdinet;
int sent;
/* we can filter the level of the messages that are sent to each logger */
- if (level > loglevel[nblogger])
+ if (level > logsrv->level)
continue;
/* For each target, we may have a different facility.
* time, we only change the facility in the pre-computed header,
* and we change the pointer to the header accordingly.
*/
- fac_level = (facilities[nblogger] << 3) + MAX(level, minlvl[nblogger]);
+ fac_level = (logsrv->facility << 3) + MAX(level, logsrv->minlvl);
log_ptr = logmsg + 3; /* last digit of the log level */
do {
*log_ptr = '0' + fac_level % 10;
Alert("sendto logger #%d failed: %s (errno=%d)\n",
nblogger, strerror(errno), errno);
}
+ nblogger++;
}
}
addr_to_str(&s->si[0].addr.from, pn, sizeof(pn));
get_localtime(s->logs.tv_accept.tv_sec, &tm);
- if (fe->logfac1 < 0 && fe->logfac2 < 0)
+ if(LIST_ISEMPTY(&fe->logsrvs))
return;
prx_log = fe;