499 lines
12 KiB
Diff
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);
|