syslogd/sysklogd-ipv6.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