diff -ru haproxy-1.3.13.1.orig/include/common/standard.h haproxy-1.3.13.1/include/common/standard.h --- haproxy-1.3.13.1.orig/include/common/standard.h 2007-11-03 23:57:29.000000000 -0700 +++ haproxy-1.3.13.1/include/common/standard.h 2007-12-04 14:13:50.000000000 -0800 @@ -75,6 +75,12 @@ extern int ishex(char s); /* + * converts to a struct sockaddr_un* which is locally allocated. + * The format is "/path", where "/path" is a path to a UNIX domain socket. + */ +struct sockaddr_un *str2sun(char *str); + +/* * converts to a struct sockaddr_in* which is locally allocated. * The format is "addr:port", where "addr" can be a dotted IPv4 address, * a host name, or empty or "*" to indicate INADDR_ANY. diff -ru haproxy-1.3.13.1.orig/include/types/global.h haproxy-1.3.13.1/include/types/global.h --- haproxy-1.3.13.1.orig/include/types/global.h 2007-11-03 23:57:29.000000000 -0700 +++ haproxy-1.3.13.1/include/types/global.h 2007-12-04 12:14:28.000000000 -0800 @@ -25,6 +25,7 @@ #include #include +#include #include #include @@ -59,7 +60,7 @@ char *pidfile; int logfac1, logfac2; int loglev1, loglev2; - struct sockaddr_in logsrv1, logsrv2; + struct logsrv logsrv1, logsrv2; struct { int maxpollevents; /* max number of poll events at once */ } tune; diff -ru haproxy-1.3.13.1.orig/include/types/log.h haproxy-1.3.13.1/include/types/log.h --- haproxy-1.3.13.1.orig/include/types/log.h 2007-11-03 23:57:29.000000000 -0700 +++ haproxy-1.3.13.1/include/types/log.h 2007-12-04 14:54:09.000000000 -0800 @@ -22,6 +22,8 @@ #ifndef _TYPES_LOG_H #define _TYPES_LOG_H +#include +#include #include #define MAX_SYSLOG_LEN 1024 @@ -44,6 +46,15 @@ #define LW_REQHDR 1024 /* request header(s) */ #define LW_RSPHDR 2048 /* response header(s) */ +struct logsrv { + union { + struct sockaddr addr; + struct sockaddr_un un; /* AF_UNIX */ + struct sockaddr_in in; /* AF_INET */ + } u; +}; + +int logsrv_addrlen(const struct logsrv *logsrv); #endif /* _TYPES_LOG_H */ diff -ru haproxy-1.3.13.1.orig/include/types/proxy.h haproxy-1.3.13.1/include/types/proxy.h --- haproxy-1.3.13.1.orig/include/types/proxy.h 2007-11-03 23:57:29.000000000 -0700 +++ haproxy-1.3.13.1/include/types/proxy.h 2007-12-04 12:14:28.000000000 -0800 @@ -37,6 +37,7 @@ #include #include #include +#include #include #include #include @@ -124,7 +125,7 @@ struct sockaddr_in tproxy_addr; /* non-local address we want to bind to for connect() */ #endif struct proxy *next; - struct sockaddr_in logsrv1, logsrv2; /* 2 syslog servers */ + struct logsrv logsrv1, logsrv2; /* 2 syslog servers */ signed char logfac1, logfac2; /* log facility for both servers. -1 = disabled */ int loglev1, loglev2; /* log level for each server, 7 by default */ int to_log; /* things to be logged (LW_*) */ diff -ru haproxy-1.3.13.1.orig/src/cfgparse.c haproxy-1.3.13.1/src/cfgparse.c --- haproxy-1.3.13.1.orig/src/cfgparse.c 2007-11-03 23:57:29.000000000 -0700 +++ haproxy-1.3.13.1/src/cfgparse.c 2007-12-04 14:55:55.000000000 -0800 @@ -415,7 +415,7 @@ global.pidfile = strdup(args[1]); } else if (!strcmp(args[0], "log")) { /* syslog server address */ - struct sockaddr_in *sa; + struct logsrv logsrv; int facility, level; if (*(args[1]) == 0 || *(args[2]) == 0) { @@ -438,17 +438,23 @@ } } - sa = str2sa(args[1]); - if (!sa->sin_port) - sa->sin_port = htons(SYSLOG_PORT); + if (args[1][0] == '/') { + logsrv.u.addr.sa_family = AF_UNIX; + logsrv.u.un = *str2sun(args[1]); + } else { + logsrv.u.addr.sa_family = AF_INET; + logsrv.u.in = *str2sa(args[1]); + if (!logsrv.u.in.sin_port) + logsrv.u.in.sin_port = htons(SYSLOG_PORT); + } if (global.logfac1 == -1) { - global.logsrv1 = *sa; + global.logsrv1 = logsrv; global.logfac1 = facility; global.loglev1 = level; } else if (global.logfac2 == -1) { - global.logsrv2 = *sa; + global.logsrv2 = logsrv; global.logfac2 = facility; global.loglev2 = level; } @@ -1559,7 +1565,7 @@ curproxy->srv_act++; } else if (!strcmp(args[0], "log")) { /* syslog server address */ - struct sockaddr_in *sa; + struct logsrv logsrv; int facility; if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) { @@ -1588,17 +1594,25 @@ } } - sa = str2sa(args[1]); - if (!sa->sin_port) - sa->sin_port = htons(SYSLOG_PORT); + if (args[1][0] == '/') { + logsrv.u.addr.sa_family = AF_UNIX; + logsrv.u.un = *str2sun(args[1]); + } else { + logsrv.u.addr.sa_family = AF_INET; + logsrv.u.in = *str2sa(args[1]); + if (!logsrv.u.in.sin_port) { + logsrv.u.in.sin_port = + htons(SYSLOG_PORT); + } + } if (curproxy->logfac1 == -1) { - curproxy->logsrv1 = *sa; + curproxy->logsrv1 = logsrv; curproxy->logfac1 = facility; curproxy->loglev1 = level; } else if (curproxy->logfac2 == -1) { - curproxy->logsrv2 = *sa; + curproxy->logsrv2 = logsrv; curproxy->logfac2 = facility; curproxy->loglev2 = level; } diff -ru haproxy-1.3.13.1.orig/src/log.c haproxy-1.3.13.1/src/log.c --- haproxy-1.3.13.1.orig/src/log.c 2007-11-03 23:57:29.000000000 -0700 +++ haproxy-1.3.13.1/src/log.c 2007-12-04 16:43:53.000000000 -0800 @@ -17,6 +17,7 @@ #include #include #include +#include #include @@ -29,6 +30,9 @@ #include #include +#ifndef MSG_NOSIGNAL +#define MSG_NOSIGNAL (0) +#endif /* !MSG_NOSIGNAL */ const char *log_facilities[NB_LOG_FACILITIES] = { "kern", "user", "mail", "daemon", @@ -139,6 +143,32 @@ return facility; } +/* + * Return the length of the address endpoint, suitable for use with sendto(). + */ +int logsrv_addrlen(const struct logsrv *logsrv) +{ +#ifdef __SOCKADDR_COMMON + switch (logsrv->u.addr.sa_family) { + case AF_UNIX: + return sizeof(logsrv->u.un); + case AF_INET: + return sizeof(logsrv->u.in); + default: + break; + } +#else /* !__SOCKADDR_COMMON */ + switch (logsrv->u.addr.sa_family) { + case AF_UNIX: + return logsrv->u.un.sun_len; + case AF_INET: + return logsrv->u.in.sin_len; + default: + break; + } +#endif /* !__SOCKADDR_COMMON */ + return -1; +} /* * This function sends a syslog message to both log servers of a proxy, @@ -148,26 +178,19 @@ */ void send_log(struct proxy *p, int level, const char *message, ...) { - static int logfd = -1; /* syslog UDP socket */ + static int logfds[2] = { -1, -1 }; /* syslog sockets */ static long tvsec = -1; /* to force the string to be initialized */ va_list argp; static char logmsg[MAX_SYSLOG_LEN]; static char *dataptr = NULL; int fac_level; int hdr_len, data_len; - struct sockaddr_in *sa[2]; + struct logsrv *logsrvs[2]; int facilities[2], loglevel[2]; + int nblogger; int nbloggers = 0; char *log_ptr; - if (logfd < 0) { - if ((logfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) - return; - /* we don't want to receive anything on this socket */ - setsockopt(logfd, SOL_SOCKET, SO_RCVBUF, &zero, sizeof(zero)); - shutdown(logfd, SHUT_RD); /* does nothing under Linux, maybe needed for others */ - } - if (level < 0 || progname == NULL || message == NULL) return; @@ -206,35 +229,60 @@ if (p == NULL) { if (global.logfac1 >= 0) { - sa[nbloggers] = &global.logsrv1; + logsrvs[nbloggers] = &global.logsrv1; facilities[nbloggers] = global.logfac1; loglevel[nbloggers] = global.loglev1; nbloggers++; } if (global.logfac2 >= 0) { - sa[nbloggers] = &global.logsrv2; + logsrvs[nbloggers] = &global.logsrv2; facilities[nbloggers] = global.logfac2; loglevel[nbloggers] = global.loglev2; nbloggers++; } } else { if (p->logfac1 >= 0) { - sa[nbloggers] = &p->logsrv1; + logsrvs[nbloggers] = &p->logsrv1; facilities[nbloggers] = p->logfac1; loglevel[nbloggers] = p->loglev1; nbloggers++; } if (p->logfac2 >= 0) { - sa[nbloggers] = &p->logsrv2; + logsrvs[nbloggers] = &p->logsrv2; facilities[nbloggers] = p->logfac2; loglevel[nbloggers] = p->loglev2; nbloggers++; } } - while (nbloggers-- > 0) { + for (nblogger = 0; nblogger < nbloggers; nblogger++) { + if (logfds[nblogger] < 0) { + const struct logsrv *logsrv = logsrvs[nblogger]; + int proto = logsrv->u.addr.sa_family == AF_UNIX ? 0 : + IPPROTO_UDP; + int logfd; + if ((logfd = socket(logsrv->u.addr.sa_family, + SOCK_DGRAM, proto)) < 0) { + Alert("socket failed: %s (errno=%d)\n", + strerror(errno), errno); + return; + } + /* we don't want to receive anything on this socket */ + setsockopt(logfd, SOL_SOCKET, SO_RCVBUF, + &zero, sizeof(zero)); + /* does nothing under Linux, maybe needed for others */ + shutdown(logfd, SHUT_RD); + logfds[nblogger] = logfd; + } + } + + for (nblogger = 0; nblogger < nbloggers; nblogger++) { + const struct logsrv *logsrv = logsrvs[nblogger]; + int logfd = logfds[nblogger]; + int sent; + /* we can filter the level of the messages that are sent to each logger */ - if (level > loglevel[nbloggers]) + if (level > loglevel[nblogger]) continue; /* For each target, we may have a different facility. @@ -244,7 +292,7 @@ * time, we only change the facility in the pre-computed header, * and we change the pointer to the header accordingly. */ - fac_level = (facilities[nbloggers] << 3) + level; + fac_level = (facilities[nblogger] << 3) + level; log_ptr = logmsg + 3; /* last digit of the log level */ do { *log_ptr = '0' + fac_level % 10; @@ -254,14 +302,12 @@ *log_ptr = '<'; /* the total syslog message now starts at logptr, for dataptr+data_len-logptr */ - -#ifndef MSG_NOSIGNAL - sendto(logfd, log_ptr, dataptr + data_len - log_ptr, MSG_DONTWAIT, - (struct sockaddr *)sa[nbloggers], sizeof(**sa)); -#else - sendto(logfd, log_ptr, dataptr + data_len - log_ptr, MSG_DONTWAIT | MSG_NOSIGNAL, - (struct sockaddr *)sa[nbloggers], sizeof(**sa)); -#endif + sent = sendto(logfd, log_ptr, dataptr + data_len - log_ptr, + MSG_DONTWAIT | MSG_NOSIGNAL, &logsrv->u.addr, logsrv_addrlen(logsrv)); + if (sent < 0) { + Alert("sendto failed: %s (errno=%d)\n", + strerror(errno), errno); + } } } diff -ru haproxy-1.3.13.1.orig/src/proxy.c haproxy-1.3.13.1/src/proxy.c --- haproxy-1.3.13.1.orig/src/proxy.c 2007-11-03 23:57:29.000000000 -0700 +++ haproxy-1.3.13.1/src/proxy.c 2007-12-04 14:34:42.000000000 -0800 @@ -12,6 +12,7 @@ #include #include +#include #include #include #include diff -ru haproxy-1.3.13.1.orig/src/standard.c haproxy-1.3.13.1/src/standard.c --- haproxy-1.3.13.1.orig/src/standard.c 2007-11-03 23:57:29.000000000 -0700 +++ haproxy-1.3.13.1/src/standard.c 2007-12-04 16:52:45.000000000 -0800 @@ -82,6 +82,37 @@ return 0; } +/* + * converts to a struct sockaddr_un* which is locally allocated. + * The format is "/path", where "/path" is a path to a UNIX domain socket. + */ +struct sockaddr_un *str2sun(char *str) +{ + static struct sockaddr_un sun; + int strsz; /* length included null */ + + memset(&sun, 0, sizeof(sun)); + str = strdup(str); + if (str == NULL) + goto out_nofree; + + strsz = strlen(str) + 1; + if (strsz > sizeof(sun.sun_path)) { + Alert("Socket path '%s' too long (max %d)\n", + str, sizeof(sun.sun_path) - 1); + goto out_nofree; + } + +#ifndef __SOCKADDR_COMMON + sun.sun_len = sizeof(sun); +#endif /* !__SOCKADDR_COMMON */ + sun.sun_family = AF_UNIX; + memcpy(sun.sun_path, str, strsz); + + free(str); + out_nofree: + return &sun; +} /* * converts to a struct sockaddr_in* which is locally allocated. @@ -118,6 +149,9 @@ else sa.sin_addr = *(struct in_addr *) *(he->h_addr_list); } +#ifndef __SOCKADDR_COMMON + sa.sin_len = sizeof(sa); +#endif /* !__SOCKADDR_COMMON */ sa.sin_port = htons(port); sa.sin_family = AF_INET;