syslogd/sysklogd-1.4.1-dns.patch

499 lines
12 KiB
Diff

---
Makefile | 4
resolve.c | 249 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
syslogd.c | 139 +++++-----------------------------
3 files changed, 275 insertions(+), 117 deletions(-)
--- Makefile
+++ Makefile 2022-10-18 06:11:16.691008894 +0000
@@ -79,8 +79,8 @@ test: syslog_tst ksym oops.ko tsyslogd
install: install_man install_exec
-syslogd: syslogd.o pidfile.o
- ${CC} ${LDFLAGS} -o syslogd syslogd.o pidfile.o ${LIBS}
+syslogd: syslogd.o pidfile.o resolve.o
+ ${CC} ${LDFLAGS} -o syslogd syslogd.o pidfile.o resolve.o ${LIBS}
klogd: klogd.o syslog.o pidfile.o ksym.o ksym_mod.o
${CC} ${LDFLAGS} -o klogd klogd.o syslog.o pidfile.o ksym.o \
--- resolve.c
+++ resolve.c 2022-10-18 06:11:16.691008894 +0000
@@ -0,0 +1,249 @@
+/*
+ * Resolve a hostname
+ *
+ * Copyright (C) 2003, SuSE Linux AG
+ * Written by okir@suse.de
+ */
+
+#include <sys/poll.h>
+#include <netdb.h>
+#include <string.h>
+#include <time.h>
+#include <malloc.h>
+#include <stdlib.h>
+#include <signal.h>
+#include <unistd.h>
+
+#if defined(__GLIBC__)
+#define dprintf mydprintf
+#endif /* __GLIBC__ */
+
+/* Number of times we retry resolving a name */
+#define RESOLVER_RETRIES 10
+/* Timeout between retries to resolve a name */
+#define RESOLVER_RETRY_TIME (3 * 60)
+/* Time to wait for the sub-process comes up with an
+ * answer, before we suspend the entry */
+#define RESOLVER_WAIT_TIME 5
+
+struct res_name {
+ struct res_name * next;
+ char * name;
+ unsigned int retries;
+ time_t retry_time;
+ time_t wait_time;
+ pid_t process;
+ int pipe;
+ struct sockaddr_storage address;
+};
+
+extern void dprintf(char *fmt, ...);
+static int do_result(struct res_name *res);
+static void do_query(int, int, const char *);
+
+static struct res_name *resolve;
+
+int
+resolve_name(const char *name, int family, struct sockaddr_storage *addr)
+{
+ struct res_name *res;
+ int fd[2];
+ pid_t pid;
+ time_t now;
+
+ time(&now);
+ for (res = resolve; res; res = res->next) {
+ if (!strcmp(res->name, name)) {
+ /* If there's still a sub-process
+ * attached, see if it came up with an
+ * answer in the meantime */
+ if (res->pipe >= 0)
+ do_result(res);
+ goto check_result;
+ }
+ }
+
+ res = (struct res_name *) calloc(1, sizeof(*res));
+ res->name = strdup(name);
+ res->retries = RESOLVER_RETRIES;
+ res->retry_time = now + RESOLVER_RETRY_TIME;
+ res->pipe = -1;
+ res->next = resolve;
+ resolve = res;
+
+retry: res->retries -= 1;
+
+ dprintf("Trying to resolve \"%s\", attempt #%u\n",
+ res->name, RESOLVER_RETRIES - res->retries);
+
+ if (res->pipe >= 0) {
+ /* Make sure resolver subprocess is dead */
+ kill(res->process, SIGKILL);
+ close(res->pipe);
+ res->pipe = -1;
+ }
+
+ signal(SIGCHLD, SIG_IGN);
+ if (pipe(fd) < 0) {
+ /* log error? */
+ return -1;
+ }
+ if ((pid = fork()) < 0) {
+ /* log error? */
+ close(fd[0]);
+ close(fd[1]);
+ return -1;
+ }
+
+ if (pid == 0) {
+ close(fd[0]);
+ do_query(fd[1], family, res->name);
+ /* shouldn't return */
+ exit(1);
+ }
+
+ res->wait_time = now + RESOLVER_WAIT_TIME;
+ res->process = pid;
+ res->pipe = fd[0];
+ close(fd[1]);
+
+ /* Try to collect result within the next couple
+ * of seconds */
+ do_result(res);
+
+check_result:
+ if (res->pipe >= 0) {
+ dprintf("%s: name resolution not complete, "
+ "waiting for resolver sub-process\n",
+ res->name);
+ return 0;
+ }
+
+ if (res->address.ss_family != AF_UNSPEC) {
+ *addr = res->address;
+ return 1;
+ }
+ if (res->retries == 0) {
+ dprintf("%s: too many failed attempts to resolve hostname, "
+ "given up.\n", res->name);
+ return -1;
+ }
+ if (res->retry_time > now) {
+ dprintf("%s: name resolution failed, "
+ "will retry in %d seconds\n",
+ res->name, res->retry_time - now);
+ return 0;
+ }
+ goto retry;
+}
+
+/*
+ * This function clears the resolver's internal state
+ * when syslogd received a SIGHUP
+ */
+void
+init_resolver(void)
+{
+ struct res_name *res;
+
+ for (res = resolve; res; res = res->next) {
+ res->address.ss_family = AF_UNSPEC;
+ res->retries = RESOLVER_RETRIES;
+ res->retry_time = 0;
+ }
+}
+
+
+/*
+ * Collect result from sub-process
+ */
+int
+do_result(struct res_name *res)
+{
+ struct sockaddr_storage addr;
+ struct pollfd _poll;
+ long wait;
+ int n;
+
+ if (res->pipe < 0)
+ return 0;
+
+ /* See if we should wait for the subprocess to come
+ * up with an answer (the initial call to do_result
+ * after starting the sub-process will always wait for
+ * a few seconds to avoid losing messages) */
+ if ((wait = res->wait_time - time(NULL)) < 0)
+ wait = 0;
+
+ /* See if we get the resolver's result within the
+ * next "wait" seconds. If not, let it continue in the
+ * background */
+ _poll.fd = res->pipe;
+ _poll.events = POLLIN;
+ if (poll(&_poll, 1, wait * 1000) < 1)
+ return 0;
+
+ n = read(res->pipe, &addr, sizeof(addr));
+
+ /* child process has done its duty. */
+ kill(res->process, SIGKILL);
+ close(res->pipe);
+ res->process = 0;
+ res->pipe = -1;
+
+ if (n != sizeof(addr))
+ return -1;
+
+ res->address = addr;
+ if (addr.ss_family != AF_UNSPEC)
+ return 1;
+ return -1;
+}
+
+/*
+ * Sub-process performing lookup
+ */
+void
+do_query(int fd, int family, const char *name)
+{
+ struct sockaddr_storage ss;
+ struct addrinfo hints, *res;
+ int r;
+
+ memset(&hints, 0, sizeof(hints));
+ hints.ai_socktype = SOCK_DGRAM;
+#ifdef notyet
+ /* XXX - specify AI_whatever for automatic v4-v6 mapping */
+#else
+ hints.ai_family = (family == AF_INET)? family : AF_UNSPEC;
+#endif
+
+ r = getaddrinfo(name, "syslog", &hints, &res);
+ if (r != 0) {
+ dprintf("failed to resolve \"%s\": %s\n",
+ name, gai_strerror(r));
+ exit(1);
+ }
+
+ memset(&ss, 0, sizeof(ss));
+
+ /* Do v4mapped v6 address (supported by recent glibcs
+ * only) */
+ if (family == AF_INET6 && res->ai_family == AF_INET) {
+ struct sockaddr_in6 *six = (struct sockaddr_in6 *) &ss;
+ struct sockaddr_in *sin = (struct sockaddr_in *) res->ai_addr;
+
+ six->sin6_family = AF_INET6;
+ six->sin6_port = sin->sin_port;
+ six->sin6_addr.s6_addr16[5] = 0xffff;
+ six->sin6_addr.s6_addr32[3] = sin->sin_addr.s_addr;
+ } else if (res->ai_addrlen > sizeof(ss)) {
+ dprintf("failed to resolve \"%s\": address too large\n",
+ name);
+ exit(1);
+ } else {
+ memcpy(&ss, res->ai_addr, res->ai_addrlen);
+ }
+ write(fd, &ss, sizeof(ss));
+ exit(0);
+}
--- syslogd.c
+++ syslogd.c 2022-10-18 06:17:39.648170295 +0000
@@ -683,14 +683,7 @@ struct filed {
struct {
char f_hname[MAXHOSTNAMELEN+1];
#ifdef INET6
- union {
- struct sockaddr sa;
- struct sockaddr_in sin;
- struct sockaddr_in6 sin6;
- } f_sa;
-#define f_addr f_sa.sa
-#define f_addr4 f_sa.sin
-#define f_addr6 f_sa.sin6
+ struct sockaddr_storage f_addr;
#else
struct sockaddr_in f_addr;
#endif
@@ -846,19 +839,17 @@ int decode(char *name, struct code *code
#if defined(__GLIBC__)
#define dprintf mydprintf
#endif /* __GLIBC__ */
-static void dprintf(char *, ...);
+void dprintf(char *, ...);
static void allocate_log(void);
-void sighup_handler();
+void sighup_handler(int sig);
#ifdef SYSLOG_UNIXAF
static int create_unix_socket(const char *path);
#endif
#ifdef SYSLOG_INET
static int create_inet_socket();
-#ifdef INET6
-static void setup_inetaddr_all();
-static const char *setup_inetaddr(struct filed *f);
-#endif
+extern int resolve_name(const char *, int, struct sockaddr_storage *);
+extern void init_resolver(void);
#endif
int main(argc, argv)
@@ -1413,63 +1404,6 @@ static int create_inet_socket()
return fd;
}
-#ifdef INET6
-
-static void setup_inetaddr_all()
-{
- struct filed *f;
-#ifdef SYSV
- int lognum;
-
- for (lognum = 0; lognum <= nlogs; lognum++) {
- f = &Files[lognum];
-#else
- for (f = Files; f; f = f->f_next) {
-#endif
- if (f->f_type == F_FORW_UNKN) {
- if (setup_inetaddr(f)) {
- f->f_prevcount = INET_RETRY_MAX;
- f->f_time = time( (time_t *)0 );
- } else {
- f->f_type = F_FORW;
- }
- }
- }
-}
-
-static const char *setup_inetaddr(struct filed *f)
-{
- struct addrinfo hints, *res;
- int error;
-
- memset(&hints, 0, sizeof(hints));
- hints.ai_family = family == AF_INET6 ? AF_UNSPEC : AF_INET;
- hints.ai_socktype = SOCK_DGRAM;
- error = getaddrinfo(f->f_un.f_forw.f_hname, "syslog", &hints, &res);
- if (error) {
- return gai_strerror(error);
- }
- if (res->ai_addrlen > sizeof(f->f_un.f_forw.f_sa)) {
- freeaddrinfo(res);
- return "addrlen too large";
- }
- if (family == AF_INET6 && res->ai_family == AF_INET) {
- /* v4mapped addr */
- f->f_un.f_forw.f_addr.sa_family = AF_INET6;
- f->f_un.f_forw.f_addr6.sin6_port =
- ((struct sockaddr_in *)res->ai_addr)->sin_port;
- f->f_un.f_forw.f_addr6.sin6_addr.s6_addr16[5] = 0xffff;
- memcpy(&f->f_un.f_forw.f_addr6.sin6_addr.s6_addr32[3],
- &((struct sockaddr_in *)res->ai_addr)->sin_addr,
- sizeof(struct in_addr));
- } else {
- memcpy(&f->f_un.f_forw.f_addr, res->ai_addr, res->ai_addrlen);
- }
- freeaddrinfo(res);
-
- return NULL;
-}
-#endif /* end of INET6 */
#endif
char **
@@ -1913,7 +1847,7 @@ void fprintlog(f, from, flags, msg)
char line[MAXLINE + 1];
time_t fwd_suspend;
#ifdef INET6
- const char *errmsg;
+ int reserr;
#else
struct hostent *hp;
#endif
@@ -1982,38 +1916,21 @@ void fprintlog(f, from, flags, msg)
*/
case F_FORW_UNKN:
dprintf(" %s\n", f->f_un.f_forw.f_hname);
- fwd_suspend = time((time_t *) 0) - f->f_time;
- if ( fwd_suspend >= INET_SUSPEND_TIME ) {
- dprintf("Forwarding suspension to unknown over, retrying\n");
-#ifdef INET6
- if ((errmsg = setup_inetaddr(f))) {
- dprintf("Failure: %s\n", errmsg);
-#else
- if ( (hp = gethostbyname(f->f_un.f_forw.f_hname)) == NULL ) {
- dprintf("Failure: %s\n", sys_h_errlist[h_errno]);
-#endif
- dprintf("Retries: %d\n", f->f_prevcount);
- if ( --f->f_prevcount < 0 ) {
- dprintf("Giving up.\n");
- f->f_type = F_UNUSED;
- }
- else
- dprintf("Left retries: %d\n", f->f_prevcount);
- }
- else {
- dprintf("%s found, resuming.\n", f->f_un.f_forw.f_hname);
-#ifndef INET6 /* not */
- memcpy((char *) &f->f_un.f_forw.f_addr.sin_addr, hp->h_addr, hp->h_length);
-#endif
- f->f_prevcount = 0;
- f->f_type = F_FORW;
- goto f_forw;
- }
+ reserr = resolve_name(f->f_un.f_forw.f_hname,
+ family,
+ &f->f_un.f_forw.f_addr);
+ if (reserr > 0) {
+ dprintf("Successfully resolved hostname \"%s\"\n", f->f_un.f_forw.f_hname);
+ f->f_type = F_FORW;
+ } else if (reserr < 0) {
+ dprintf("Giving up on hostname \"%s\"\n", f->f_un.f_forw.f_hname);
+ f->f_type = F_UNUSED;
+ break;
+ } else {
+ /* Not yet - query in progress, or suspended */
+ break;
}
- else
- dprintf("Forwarding suspension not over, time " \
- "left: %d\n", INET_SUSPEND_TIME - fwd_suspend);
- break;
+ /* fallthrough */
case F_FORW:
/*
@@ -2429,9 +2346,7 @@ void logerror(type)
}
void die(sig)
-
int sig;
-
{
register struct filed *f;
char buf[100];
@@ -2655,6 +2570,7 @@ void init()
#endif
#ifdef SYSLOG_INET
+ init_resolver();
if (Forwarding || AcceptRemote) {
if (finet < 0) {
finet = create_inet_socket();
@@ -2671,10 +2587,6 @@ void init()
InetInuse = 0;
}
inetm = finet;
-#ifdef INET6
- if (finet >= 0)
- setup_inetaddr_all();
-#endif
#endif
Initialized = 1;
@@ -3040,8 +2952,7 @@ int decode(name, codetab)
return (-1);
}
-static void dprintf(char *fmt, ...)
-
+void dprintf(char *fmt, ...)
{
va_list ap;
@@ -3061,8 +2972,7 @@ static void dprintf(char *fmt, ...)
* The following function is responsible for allocating/reallocating the
* array which holds the structures which define the logging outputs.
*/
-static void allocate_log()
-
+static void allocate_log(void)
{
dprintf("Called allocate_log, nlogs = %d.\n", nlogs);
@@ -3109,8 +3019,7 @@ static void allocate_log()
* doing this during a signal handler. Instead this function simply sets
* a flag variable which will tell the main loop to go through a restart.
*/
-void sighup_handler()
-
+void sighup_handler(int sig)
{
restart = 1;
signal(SIGHUP, sighup_handler);