Submitted By: Robert Connolly (ashes) Date: 2007-05-25 Initial Package Version: 1.4.1 Upstream Status: Not Submitted Origin: sysklogd-1.4.2-2.fc7's sysklogd-1.4.2rh.tar.gz sysklogd-1.4.2rh.timezone.patch Parts of sysklogd-1.4.2-rh-alt-warnings.patch sysklogd-1.4.2-owl-syslogd-doexit.patch Description: This is over a dozen patches rolled in one. It becomes too complicated to keep these patches separate, because eventually they need to be installed in order, and then there's no point in keeping them separate. This is why Fedora created their own tarball. This patch includes various upstream and community bug fixes and enhancements, including sparc and alpha fixes. The changelog would double the size of this patch, and most of it has very little details, so I didn't include it. After applying the sysklogd-1.4.2rh.diff I: rm kernel.patch rm -rf redhat/ rm sysklogd.spec cp ../sysklogd-1.4.1.orig/Makefile Makefile Then I edited Makefile with -DINET6 and -D_GNU_SOURCE, etc. Use 'make COPTS=' to set your own cflags. I also fixed '#undef *syslog', chdir(2), and write(2), to supress GCC warnings. diff -Naur sysklogd-1.4.1.orig/Makefile sysklogd-1.4.1/Makefile --- sysklogd-1.4.1.orig/Makefile 1998-10-12 20:25:15.000000000 +0000 +++ sysklogd-1.4.1/Makefile 2007-05-25 06:10:06.000000000 +0000 @@ -1,10 +1,12 @@ # Makefile for syslogd and klogd daemons. CC= gcc -#CFLAGS= -g -DSYSV -Wall -#LDFLAGS= -g -CFLAGS= $(RPM_OPT_FLAGS) -O3 -DSYSV -fomit-frame-pointer -Wall -fno-strength-reduce -LDFLAGS= -s +# COPTS_SSP= -fstack-protector-all --param=ssp-buffer-size=4 -Wstack-protector +# COPTS_EXTRA= -D_FORTIFY_SOURCE=2 -fPIE +COPTS= -g -O2 -fomit-frame-pointer ${COPTS_SSP} ${COPTS_EXTRA} +CFLAGS= -DSYSV -DINET6 -D_GNU_SOURCE -std=gnu99 -Wall -Wformat -Wformat-security -Werror ${COPTS} +# LDFLAGS_EXTRA= -pie -z now -z relro -z combreloc +LDFLAGS= ${LDFLAGS_EXTRA} # Look where your install program is. INSTALL = /usr/bin/install @@ -25,7 +27,7 @@ # Define the following to impart start-up delay in klogd. This is # useful if klogd is started simultaneously or in close-proximity to syslogd. -# KLOGD_START_DELAY = -DKLOGD_DELAY=5 +KLOGD_START_DELAY = -DKLOGD_DELAY=1 # The following define determines whether the package adheres to the # file system standard. @@ -44,7 +46,7 @@ # ballot below. SYSLOGD_PIDNAME = -DSYSLOGD_PIDNAME=\"syslogd.pid\" -SYSLOGD_FLAGS= -DSYSLOG_INET -DSYSLOG_UNIXAF -DNO_SCCS ${FSSTND} \ +SYSLOGD_FLAGS= -DSYSLOG_INET -DINET6 -DSYSLOG_UNIXAF -DNO_SCCS ${FSSTND} \ ${SYSLOGD_PIDNAME} SYSLOG_FLAGS= -DALLOW_KERNEL_LOGGING KLOGD_FLAGS = ${FSSTND} ${KLOGD_START_DELAY} @@ -106,14 +108,14 @@ ${CC} ${CFLAGS} -DTEST -o ksym_test.o -c ksym.c clean: - rm -f *.o *.log *~ *.orig + rm -f *.o *.log *~ *.orig syslogd klogd clobber: clean rm -f syslogd klogd ksym syslog_tst oops_test TAGS tsyslogd tklogd install_exec: syslogd klogd - ${INSTALL} -m 500 -s syslogd ${BINDIR}/syslogd - ${INSTALL} -m 500 -s klogd ${BINDIR}/klogd + ${INSTALL} -m 500 syslogd ${BINDIR}/syslogd + ${INSTALL} -m 500 klogd ${BINDIR}/klogd install_man: ${INSTALL} -o ${MAN_OWNER} -g ${MAN_OWNER} -m 644 sysklogd.8 ${MANDIR}/man8/sysklogd.8 diff -Naur sysklogd-1.4.1.orig/klogd.c sysklogd-1.4.1/klogd.c --- sysklogd-1.4.1.orig/klogd.c 2001-03-11 19:40:10.000000000 +0000 +++ sysklogd-1.4.1/klogd.c 2007-05-25 05:59:23.000000000 +0000 @@ -275,6 +275,10 @@ #define ksyslog klogctl #endif +#ifndef _PATH_KLOG +#define _PATH_KLOG "/proc/kmsg" +#endif + #define LOG_BUFFER_SIZE 4096 #define LOG_LINE_LENGTH 1000 @@ -291,7 +295,7 @@ terminate = 0, caught_TSTP = 0, reload_symbols = 0, - console_log_level = -1; + console_log_level = 6; static int use_syscall = 0, one_shot = 0, @@ -509,8 +513,7 @@ /* Set level of kernel console messaging.. */ - if ( (console_log_level != -1) - && (ksyslog(8, NULL, console_log_level) < 0) && \ + if ( (ksyslog(8, NULL, console_log_level) < 0) && \ (errno == EINVAL) ) { /* @@ -738,7 +741,7 @@ switch( parse_state ) { case PARSING_TEXT: - delta = copyin( line, space, ptr, len, "\n[%" ); + delta = copyin( line, space, ptr, len, "\n[" ); line += delta; ptr += delta; space -= delta; @@ -794,30 +797,9 @@ parse_state = PARSING_SYMSTART; /* at < */ break; } - if( *ptr == '%' ) /* dangerous printf marker */ - { - delta = 0; - while (len && *ptr == '%') - { - *line++ = *ptr++; /* copy it in */ - space -= 1; - len -= 1; - delta++; - } - if (delta % 2) /* odd amount of %'s */ - { - if (space) - { - *line++ = '%'; /* so simply add one */ - space -= 1; - } - else - { - *line++ = '\0'; /* remove the last one / terminate the string */ - } - - } - } + /* Now that line_buff is no longer fed to *printf as format + * string, '%'s are no longer "dangerous". + */ break; case PARSING_SYMSTART: @@ -887,8 +869,7 @@ value = strtoul(sym_start+1, (char **) 0, 16); *(line-1) = '>'; /* put back delim */ - symbol = LookupSymbol(value, &sym); - if ( !symbol_lookup || symbol == (char *) 0 ) + if ( !symbol_lookup || (symbol = LookupSymbol(value, &sym)) == (char *)0 ) { parse_state = PARSING_TEXT; break; @@ -938,7 +919,7 @@ * messages into this fresh buffer. */ memset(log_buffer, '\0', sizeof(log_buffer)); - if ( (rdcnt = ksyslog(2, log_buffer, sizeof(log_buffer))) < 0 ) + if ( (rdcnt = ksyslog(2, log_buffer, sizeof(log_buffer)-1)) < 0 ) { if ( errno == EINTR ) return; @@ -965,10 +946,14 @@ memset(log_buffer, '\0', sizeof(log_buffer)); if ( (rdcnt = read(kmsg, log_buffer, sizeof(log_buffer)-1)) < 0 ) { + int saved_errno = errno; + if ( errno == EINTR ) return; Syslog(LOG_ERR, "Cannot read proc file system: %d - %s.", \ errno, strerror(errno)); + if ( saved_errno == EPERM ) + Terminate(); } else LogLine(log_buffer, rdcnt); @@ -991,7 +976,10 @@ *output = (char *) 0; #ifndef TESTING - chdir ("/"); + if (chdir("/") != 0) { + fprintf(stderr, "klogd: chdir to / failed: %m"); + exit (1); + } #endif /* Parse the command-line. */ while ((ch = getopt(argc, argv, "c:df:iIk:nopsvx2")) != EOF) @@ -1143,8 +1131,11 @@ if ( one_shot ) { if (symbol_lookup) { - InitKsyms(symfile); - InitMsyms(); + symbol_lookup = (InitKsyms(symfile) == 1); + symbol_lookup |= InitMsyms(); + if (symbol_lookup == 0) { + Syslog(LOG_WARNING, "cannot find any symbols, turning off symbol lookups\n"); + } } if ( (logsrc = GetKernelLogSrc()) == kernel ) LogKernelLine(); @@ -1159,8 +1150,11 @@ #endif logsrc = GetKernelLogSrc(); if (symbol_lookup) { - InitKsyms(symfile); - InitMsyms(); + symbol_lookup = (InitKsyms(symfile) == 1); + symbol_lookup |= InitMsyms(); + if (symbol_lookup == 0) { + Syslog(LOG_WARNING, "cannot find any symbols, turning off symbol lookups\n"); + } } /* The main loop. */ diff -Naur sysklogd-1.4.1.orig/klogd.h sysklogd-1.4.1/klogd.h --- sysklogd-1.4.1.orig/klogd.h 1997-06-13 09:35:54.000000000 +0000 +++ sysklogd-1.4.1/klogd.h 2007-05-25 05:59:23.000000000 +0000 @@ -31,6 +31,12 @@ #include #include +#ifdef syslog +#undef syslog /* Use internal version. */ +#endif +#ifdef vsyslog +#undef vsyslog /* Ditto. */ +#endif /* Function prototypes. */ extern int InitKsyms(char *); @@ -38,3 +44,6 @@ extern char * ExpandKadds(char *, char *); extern void SetParanoiaLevel(int); extern void Syslog(int priority, char *fmt, ...); +extern void syslog(int pri, const char *fmt, ...); +extern void vsyslog(int pri, const char *fmt, va_list ap); +extern void openlog(const char *ident, int logstat, int logfac); diff -Naur sysklogd-1.4.1.orig/ksym.c sysklogd-1.4.1/ksym.c --- sysklogd-1.4.1.orig/ksym.c 2000-09-12 21:53:31.000000000 +0000 +++ sysklogd-1.4.1/ksym.c 2007-05-25 05:59:23.000000000 +0000 @@ -112,6 +112,7 @@ #include #include #include +#include #include "klogd.h" #include "ksyms.h" @@ -344,6 +345,7 @@ if ( (sym_file = fopen(symfile, "r")) != (FILE *) 0 ) { if (CheckMapVersion(symfile) == 1) file = symfile; + fclose(sym_file); } if (sym_file == (FILE *) 0 || file == (char *) 0) { sprintf (symfile, "%s", *mf); @@ -352,6 +354,7 @@ if ( (sym_file = fopen(symfile, "r")) != (FILE *) 0 ) { if (CheckMapVersion(symfile) == 1) file = symfile; + fclose(sym_file); } } @@ -770,6 +773,84 @@ if ( (num_syms == 0) || (kp = strstr(line, "[<")) == (char *) 0 ) { +#ifdef __sparc__ + if (num_syms) { + /* + * On SPARC, register dumps do not have the [< >] characters in it. + */ + static struct sparc_tests { + char *str; + int len; + } tests[] = { { "PC: ", 4 }, + { " o7: ", 5 }, + { " ret_pc: ", 9 }, + { " i7: ", 5 }, + { "Caller[", 7 } + }; + int i, j, ndigits; + char *kp2; + for (i = 0; i < 5; i++) { + kp = strstr(line, tests[i].str); + if (!kp) continue; + kp2 = kp + tests[i].len; + if (!isxdigit(*kp2)) continue; + for (ndigits = 1; isxdigit(kp2[ndigits]); ndigits++); + if (ndigits != 8 && ndigits != 16) continue; + /* On sparc64, all kernel addresses are in first 4GB */ + if (ndigits == 16) { + if (strncmp (kp2, "00000000", 8)) continue; + kp2 += 8; + } + if (!i) { + char *kp3; + if (ndigits == 16 && kp > line && kp[-1L] != 'T') continue; + kp3 = kp2 + 8; + if (ndigits == 16) { + if (strncmp (kp3, " TNPC: 00000000", 15) || !isxdigit(kp3[15])) + continue; + kp3 += 15; + } else { + if (strncmp (kp3, " NPC: ", 6) || !isxdigit(kp3[6])) + continue; + kp3 += 6; + } + for (j = 0; isxdigit(kp3[j]); j++); + if (j != 8) continue; + strncpy(elp, line, kp2 + 8 - line); + elp += kp2 + 8 - line; + value = strtol(kp2, (char **) 0, 16); + if ( (symbol = LookupSymbol(value, &sym)) ) { + if (sym.size) + elp += sprintf(elp, " (%s+%d/%d)", symbol, sym.offset, sym.size); + else + elp += sprintf(elp, " (%s)", symbol); + } + strncpy(elp, kp2 + 8, kp3 - kp2); + elp += kp3 - kp2; + value = strtol(kp3, (char **) 0, 16); + if ( (symbol = LookupSymbol(value, &sym)) ) { + if (sym.size) + elp += sprintf(elp, " (%s+%d/%d)", symbol, sym.offset, sym.size); + else + elp += sprintf(elp, " (%s)", symbol); + } + strcpy(elp, kp3 + 8); + } else { + strncpy(elp, line, kp2 + 8 - line); + elp += kp2 + 8 - line; + value = strtol(kp2, (char **) 0, 16); + if ( (symbol = LookupSymbol(value, &sym)) ) { + if (sym.size) + elp += sprintf(elp, " (%s+%d/%d)", symbol, sym.offset, sym.size); + else + elp += sprintf(elp, " (%s)", symbol); + } + strcpy(elp, kp2 + 8); + } + return el; + } + } +#endif strcpy(el, line); return(el); } diff -Naur sysklogd-1.4.1.orig/ksym_mod.c sysklogd-1.4.1/ksym_mod.c --- sysklogd-1.4.1.orig/ksym_mod.c 2000-09-12 21:15:28.000000000 +0000 +++ sysklogd-1.4.1/ksym_mod.c 2007-05-25 05:59:23.000000000 +0000 @@ -93,7 +93,7 @@ #include #include #else /* __GLIBC__ */ -#include +#include "module.h" extern __off64_t lseek64 __P ((int __fd, __off64_t __offset, int __whence)); extern int get_kernel_syms __P ((struct kernel_sym *__table)); #endif /* __GLIBC__ */ diff -Naur sysklogd-1.4.1.orig/module.h sysklogd-1.4.1/module.h --- sysklogd-1.4.1.orig/module.h 1970-01-01 00:00:00.000000000 +0000 +++ sysklogd-1.4.1/module.h 2007-05-25 05:59:23.000000000 +0000 @@ -0,0 +1,62 @@ + +/* Module definitions for klogd's module support */ +struct kernel_sym +{ + unsigned long value; + char name[60]; +}; + +struct module_symbol +{ + unsigned long value; + const char *name; +}; + +struct module_ref +{ + struct module *dep; /* "parent" pointer */ + struct module *ref; /* "child" pointer */ + struct module_ref *next_ref; +}; + +struct module_info +{ + unsigned long addr; + unsigned long size; + unsigned long flags; + long usecount; +}; + + +typedef struct { volatile int counter; } atomic_t; + +struct module +{ + unsigned long size_of_struct; /* == sizeof(module) */ + struct module *next; + const char *name; + unsigned long size; + + union + { + atomic_t usecount; + long pad; + } uc; /* Needs to keep its size - so says rth */ + + unsigned long flags; /* AUTOCLEAN et al */ + + unsigned nsyms; + unsigned ndeps; + + struct module_symbol *syms; + struct module_ref *deps; + struct module_ref *refs; + int (*init)(void); + void (*cleanup)(void); + const struct exception_table_entry *ex_table_start; + const struct exception_table_entry *ex_table_end; +#ifdef __alpha__ + unsigned long gp; +#endif +}; + diff -Naur sysklogd-1.4.1.orig/pidfile.c sysklogd-1.4.1/pidfile.c --- sysklogd-1.4.1.orig/pidfile.c 1998-02-10 22:37:12.000000000 +0000 +++ sysklogd-1.4.1/pidfile.c 2007-05-25 05:59:23.000000000 +0000 @@ -25,6 +25,7 @@ */ #include +#include #include #include #include @@ -41,11 +42,15 @@ int read_pid (char *pidfile) { FILE *f; - int pid; + char pidbuf[7]; /* 'kernel.pid_max = 32768', 5 digits. 7 is plenty. */ + pid_t pid=0; if (!(f=fopen(pidfile,"r"))) return 0; - fscanf(f,"%d", &pid); + + if (fgets(pidbuf, sizeof(pidbuf), f) != NULL) { + pid = atol(pidbuf); + } fclose(f); return pid; } @@ -85,7 +90,8 @@ { FILE *f; int fd; - int pid; + char pidbuf[7]; /* 'kernel.pid_max = 32768', 5 digits. 7 is plenty. */ + pid_t pid=0; if ( ((fd = open(pidfile, O_RDWR|O_CREAT, 0644)) == -1) || ((f = fdopen(fd, "r+")) == NULL) ) { @@ -94,7 +100,9 @@ } if (flock(fd, LOCK_EX|LOCK_NB) == -1) { - fscanf(f, "%d", &pid); + if (fgets(pidbuf, sizeof(pidbuf), f) != NULL) { + pid = atol(pidbuf); + } fclose(f); printf("Can't lock, lock is held by pid %d.\n", pid); return 0; diff -Naur sysklogd-1.4.1.orig/sysklogd.8 sysklogd-1.4.1/sysklogd.8 --- sysklogd-1.4.1.orig/sysklogd.8 2001-03-11 19:35:51.000000000 +0000 +++ sysklogd-1.4.1/sysklogd.8 2007-05-25 05:59:23.000000000 +0000 @@ -7,6 +7,7 @@ sysklogd \- Linux system logging utilities. .SH SYNOPSIS .B syslogd +.RB [ " \-46A " ] .RB [ " \-a " .I socket ] @@ -30,6 +31,7 @@ .I domainlist ] .RB [ " \-v " ] +.RB [ " \-x " ] .LP .SH DESCRIPTION .B Sysklogd @@ -74,6 +76,26 @@ .LP .SH OPTIONS .TP +.BI "\-4" +Force +.B syslogd +to use IPv4 addresses only. +.TP +.BI "\-6" +Force +.B syslogd +to use IPv6 addresses only. +.TP +.BI "\-A" +Ordinarily, +.B syslogd +tries to send the message to only one address +even if the host has more than one A or AAAA record. If this +option is specified, +.B syslogd +tries to send the message to all +addresses. +.TP .BI "\-a " "socket" Using this argument you can specify additional sockets from that .B syslogd @@ -152,6 +174,11 @@ .TP .B "\-v" Print version and exit. +.TP +.B "\-x" +Disable name lookups when receiving remote messages. +This avoids deadlocks when the nameserver is running on +the same machine that runs the syslog daemon. .LP .SH SIGNALS .B Syslogd diff -Naur sysklogd-1.4.1.orig/syslog.c sysklogd-1.4.1/syslog.c --- sysklogd-1.4.1.orig/syslog.c 2001-03-11 19:35:51.000000000 +0000 +++ sysklogd-1.4.1/syslog.c 2007-05-25 05:59:23.000000000 +0000 @@ -54,11 +54,6 @@ #include #include #include -#if 0 -#include "syslog.h" -#include "pathnames.h" -#endif - #include #include #include @@ -70,6 +65,13 @@ #include #include +#ifdef syslog +#undef syslog /* Use internal version. */ +#endif +#ifdef vsyslog +#undef vsyslog /* Ditto. */ +#endif + #define _PATH_LOGNAME "/dev/log" static int LogFile = -1; /* fd for log */ @@ -179,7 +181,10 @@ (void)strcat(tbuf, "\r\n"); cnt += 2; p = index(tbuf, '>') + 1; - (void)write(fd, p, cnt - (p - tbuf)); + if (write(fd, p, cnt - (p - tbuf)) == -1) { + (void)close(fd); + return; + } (void)close(fd); } diff -Naur sysklogd-1.4.1.orig/syslog_tst.c sysklogd-1.4.1/syslog_tst.c --- sysklogd-1.4.1.orig/syslog_tst.c 1997-06-02 17:21:41.000000000 +0000 +++ sysklogd-1.4.1/syslog_tst.c 2007-05-25 05:59:23.000000000 +0000 @@ -42,7 +42,7 @@ if ( (nl = strrchr(bufr, '\n')) != \ (char *) 0) *nl = '\0'; - syslog(LOG_INFO, bufr); + syslog(LOG_INFO, "%s", bufr); logged += strlen(bufr); if ( logged > 1024 ) { @@ -54,7 +54,7 @@ } else while (argc-- > 1) - syslog(LOG_INFO, argv++[1]); + syslog(LOG_INFO, "%s", argv++[1]); } else { diff -Naur sysklogd-1.4.1.orig/syslogd.c sysklogd-1.4.1/syslogd.c --- sysklogd-1.4.1.orig/syslogd.c 2001-03-11 19:40:10.000000000 +0000 +++ sysklogd-1.4.1/syslogd.c 2007-05-25 05:59:23.000000000 +0000 @@ -441,6 +441,15 @@ * Don't return a closed fd if `-a' is called with a wrong path. * Thanks to Bill Nottingham for providing * a patch. + * Wed Dec 1 18:00:00 EST 2004: Jason Vas Dias + * Use 'siginterrupt(SIGALRM,1)' after each 'signal(SIGALRM,domark)' + * else recvfrom(...) will never be interrupted + * (bugzilla #141983) + * + * Thu Dec 1 11:00:00 EST 2004: Jason Vas Dias + * Don't allow remote logging host targets like '@localhost' + * (or any name that resolves to the address of a local interface)!! + * */ @@ -491,6 +500,8 @@ #include #include #include +#include + #ifndef TESTING #include "pidfile.h" #endif @@ -555,10 +566,11 @@ char **parts; -int inetm = 0; static int debugging_on = 0; static int nlogs = -1; static int restart = 0; +static int alarm_signal = 0; +static int exit_on_signal = 0; #define MAXFUNIX 20 @@ -613,22 +625,23 @@ short f_type; /* entry type, see below */ short f_file; /* file descriptor */ time_t f_time; /* time this was last written */ + char *f_host; /* host from which to recd. */ u_char f_pmask[LOG_NFACILITIES+1]; /* priority mask */ union { char f_uname[MAXUNAMES][UNAMESZ+1]; struct { - char f_hname[MAXHOSTNAMELEN+1]; - struct sockaddr_in f_addr; + char f_hname[MAXHOSTNAMELEN]; + struct addrinfo *f_addr; } f_forw; /* forwarding address */ char f_fname[MAXFNAME]; } f_un; char f_prevline[MAXSVLINE]; /* last message logged */ char f_lasttime[16]; /* time of last occurrence */ - char f_prevhost[MAXHOSTNAMELEN+1]; /* host from which recd. */ + char f_prevhost[MAXHOSTNAMELEN]; /* host from which recd. */ int f_prevpri; /* pri of f_prevline */ int f_prevlen; /* length of f_prevline */ int f_prevcount; /* repetition cnt of prevline */ - int f_repeatcount; /* number of "repeated" msgs */ + u_int f_repeatcount; /* number of "repeated" msgs */ int f_flags; /* store some additional flags */ }; @@ -637,8 +650,8 @@ * in seconds after previous message is logged. After each flush, * we move to the next interval until we reach the largest. */ -int repeatinterval[] = { 30, 60 }; /* # of secs before flush */ -#define MAXREPEAT ((sizeof(repeatinterval) / sizeof(repeatinterval[0])) - 1) +time_t repeatinterval[] = { 30, 60 }; /* # of secs before flush */ +#define MAXREPEAT ((int) ((sizeof(repeatinterval) / sizeof(repeatinterval[0])) - 1)) #define REPEATTIME(f) ((f)->f_time + repeatinterval[(f)->f_repeatcount]) #define BACKOFF(f) { if (++(f)->f_repeatcount > MAXREPEAT) \ (f)->f_repeatcount = MAXREPEAT; \ @@ -721,15 +734,22 @@ }; int Debug; /* debug flag */ -char LocalHostName[MAXHOSTNAMELEN+1]; /* our hostname */ -char *LocalDomain; /* our local domain name */ +int resolve = 1; /* resolve hostname */ +char LocalHostName[MAXHOSTNAMELEN]; /* our hostname */ +const char *LocalDomain; /* our local domain name */ int InetInuse = 0; /* non-zero if INET sockets are being used */ -int finet = -1; /* Internet datagram socket */ -int LogPort; /* port number for INET connections */ +int * finet = NULL; /* Internet datagram socket */ int Initialized = 0; /* set when we have initialized ourselves */ int MarkInterval = 20 * 60; /* interval between marks in seconds */ +#ifdef INET6 +int family = PF_UNSPEC; /* protocol family (IPv4, IPv6 or both) */ +#else +int family = PF_INET; /* protocol family (IPv4 only) */ +#endif +int send_to_all = 0; /* send message to all IPv4/IPv6 addresses */ int MarkSeq = 0; /* mark sequence number */ int NoFork = 0; /* don't fork - don't run in daemon mode */ +int DisableDNS = 0; /* don't look up IP addresses of incoming messages */ int AcceptRemote = 0; /* receive messages that come via UDP */ char **StripDomains = NULL; /* these domains may be stripped before writing logs */ char **LocalHosts = NULL; /* these hosts are logged with their hostname */ @@ -743,7 +763,7 @@ char **crunch_list(char *list); int usage(void); void untty(void); -void printchopped(const char *hname, char *msg, int len, int fd); +void printchopped(const char *hname, char *msg, size_t len, int fd); void printline(const char *hname, char *msg); void printsys(char *msg); void logmsg(int pri, char *msg, const char *from, int flags); @@ -751,11 +771,14 @@ void endtty(); void wallmsg(register struct filed *f, struct iovec *iov); void reapchild(); -const char *cvthname(struct sockaddr_in *f); +const char *cvthname(struct sockaddr_storage *f); void domark(); +void alarm_handler(int sig); void debug_switch(); -void logerror(char *type); +void logerror(const char *type); void die(int sig); +static void free_host_ai_list( struct addrinfo *ai ); +void exit_signal_handler(int sig); #ifndef TESTING void doexit(int sig); #endif @@ -773,9 +796,13 @@ static int create_unix_socket(const char *path); #endif #ifdef SYSLOG_INET -static int create_inet_socket(); +static int * create_inet_sockets(); #endif +static struct addrinfo *host_ai_list( char *host ); +static int hosts_equal(struct addrinfo *ai1, struct addrinfo *ai2); +static struct addrinfo *not_local_address( char *host ); + int main(argc, argv) int argc; char **argv; @@ -786,7 +813,7 @@ int len, num_fds; #else /* __GLIBC__ */ #ifndef TESTING - size_t len; + socklen_t len; #endif int num_fds; #endif /* __GLIBC__ */ @@ -808,12 +835,13 @@ #ifndef TESTING int fd; #ifdef SYSLOG_INET - struct sockaddr_in frominet; - char *from; + struct sockaddr_storage frominet; + const char *from; #endif pid_t ppid = getpid(); #endif int ch; + int l; struct hostent *hent; char line[MAXLINE +1]; @@ -822,15 +850,29 @@ int maxfds; #ifndef TESTING - chdir ("/"); + if (chdir("/") != 0) { + fprintf(stderr, "klogd: chdir to / failed: %m"); + exit (1); + } #endif for (i = 1; i < MAXFUNIX; i++) { funixn[i] = ""; funix[i] = -1; } - while ((ch = getopt(argc, argv, "a:dhf:l:m:np:rs:v")) != EOF) + while ((ch = getopt(argc, argv, "46Aa:dhf:l:m:np:rs:vx")) != EOF) switch((char)ch) { + case '4': + family = PF_INET; + break; +#ifdef INET6 + case '6': + family = PF_INET6; + break; +#endif + case 'A': + send_to_all++; + break; case 'a': if (nfunix < MAXFUNIX) funixn[nfunix++] = optarg; @@ -877,6 +919,9 @@ case 'v': printf("syslogd %s.%s\n", VERSION, PATCHLEVEL); exit (0); + case 'x': + DisableDNS = 1; + break; case '?': default: usage(); @@ -890,11 +935,11 @@ dprintf("Checking pidfile.\n"); if (!check_pid(PidFile)) { + signal (SIGTERM, doexit); if (fork()) { /* * Parent process */ - signal (SIGTERM, doexit); sleep(300); /* * Not reached unless something major went wrong. 5 @@ -906,6 +951,7 @@ */ exit(1); } + signal (SIGTERM, SIG_DFL); num_fds = getdtablesize(); for (i= 0; i < num_fds; i++) (void) close(i); @@ -986,14 +1032,26 @@ if (isupper(*p)) *p = tolower(*p); - (void) signal(SIGTERM, die); - (void) signal(SIGINT, Debug ? die : SIG_IGN); - (void) signal(SIGQUIT, Debug ? die : SIG_IGN); + (void) signal(SIGTERM, exit_signal_handler); + (void) signal(SIGINT, Debug ? exit_signal_handler : SIG_IGN); + (void) signal(SIGQUIT, Debug ? exit_signal_handler : SIG_IGN); (void) signal(SIGCHLD, reapchild); - (void) signal(SIGALRM, domark); + (void) signal(SIGALRM, alarm_handler); (void) signal(SIGUSR1, Debug ? debug_switch : SIG_IGN); (void) alarm(TIMERINTVL); - + + /* By default, signal() now specifies SA_RESTART, so system calls + * will NOT now return EINTR when a signal arrives during them. + * This makes things like recvfrom potentially hang forever... + * Hence we need to add siginterrupt calls: + */ + siginterrupt(SIGTERM,1); + siginterrupt(SIGINT, 1); + siginterrupt(SIGQUIT,1); + siginterrupt(SIGCHLD,1); + siginterrupt(SIGALRM,1); + siginterrupt(SIGUSR1,1); + /* Create a partial message table for all file descriptors. */ num_fds = getdtablesize(); dprintf("Allocated parts table for %d file descriptors.\n", num_fds); @@ -1049,8 +1107,11 @@ * descriptors. */ if ( InetInuse && AcceptRemote ) { - FD_SET(inetm, &readfds); - if (inetm>maxfds) maxfds=inetm; + for (i = 0; i < *finet; i++) { + if (finet[i+1] != -1) + FD_SET(finet[i+1], &readfds); + if (finet[i+1]>maxfds) maxfds=finet[i+1]; + } dprintf("Listening on syslog UDP port.\n"); } #endif @@ -1072,17 +1133,32 @@ } nfds = select(maxfds+1, (fd_set *) &readfds, (fd_set *) NULL, (fd_set *) NULL, (struct timeval *) NULL); + + if ( exit_on_signal ) + { + die( exit_on_signal ); + exit_on_signal = 0; + } + if ( restart ) { + restart = 0; dprintf("\nReceived SIGHUP, reloading syslogd.\n"); init(); - restart = 0; continue; } + + if ( alarm_signal ) + { + domark(); + alarm_signal = 0; + } + if (nfds == 0) { dprintf("No select activity.\n"); continue; } + if (nfds < 0) { if (errno != EINTR) logerror("select"); @@ -1120,34 +1196,30 @@ #endif #ifdef SYSLOG_INET - if (InetInuse && AcceptRemote && FD_ISSET(inetm, &readfds)) { - len = sizeof(frominet); - memset(line, '\0', sizeof(line)); - i = recvfrom(finet, line, MAXLINE - 2, 0, \ - (struct sockaddr *) &frominet, &len); - dprintf("Message from inetd socket: #%d, host: %s\n", - inetm, inet_ntoa(frominet.sin_addr)); - if (i > 0) { - line[i] = line[i+1] = '\0'; - from = (char *)cvthname(&frominet); - /* - * Here we could check if the host is permitted - * to send us syslog messages. We just have to - * catch the result of cvthname, look for a dot - * and if that doesn't exist, replace the first - * '\0' with '.' and we have the fqdn in lowercase - * letters so we could match them against whatever. - * -Joey - */ - printchopped(from, line, \ - i + 2, finet); - } else if (i < 0 && errno != EINTR) { - dprintf("INET socket error: %d = %s.\n", \ - errno, strerror(errno)); - logerror("recvfrom inet"); - /* should be harmless now that we set - * BSDCOMPAT on the socket */ - sleep(10); + if (InetInuse && AcceptRemote && finet) { + for (i = 0; i < *finet; i++) { + if (FD_ISSET(finet[i+1], &readfds)) { + len = sizeof(frominet); + memset(line, '\0', sizeof(line)); + l = recvfrom(finet[i+1], line, MAXLINE - 2, + 0, (struct sockaddr *)&frominet, + &len); + if (l > 0) { + line[l] = line[l+1] = '\0'; + from = cvthname(&frominet); + printchopped(from, line, l + 2, finet[i+1]); + dprintf("Message from inetd socket: #%d, host: %s\n", + finet[i+1], from); + } + else + if (l < 0 && errno != EINTR) { + dprintf("INET socket error: %d = %s.\n", + errno, strerror(errno)); + logerror("recvfrom inet"); + /* should be harmless */ + sleep(10); + } + } } } #endif @@ -1174,7 +1246,7 @@ int usage() { - fprintf(stderr, "usage: syslogd [-drvh] [-l hostlist] [-m markinterval] [-n] [-p path]\n" \ + fprintf(stderr, "usage: syslogd [-46Adrvxh] [-l hostlist] [-m markinterval] [-n] [-p path]\n" \ " [-s domainlist] [-f conffile]\n"); exit(1); } @@ -1212,41 +1284,71 @@ #endif #ifdef SYSLOG_INET -static int create_inet_socket() +static int * create_inet_sockets() { - int fd, on = 1; - struct sockaddr_in sin; - - fd = socket(AF_INET, SOCK_DGRAM, 0); - if (fd < 0) { - logerror("syslog: Unknown protocol, suspending inet service."); - return fd; - } - - memset(&sin, 0, sizeof(sin)); - sin.sin_family = AF_INET; - sin.sin_port = LogPort; - if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, \ - (char *) &on, sizeof(on)) < 0 ) { - logerror("setsockopt(REUSEADDR), suspending inet"); - close(fd); - return -1; - } - /* We need to enable BSD compatibility. Otherwise an attacker - * could flood our log files by sending us tons of ICMP errors. - */ - if (setsockopt(fd, SOL_SOCKET, SO_BSDCOMPAT, \ - (char *) &on, sizeof(on)) < 0) { - logerror("setsockopt(BSDCOMPAT), suspending inet"); - close(fd); - return -1; - } - if (bind(fd, (struct sockaddr *) &sin, sizeof(sin)) < 0) { - logerror("bind, suspending inet"); - close(fd); - return -1; - } - return fd; + struct addrinfo hints, *res, *r; + int error, maxs, *s, *socks; + + memset(&hints, 0, sizeof(hints)); + hints.ai_flags = AI_PASSIVE; + hints.ai_family = family; + hints.ai_socktype = SOCK_DGRAM; + error = getaddrinfo(NULL, "syslog", &hints, &res); + if (error) { + logerror(gai_strerror(error)); + errno = 0; + die(0); + } + + /* Count max number of sockets we may open */ + for (maxs = 0, r = res; r; r = r->ai_next, maxs++); + socks = malloc((maxs+1) * sizeof(int)); + if (!socks) { + logerror("couldn't allocate memory for sockets"); + die(0); + } + + *socks = 0; /* num of sockets counter at start of array */ + s = socks + 1; + for (r = res; r; r = r->ai_next) { + *s = socket(r->ai_family, r->ai_socktype, r->ai_protocol); + if (*s < 0) { + logerror("socket"); + continue; + } + + if (r->ai_family == AF_INET6) { + int on = 1; + if (setsockopt(*s, IPPROTO_IPV6, IPV6_V6ONLY, + (char *)&on, sizeof (on)) < 0) { + logerror("setsockopt"); + close(*s); + continue; + } + } + + if (bind(*s, r->ai_addr, r->ai_addrlen) < 0) { + close(*s); + logerror("bind"); + continue; + } + + (*socks)++; + s++; + } + + if (*socks == 0) { + free(socks); + if (Debug) + return(NULL); + else + die(0); + } + + if (res) + freeaddrinfo(res); + + return(socks); } #endif @@ -1254,30 +1356,26 @@ crunch_list(list) char *list; { - int count, i; + int i, m, n; char *p, *q; char **result = NULL; p = list; /* strip off trailing delimiters */ - while (p[strlen(p)-1] == LIST_DELIMITER) { - count--; + while (*p && p[strlen(p)-1] == LIST_DELIMITER) p[strlen(p)-1] = '\0'; - } /* cut off leading delimiters */ - while (p[0] == LIST_DELIMITER) { - count--; + while (p[0] == LIST_DELIMITER) p++; - } - /* count delimiters to calculate elements */ - for (count=i=0; p[i]; i++) - if (p[i] == LIST_DELIMITER) count++; + /* count delimiters to calculate the number of elements */ + for (n = i = 0; p[i]; i++) + if (p[i] == LIST_DELIMITER) n++; - if ((result = (char **)malloc(sizeof(char *) * count+2)) == NULL) { + if ((result = (char **)malloc(sizeof(char *) * (n + 2))) == NULL) { printf ("Sorry, can't get enough memory, exiting.\n"); - exit(0); + exit(1); } /* @@ -1285,30 +1383,28 @@ * characters are different from any delimiters, * so we don't have to care about this. */ - count = 0; - while ((q=strchr(p, LIST_DELIMITER))) { - result[count] = (char *) malloc((q - p + 1) * sizeof(char)); - if (result[count] == NULL) { + m = 0; + while ((q = strchr(p, LIST_DELIMITER)) && m < n) { + result[m] = (char *) malloc((q - p + 1) * sizeof(char)); + if (result[m] == NULL) { printf ("Sorry, can't get enough memory, exiting.\n"); - exit(0); + exit(1); } - strncpy(result[count], p, q - p); - result[count][q - p] = '\0'; + memcpy(result[m], p, q - p); + result[m][q - p] = '\0'; p = q; p++; - count++; + m++; } - if ((result[count] = \ - (char *)malloc(sizeof(char) * strlen(p) + 1)) == NULL) { + if ((result[m] = strdup(p)) == NULL) { printf ("Sorry, can't get enough memory, exiting.\n"); - exit(0); + exit(1); } - strcpy(result[count],p); - result[++count] = NULL; + result[++m] = NULL; #if 0 - count=0; - while (result[count]) - dprintf ("#%d: %s\n", count, StripDomains[count++]); + m = 0; + while (result[m]) + dprintf ("#%d: %s\n", m, result[m++]); #endif return result; } @@ -1346,7 +1442,7 @@ void printchopped(hname, msg, len, fd) const char *hname; char *msg; - int len; + size_t len; int fd; { auto int ptlngth; @@ -1446,6 +1542,7 @@ while ((c = *p++) && q < &line[sizeof(line) - 4]) { if (c == '\n') *q++ = ' '; +#if 0 else if (c < 040) { *q++ = '^'; *q++ = c ^ 0100; @@ -1454,7 +1551,9 @@ *q++ = '0' + ((c & 0300) >> 6); *q++ = '0' + ((c & 0070) >> 3); *q++ = '0' + (c & 0007); - } else + } +#endif + else *q++ = c; } *q = '\0'; @@ -1550,18 +1649,13 @@ * Check to see if msg looks non-standard. */ msglen = strlen(msg); - if (msglen < 16 || msg[3] != ' ' || msg[6] != ' ' || - msg[9] != ':' || msg[12] != ':' || msg[15] != ' ') - flags |= ADDDATE; - - (void) time(&now); - if (flags & ADDDATE) - timestamp = ctime(&now) + 4; - else { - timestamp = msg; + if (!(msglen < 16 || msg[3] != ' ' || msg[6] != ' ' || + msg[9] != ':' || msg[12] != ':' || msg[15] != ' ')) { msg += 16; msglen -= 16; } + (void) time(&now); + timestamp = ctime(&now) + 4; /* extract facility and priority level */ if (flags & MARK) @@ -1661,13 +1755,15 @@ char *msg; { struct iovec iov[6]; + struct addrinfo *r; register struct iovec *v = iov; char repbuf[80]; #ifdef SYSLOG_INET register int l; + int i,lsent = 0; char line[MAXLINE + 1]; time_t fwd_suspend; - struct hostent *hp; + struct addrinfo *saddr; #endif dprintf("Called fprintlog, "); @@ -1736,7 +1832,7 @@ fwd_suspend = time((time_t *) 0) - f->f_time; if ( fwd_suspend >= INET_SUSPEND_TIME ) { dprintf("Forwarding suspension to unknown over, retrying\n"); - if ( (hp = gethostbyname(f->f_un.f_forw.f_hname)) == NULL ) { + if ( (saddr = not_local_address(f->f_un.f_forw.f_hname)) == NULL ) { dprintf("Failure: %s\n", sys_h_errlist[h_errno]); dprintf("Retries: %d\n", f->f_prevcount); if ( --f->f_prevcount < 0 ) { @@ -1748,7 +1844,7 @@ } else { dprintf("%s found, resuming.\n", f->f_un.f_forw.f_hname); - memcpy((char *) &f->f_un.f_forw.f_addr.sin_addr, hp->h_addr, hp->h_length); + f->f_un.f_forw.f_addr = saddr; f->f_prevcount = 0; f->f_type = F_FORW; goto f_forw; @@ -1776,15 +1872,31 @@ l = strlen(line); if (l > MAXLINE) l = MAXLINE; - if (sendto(finet, line, l, 0, \ - (struct sockaddr *) &f->f_un.f_forw.f_addr, - sizeof(f->f_un.f_forw.f_addr)) != l) { - int e = errno; - dprintf("INET sendto error: %d = %s.\n", - e, strerror(e)); - f->f_type = F_FORW_SUSP; - errno = e; - logerror("sendto"); + if (finet) { + for (r = f->f_un.f_forw.f_addr; r; r = r->ai_next) { + for (i = 0; i < *finet; i++) { +#if 0 + /* + * should we check AF first, or just + * trial and error? FWD + */ + if (r->ai_family == address_family_of(finet[i+1])) +#endif + lsent = sendto(finet[i+1], line, l, 0, + r->ai_addr, r->ai_addrlen); + if (lsent == l) + break; + } + if (lsent == l && !send_to_all) + break; + } + if (lsent != l) { + int e = errno; + dprintf("INET sendto error: %d = %s.\n", e, strerror(e)); + f->f_type = F_FORW_SUSP; + errno = e; + logerror("sendto"); + } } } break; @@ -1839,7 +1951,7 @@ #else && e == EBADF) { #endif - f->f_file = open(f->f_un.f_fname, O_WRONLY|O_APPEND|O_NOCTTY); + f->f_file = open(f->f_un.f_fname, O_WRONLY|O_APPEND|O_NOCTTY|O_LARGEFILE); if (f->f_file < 0) { f->f_type = F_UNUSED; logerror(f->f_un.f_fname); @@ -1914,6 +2026,7 @@ (void) signal(SIGTERM, SIG_DFL); (void) alarm(0); (void) signal(SIGALRM, endtty); + siginterrupt(SIGALRM,1); #ifndef SYSV (void) signal(SIGTTOU, SIG_IGN); (void) sigsetmask(0); @@ -1929,7 +2042,7 @@ /* is this slot used? */ if (ut.ut_name[0] == '\0') continue; - if (ut.ut_type == LOGIN_PROCESS) + if (ut.ut_type != USER_PROCESS) continue; if (!(strcmp (ut.ut_name,"LOGIN"))) /* paranoia */ continue; @@ -2003,27 +2116,48 @@ * Return a printable representation of a host address. */ const char *cvthname(f) - struct sockaddr_in *f; + struct sockaddr_storage *f; { - struct hostent *hp; + int error; register char *p; + sigset_t omask, nmask; int count; + static char hname[NI_MAXHOST], ip[NI_MAXHOST]; + + error = getnameinfo((struct sockaddr *)f, + sizeof(*f), + ip, sizeof ip, NULL, 0, + NI_NUMERICHOST); + dprintf("cvthname(%s)\n", ip); - if (f->sin_family != AF_INET) { - dprintf("Malformed from address.\n"); + if (error) { + dprintf("Malformed from address %s\n", gai_strerror(error)); return ("???"); } - hp = gethostbyaddr((char *) &f->sin_addr, sizeof(struct in_addr), \ - f->sin_family); - if (hp == 0) { - dprintf("Host name for your address (%s) unknown.\n", - inet_ntoa(f->sin_addr)); - return (inet_ntoa(f->sin_addr)); + + + if (!DisableDNS) { + sigemptyset(&nmask); + sigaddset(&nmask, SIGHUP); + sigprocmask(SIG_BLOCK, &nmask, &omask); + + error = getnameinfo((struct sockaddr *)f, + sizeof(*f), + hname, sizeof hname, NULL, 0, + NI_NAMEREQD); + + sigprocmask(SIG_SETMASK, &omask, NULL); + } + + if (error || DisableDNS) { + dprintf("Host name for your address (%s) unknown\n", ip); + return (ip); } + /* * Convert to lower case, just like LocalDomain above */ - for (p = (char *)hp->h_name; *p ; p++) + for (p = (char *) hname; *p ; p++) if (isupper(*p)) *p = tolower(*p); @@ -2031,17 +2165,17 @@ * Notice that the string still contains the fqdn, but your * hostname and domain are separated by a '\0'. */ - if ((p = strchr(hp->h_name, '.'))) { + if ((p = strchr(hname, '.'))) { if (strcmp(p + 1, LocalDomain) == 0) { *p = '\0'; - return (hp->h_name); + return (hname); } else { if (StripDomains) { count=0; while (StripDomains[count]) { if (strcmp(p + 1, StripDomains[count]) == 0) { *p = '\0'; - return (hp->h_name); + return (hname); } count++; } @@ -2049,9 +2183,9 @@ if (LocalHosts) { count=0; while (LocalHosts[count]) { - if (!strcmp(hp->h_name, LocalHosts[count])) { + if (!strcmp(hname, LocalHosts[count])) { *p = '\0'; - return (hp->h_name); + return (hname); } count++; } @@ -2059,7 +2193,15 @@ } } - return (hp->h_name); + return (hname); +} + +void alarm_handler( int sig ) +{ + alarm_signal = 1; + (void) signal(SIGALRM, alarm_handler); + (void) alarm(TIMERINTVL); + siginterrupt(SIGALRM,1); } void domark() @@ -2092,8 +2234,6 @@ } } } - (void) signal(SIGALRM, domark); - (void) alarm(TIMERINTVL); } void debug_switch() @@ -2109,7 +2249,7 @@ * Print syslogd errors some place. */ void logerror(type) - char *type; + const char *type; { char buf[100]; @@ -2157,8 +2297,14 @@ for (i = 0; i < nfunix; i++) if (funix[i] != -1) close(funix[i]); + /* Close the inet socket. */ - if (InetInuse) close(inetm); + if (InetInuse && finet) + for (i = 0; i < *finet; i++) + if (finet[i+1] != -1) close(finet[i+1]); + free(finet); + finet = NULL; + /* Clean-up files. */ for (i = 0; i < nfunix; i++) @@ -2170,6 +2316,13 @@ exit(0); } +void exit_signal_handler(int sig) +{ + exit_on_signal = sig; + signal(sig, exit_signal_handler); + siginterrupt(sig,1); +} + /* * Signal handler to terminate the parent process. */ @@ -2177,7 +2330,7 @@ void doexit(sig) int sig; { - exit (0); + _exit(0); } #endif @@ -2212,7 +2365,6 @@ logerror("see syslogd(8) for details of whether and how to enable it."); return; } - LogPort = sp->s_port; /* * Close all open log files and free log descriptor array. @@ -2237,6 +2389,9 @@ case F_CONSOLE: (void) close(f->f_file); break; + case F_FORW: + freeaddrinfo(f->f_un.f_forw.f_addr); + break; } } @@ -2346,21 +2501,22 @@ #ifdef SYSLOG_INET if (Forwarding || AcceptRemote) { - if (finet < 0) { - finet = create_inet_socket(); - if (finet >= 0) { + if (!finet) { + finet = create_inet_sockets(); + if (*finet > 0) { InetInuse = 1; dprintf("Opened syslog UDP port.\n"); } } } else { - if (finet >= 0) - close(finet); - finet = -1; + if (finet) + for (i = 0; i < *finet; i++) + if (finet[i+1] != -1) close(finet[i+1]); + free(finet); + finet = NULL; InetInuse = 0; } - inetm = finet; #endif Initialized = 1; @@ -2440,6 +2596,8 @@ char *line; register struct filed *f; { + struct addrinfo hints, *res; + int error; register char *p; register char *q; register int i, i2; @@ -2449,7 +2607,7 @@ int ignorepri = 0; int syncfile; #ifdef SYSLOG_INET - struct hostent *hp; + struct addrinfo *ina; #endif char buf[MAXLINE]; char xbuf[200]; @@ -2605,22 +2763,29 @@ { case '@': #ifdef SYSLOG_INET - (void) strcpy(f->f_un.f_forw.f_hname, ++p); + (void)strncpy(f->f_un.f_forw.f_hname, ++p, + sizeof(f->f_un.f_forw.f_hname)); dprintf("forwarding host: %s\n", p); /*ASP*/ - if ( (hp = gethostbyname(p)) == NULL ) { + if ( (ina = not_local_address(p)) == NULL ) { f->f_type = F_FORW_UNKN; f->f_prevcount = INET_RETRY_MAX; f->f_time = time ( (time_t *)0 ); } else { f->f_type = F_FORW; + freeaddrinfo(ina); } - memset((char *) &f->f_un.f_forw.f_addr, 0, - sizeof(f->f_un.f_forw.f_addr)); - f->f_un.f_forw.f_addr.sin_family = AF_INET; - f->f_un.f_forw.f_addr.sin_port = LogPort; + memset(&hints, 0, sizeof(hints)); + hints.ai_family = family; + hints.ai_socktype = SOCK_DGRAM; + error = getaddrinfo(f->f_un.f_forw.f_hname, "syslog", &hints, + &res); + if (error) { + logerror(gai_strerror(error)); + break; + } if ( f->f_type == F_FORW ) - memcpy((char *) &f->f_un.f_forw.f_addr.sin_addr, hp->h_addr, hp->h_length); + f->f_un.f_forw.f_addr = res; /* * Otherwise the host might be unknown due to an * inaccessible nameserver (perhaps on the same @@ -2640,7 +2805,7 @@ f->f_file = open(++p, O_RDWR|O_NONBLOCK); f->f_type = F_PIPE; } else { - f->f_file = open(p, O_WRONLY|O_APPEND|O_CREAT|O_NOCTTY, + f->f_file = open(p, O_WRONLY|O_APPEND|O_CREAT|O_NOCTTY|O_LARGEFILE, 0644); f->f_type = F_FILE; } @@ -2793,6 +2958,206 @@ return; } +/* These functions are for verifying that a remote logging host + * '@name' target does NOT resolve to an address attached to a + * local interface; as reported by Chuck Mead , + * if this happens, syslogd sends log messages to itself until + * the /var partition fills up. + * Jason Vas Dias + */ + + +static void free_host_ai_list( struct addrinfo *ai ) +{ + struct addrinfo *aie=0L, *ain=0L; + for(aie = ai; aie != 0L; aie = ain) + { + ain = aie->ai_next; + if(aie->ai_addr != 0L) + free(aie->ai_addr); + if(aie->ai_canonname != 0L) + free(aie->ai_canonname); + free(aie); + } +} + +static struct addrinfo *new_host_ai_node( struct addrinfo *ai ) +{ + struct addrinfo *aie =(struct addrinfo *) malloc( sizeof(struct addrinfo) ); + int len; + + if( aie == 0L ) + return 0L; + if( ai != 0L ) + memcpy(aie, ai, sizeof(struct addrinfo)); + aie->ai_addr = 0L; + aie->ai_canonname =0L; + aie->ai_next = 0L; + if( ( ai->ai_addr != 0L ) && (ai->ai_addrlen > 0) ) + { + aie->ai_addr = (struct sockaddr*) malloc( ai->ai_addrlen ); + if( aie->ai_addr != 0L ) + memcpy(aie->ai_addr, ai->ai_addr, ai->ai_addrlen ); + } + if( ( ai->ai_canonname != 0L) && (*(ai->ai_canonname) != '\0') ) + { + len = strlen(ai->ai_canonname); + aie->ai_canonname = (char*) malloc( len + 1); + if( aie->ai_canonname != 0L ) + { + memcpy( aie->ai_canonname, ai->ai_canonname, len ); + ai->ai_canonname[len]='\0'; + } + } + return aie; +} + +struct addrinfo *host_ai_list( char *host ) +{ + struct addrinfo *ai=0L, *ail=0L, *aip, *aie, aih; + int r; + char *n; + + if ( (host == 0L) || (*host == '\0') ) + return 0L; + memset(&aih,'\0',sizeof(struct addrinfo)); + aih.ai_flags = AI_CANONNAME; + aip=0L; + if( ((r=getaddrinfo(host, 0L, &aih, &aip)) != 0 ) || (aip == 0L) ) + return(0L); + else + for( aie=aip; aie != 0L; aie=aie->ai_next ) + { + if( (aie->ai_addr == 0L) + ||(aie->ai_family == PF_UNSPEC) + ||(aie->ai_addrlen <= 0) + ) + continue; + if(ai==0L) + { + if(aie->ai_canonname == 0L) + continue; + ai = new_host_ai_node(aie); + ail= ai; + }else + { + n=0L; + if( aie->ai_canonname == 0L) + { + n = ai->ai_canonname; + aie->ai_canonname = n; + } + ai->ai_next=new_host_ai_node(aie); + ai=ai->ai_next; + if(n != 0L) + aie->ai_canonname = 0L; + } + if (aie == aie->ai_next) + break; + while + ( + (aie->ai_next != 0L) + &&( + ( aie->ai_next->ai_addr == 0L) + ||( aie->ai_addr == aie->ai_next->ai_addr ) + ||( (aie->ai_next->ai_family == aie->ai_family) + &&(aie->ai_next->ai_addrlen == aie->ai_addrlen) + &&(memcmp( aie->ai_next->ai_addr, aie->ai_addr, aie->ai_addrlen)==0) + ) + ) + )/* bug: each unique address / name combination is repeated three times! */ + aie = aie->ai_next; + } + if ( ai != 0L) + ai->ai_next=0L; + freeaddrinfo(aip); + return ail; +} + +int hosts_equal( struct addrinfo *ai1, struct addrinfo *ai2 ) +{ + struct addrinfo *ai=0; + for(; ai1 != 0L; ai1 = ai1->ai_next) + if (( ai1->ai_canonname != 0L) || ( ai1->ai_addr != 0L)) + { + for(ai = ai2; ai != 0L; ai = ai->ai_next) + { + if( ( ( ai1->ai_canonname != 0L) + &&( ai->ai_canonname != 0L) + &&( strcmp(ai->ai_canonname, ai1->ai_canonname)==0) + ) + || ( ( ai1->ai_addr != 0L) + &&( ai->ai_addr != 0L ) + &&( ai1->ai_family == ai->ai_family) + &&( ai1->ai_addrlen == ai->ai_addrlen) + &&( memcmp(ai->ai_addr, ai1->ai_addr, ai->ai_addrlen) == 0) + ) + ) break; + } + if( ai != 0L ) + break; + } + return ((ai1 != 0L) && (ai != 0L)); +} + +struct addrinfo *not_local_address(char *host) +{ + char hostname[1024]; + struct addrinfo *ai1, *ai2; + struct ifaddrs *ifa=0L; + if ( host == 0L ) + return 0L; + if( (strcmp(host,"localhost") == 0) + ||(strcmp(host,"localhost.localdomain") == 0) + ||(strcmp(host,"127.0.0.1") == 0) + ||(strcmp(host,"::1") == 0) + ) return 0L; + if (gethostname(hostname,1024) == 0) + if ( strcmp(host, hostname) == 0 ) + return 0L; + ai1 = host_ai_list(host); + ai2 = host_ai_list(hostname); + if( hosts_equal(ai1, ai2) ) { + free_host_ai_list(ai2); + free_host_ai_list(ai1); + return 0L; + } + free_host_ai_list(ai2); + ai2=0L; + if( getifaddrs(&ifa) == 0) + { + for(; (ifa != 0L) && (ifa->ifa_addr != 0L); ifa = ifa->ifa_next ) + { + if( inet_ntop( ifa->ifa_addr->sa_family, + ((ifa->ifa_addr->sa_family == PF_INET) + ? (void*)&(((struct sockaddr_in*)(ifa->ifa_addr))->sin_addr) + : (ifa->ifa_addr->sa_family == PF_INET6) + ? (void*)&(((struct sockaddr_in6*)(ifa->ifa_addr))->sin6_addr) + : (void*)&(ifa->ifa_addr->sa_data[0]) + ), + hostname, + sizeof(hostname) + ) != 0L + ) + { + ai2=host_ai_list(hostname); + if( hosts_equal(ai1, ai2) ) + break; + free_host_ai_list(ai2); + ai2=0L; + } + } + } + if( ai2 != 0L ) + { + free_host_ai_list(ai2); + free_host_ai_list(ai1); + return 0L; + } + + return ai1; +} + /* * Local variables: * c-indent-level: 8 diff -Naur sysklogd-1.4.1.orig/version.h sysklogd-1.4.1/version.h --- sysklogd-1.4.1.orig/version.h 2001-03-11 19:40:10.000000000 +0000 +++ sysklogd-1.4.1/version.h 2007-05-25 05:59:23.000000000 +0000 @@ -1,2 +1,2 @@ #define VERSION "1.4" -#define PATCHLEVEL "1" +#define PATCHLEVEL "2-prerelease"