502 lines
13 KiB
Diff
502 lines
13 KiB
Diff
---
|
|
CHANGES | 3
|
|
Makefile | 2
|
|
syslogd.c | 228 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++------
|
|
3 files changed, 210 insertions(+), 23 deletions(-)
|
|
|
|
--- CHANGES
|
|
+++ CHANGES 2022-10-13 08:13:35.285747318 +0000
|
|
@@ -72,6 +72,9 @@ Version 1.5
|
|
. Matthew Fischer <futhark@vzavenue.net>
|
|
- Remove special treatment of the percent sign in klogd
|
|
|
|
+Version 1.4.1-usagi (2001/03/21)
|
|
+ - syslogd IPv6 support
|
|
+ (based on patch from Hiroyuki YAMAMORI <h-yamamo@db3.so-net.ne.jp>)
|
|
|
|
Version 1.4.1
|
|
|
|
--- Makefile
|
|
+++ Makefile 2022-10-13 08:30:44.607385067 +0000
|
|
@@ -20,7 +20,7 @@
|
|
CC= gcc
|
|
#SKFLAGS= -g -DSYSV -Wall
|
|
#LDFLAGS= -g
|
|
-SKFLAGS= $(RPM_OPT_FLAGS) -O3 -DSYSV -fomit-frame-pointer -Wall -fno-strength-reduce
|
|
+SKFLAGS= $(RPM_OPT_FLAGS) -DINET6 -O3 -DSYSV -fomit-frame-pointer -Wall -fno-strength-reduce
|
|
# -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE
|
|
# -D_FILE_OFFSET_BITS=64 -D_LARGEFILE64_SOURCE
|
|
# $(shell getconf LFS_SKFLAGS)
|
|
--- syslogd.c
|
|
+++ syslogd.c 2022-10-13 08:30:05.088090073 +0000
|
|
@@ -654,6 +654,7 @@ int funix[MAXFUNIX] = { -1, };
|
|
* This table contains plain text for h_errno errors used by the
|
|
* net subsystem.
|
|
*/
|
|
+#ifndef INET6 /* not */
|
|
const char *sys_h_errlist[] = {
|
|
"No problem", /* NETDB_SUCCESS */
|
|
"Authoritative answer: host not found", /* HOST_NOT_FOUND */
|
|
@@ -662,6 +663,7 @@ const char *sys_h_errlist[] = {
|
|
"Valid name, no data record of requested type", /* NO_DATA */
|
|
"no address, look for MX record" /* NO_ADDRESS */
|
|
};
|
|
+#endif
|
|
|
|
/*
|
|
* This structure represents the files that will have log
|
|
@@ -680,7 +682,18 @@ struct filed {
|
|
char f_uname[MAXUNAMES][UNAMESZ+1];
|
|
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
|
|
+#else
|
|
struct sockaddr_in f_addr;
|
|
+#endif
|
|
} f_forw; /* forwarding address */
|
|
char f_fname[MAXFNAME];
|
|
} f_un;
|
|
@@ -788,7 +801,11 @@ char *LocalDomain; /* our local domain
|
|
char *emptystring = "";
|
|
int InetInuse = 0; /* non-zero if INET sockets are being used */
|
|
int finet = -1; /* Internet datagram socket */
|
|
+#ifdef INET6
|
|
+sa_family_t family; /* socket address family */
|
|
+#else
|
|
int LogPort; /* port number for INET connections */
|
|
+#endif
|
|
int Initialized = 0; /* set when we have initialized ourselves */
|
|
int MarkInterval = 20 * 60; /* interval between marks in seconds */
|
|
int MarkSeq = 0; /* mark sequence number */
|
|
@@ -815,10 +832,10 @@ void fprintlog(register struct filed *f,
|
|
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 *f);
|
|
void domark();
|
|
void debug_switch();
|
|
-void logerror(char *type);
|
|
+void logerror(const char *type);
|
|
void die(int sig);
|
|
#ifndef TESTING
|
|
void doexit(int sig);
|
|
@@ -838,6 +855,10 @@ static int create_unix_socket(const char
|
|
#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
|
|
#endif
|
|
|
|
int main(argc, argv)
|
|
@@ -875,7 +896,12 @@ int main(argc, argv)
|
|
#ifndef TESTING
|
|
int fd;
|
|
#ifdef SYSLOG_INET
|
|
+#ifdef INET6
|
|
+ struct sockaddr_storage frominet;
|
|
+ char hbuf[INET6_ADDRSTRLEN];
|
|
+#else
|
|
struct sockaddr_in frominet;
|
|
+#endif
|
|
char *from;
|
|
#endif
|
|
pid_t ppid = getpid();
|
|
@@ -1204,10 +1230,21 @@ int main(argc, argv)
|
|
memset(line, 0, sizeof(line));
|
|
msglen = recvfrom(finet, line, MAXLINE - 2, 0, \
|
|
(struct sockaddr *) &frominet, &len);
|
|
+#ifdef INET6
|
|
+ if (getnameinfo((struct sockaddr *)&frominet, len,
|
|
+ hbuf, sizeof(hbuf), NULL, 0,
|
|
+ NI_NUMERICHOST)) {
|
|
+ strcpy(hbuf, "???");
|
|
+ }
|
|
+ dprintf("Message from inetd socket: #%d, host: %s\n",
|
|
+ inetm, hbuf);
|
|
+#else
|
|
+
|
|
dprintf("Message from inetd socket: #%d, host: %s\n",
|
|
inetm, inet_ntoa(frominet.sin_addr));
|
|
+#endif
|
|
if (msglen > 0) {
|
|
- from = (char *)cvthname(&frominet);
|
|
+ from = (char *)cvthname((struct sockaddr*)&frominet);
|
|
/*
|
|
* Here we could check if the host is permitted
|
|
* to send us syslog messages. We just have to
|
|
@@ -1293,18 +1330,51 @@ static int create_unix_socket(const char
|
|
static int create_inet_socket()
|
|
{
|
|
int fd, on = 1;
|
|
+#ifdef INET6
|
|
+ struct addrinfo hints, *res;
|
|
+ int error;
|
|
+#else
|
|
struct sockaddr_in sin;
|
|
+#endif
|
|
int sockflags;
|
|
|
|
+#ifdef INET6
|
|
+ fd = socket(AF_INET6, SOCK_DGRAM, 0);
|
|
+ if (fd >= 0) {
|
|
+ family = AF_INET6;
|
|
+ } else {
|
|
+ family = AF_INET;
|
|
+ dprintf("cannot create INET6 socket.\n");
|
|
+ fd = socket(AF_INET, SOCK_DGRAM, 0);
|
|
+ }
|
|
+#else
|
|
fd = socket(AF_INET, SOCK_DGRAM, 0);
|
|
+#endif
|
|
if (fd < 0) {
|
|
logerror("syslog: Unknown protocol, suspending inet service.");
|
|
return fd;
|
|
}
|
|
|
|
+#ifdef NO_BIND_AT_FORWARD_ONLY
|
|
+ if (AcceptRemote == 0)
|
|
+ return fd;
|
|
+#endif
|
|
+#ifdef INET6
|
|
+ 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));
|
|
+ close(fd);
|
|
+ return -1;
|
|
+ }
|
|
+#else
|
|
memset(&sin, 0, sizeof(sin));
|
|
sin.sin_family = AF_INET;
|
|
sin.sin_port = LogPort;
|
|
+#endif
|
|
if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, \
|
|
(char *) &on, sizeof(on)) < 0 ) {
|
|
logerror("setsockopt(REUSEADDR), suspending inet");
|
|
@@ -1329,13 +1399,77 @@ static int create_inet_socket()
|
|
close(fd);
|
|
return -1;
|
|
}
|
|
+#ifdef INET6
|
|
+ error = bind(fd, res->ai_addr, res->ai_addrlen);
|
|
+ freeaddrinfo(res);
|
|
+ if (error < 0) {
|
|
+#else
|
|
if (bind(fd, (struct sockaddr *) &sin, sizeof(sin)) < 0) {
|
|
+#endif
|
|
logerror("bind, suspending inet");
|
|
close(fd);
|
|
return -1;
|
|
}
|
|
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 **
|
|
@@ -1778,8 +1912,12 @@ void fprintlog(f, from, flags, msg)
|
|
register int l;
|
|
char line[MAXLINE + 1];
|
|
time_t fwd_suspend;
|
|
+#ifdef INET6
|
|
+ const char *errmsg;
|
|
+#else
|
|
struct hostent *hp;
|
|
#endif
|
|
+#endif
|
|
|
|
dprintf("Called fprintlog, ");
|
|
|
|
@@ -1833,22 +1971,27 @@ void fprintlog(f, from, flags, msg)
|
|
fwd_suspend);
|
|
}
|
|
break;
|
|
-
|
|
+
|
|
/*
|
|
* The trick is to wait some time, then retry to get the
|
|
* address. If that fails retry x times and then give up.
|
|
*
|
|
* You'll run into this problem mostly if the name server you
|
|
* need for resolving the address is on the same machine, but
|
|
- * is started after syslogd.
|
|
+ * is started after syslogd.
|
|
*/
|
|
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");
|
|
@@ -1859,7 +2002,9 @@ void fprintlog(f, from, flags, msg)
|
|
}
|
|
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;
|
|
@@ -1901,7 +2046,11 @@ void fprintlog(f, from, flags, msg)
|
|
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) {
|
|
+#ifdef INET6
|
|
+ family == AF_INET6 ?
|
|
+ sizeof(struct sockaddr_in6) :
|
|
+#endif
|
|
+ sizeof(f->f_un.f_forw.f_addr)) != l) {
|
|
int e = errno;
|
|
dprintf("INET sendto error: %d = %s.\n",
|
|
e, strerror(e));
|
|
@@ -2132,28 +2281,53 @@ void reapchild()
|
|
/*
|
|
* Return a printable representation of a host address.
|
|
*/
|
|
-const char *cvthname(f)
|
|
- struct sockaddr_in *f;
|
|
+const char *cvthname(struct sockaddr *f)
|
|
{
|
|
+#ifdef INET6
|
|
+ static char hname[NI_MAXHOST];
|
|
+ int error;
|
|
+#else
|
|
struct hostent *hp;
|
|
+ char *hname;
|
|
+#endif
|
|
register char *p;
|
|
int count;
|
|
|
|
- if (f->sin_family != AF_INET) {
|
|
+#ifdef INET6
|
|
+ if (((struct sockaddr *)f)->sa_family == AF_INET6 &&
|
|
+ IN6_IS_ADDR_V4MAPPED(&((struct sockaddr_in6 *)f)->sin6_addr)) {
|
|
+ ((struct sockaddr *)f)->sa_family = AF_INET;
|
|
+ ((struct sockaddr_in *)f)->sin_addr.s_addr =
|
|
+ ((struct sockaddr_in6 *)f)->sin6_addr.s6_addr32[3];
|
|
+ }
|
|
+ error = getnameinfo((struct sockaddr *)f,
|
|
+ ((struct sockaddr *)f)->sa_family == AF_INET6 ?
|
|
+ sizeof(struct sockaddr_in6)
|
|
+ : sizeof(struct sockaddr_in),
|
|
+ hname, sizeof(hname), NULL, 0, 0);
|
|
+ if (error) {
|
|
+ dprintf("Malformed from address %s\n", gai_strerror(error));
|
|
+ return ("???");
|
|
+ }
|
|
+#else
|
|
+ if (((struct sockaddr_in *)f)->sin_family != AF_INET) {
|
|
dprintf("Malformed from address.\n");
|
|
return ("???");
|
|
}
|
|
- hp = gethostbyaddr((char *) &f->sin_addr, sizeof(struct in_addr), \
|
|
- f->sin_family);
|
|
+ hp = gethostbyaddr((char *) &(((struct sockaddr_in *)&f)->sin_addr),
|
|
+ sizeof(struct in_addr),
|
|
+ ((struct sockaddr_in *)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));
|
|
+ inet_ntoa(((struct sockaddr_in *)f)->sin_addr));
|
|
+ return (inet_ntoa(((struct sockaddr_in *)f)->sin_addr));
|
|
}
|
|
+ hname = hp->h_name;
|
|
+#endif
|
|
/*
|
|
* Convert to lower case, just like LocalDomain above
|
|
*/
|
|
- for (p = (char *)hp->h_name; *p ; p++)
|
|
+ for (p = hname; *p ; p++)
|
|
if (isupper(*p))
|
|
*p = tolower(*p);
|
|
|
|
@@ -2161,17 +2335,17 @@ const char *cvthname(f)
|
|
* 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++;
|
|
}
|
|
@@ -2179,9 +2353,9 @@ const char *cvthname(f)
|
|
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++;
|
|
}
|
|
@@ -2189,7 +2363,7 @@ const char *cvthname(f)
|
|
}
|
|
}
|
|
|
|
- return (hp->h_name);
|
|
+ return (hname);
|
|
}
|
|
|
|
void domark()
|
|
@@ -2239,7 +2413,7 @@ void debug_switch()
|
|
* Print syslogd errors some place.
|
|
*/
|
|
void logerror(type)
|
|
- char *type;
|
|
+ const char *type;
|
|
{
|
|
char buf[100];
|
|
|
|
@@ -2333,6 +2507,7 @@ void init()
|
|
#else
|
|
char cline[BUFSIZ];
|
|
#endif
|
|
+#ifndef INET6 /* not */
|
|
struct servent *sp;
|
|
|
|
sp = getservbyname("syslog", "udp");
|
|
@@ -2347,6 +2522,7 @@ void init()
|
|
LogPort = 0;
|
|
} else
|
|
LogPort = sp->s_port;
|
|
+#endif
|
|
|
|
/*
|
|
* Close all open log files and free log descriptor array.
|
|
@@ -2495,6 +2671,10 @@ void init()
|
|
InetInuse = 0;
|
|
}
|
|
inetm = finet;
|
|
+#ifdef INET6
|
|
+ if (finet >= 0)
|
|
+ setup_inetaddr_all();
|
|
+#endif
|
|
#endif
|
|
|
|
Initialized = 1;
|
|
@@ -2582,7 +2762,7 @@ void cfline(line, f)
|
|
int singlpri = 0;
|
|
int ignorepri = 0;
|
|
int syncfile;
|
|
-#ifdef SYSLOG_INET
|
|
+#if defined(SYSLOG_INET) && !defined(INET6)
|
|
struct hostent *hp;
|
|
#endif
|
|
char buf[MAXLINE];
|
|
@@ -2747,6 +2927,9 @@ void cfline(line, f)
|
|
|
|
(void) strcpy(f->f_un.f_forw.f_hname, ++p);
|
|
dprintf("forwarding host: %s\n", p); /*ASP*/
|
|
+#ifdef INET6
|
|
+ f->f_type = F_FORW_UNKN;
|
|
+#else
|
|
if ( (hp = gethostbyname(p)) == NULL ) {
|
|
f->f_type = F_FORW_UNKN;
|
|
f->f_prevcount = INET_RETRY_MAX;
|
|
@@ -2761,6 +2944,7 @@ void cfline(line, f)
|
|
f->f_un.f_forw.f_addr.sin_port = LogPort;
|
|
if ( f->f_type == F_FORW )
|
|
memcpy((char *) &f->f_un.f_forw.f_addr.sin_addr, hp->h_addr, hp->h_length);
|
|
+#endif
|
|
/*
|
|
* Otherwise the host might be unknown due to an
|
|
* inaccessible nameserver (perhaps on the same
|