summaryrefslogtreecommitdiffstats
path: root/usr.sbin/faithd/faithd.c
diff options
context:
space:
mode:
Diffstat (limited to 'usr.sbin/faithd/faithd.c')
-rw-r--r--usr.sbin/faithd/faithd.c231
1 files changed, 190 insertions, 41 deletions
diff --git a/usr.sbin/faithd/faithd.c b/usr.sbin/faithd/faithd.c
index 6c4a6a4..4d4f19e 100644
--- a/usr.sbin/faithd/faithd.c
+++ b/usr.sbin/faithd/faithd.c
@@ -1,7 +1,9 @@
+/* $KAME: faithd.c,v 1.20 2000/07/01 11:40:45 itojun Exp $ */
+
/*
* Copyright (C) 1997 and 1998 WIDE Project.
* All rights reserved.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
@@ -13,7 +15,7 @@
* 3. Neither the name of the project nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
@@ -35,6 +37,7 @@
* Usage: faithd [<port> <progpath> <arg1(progname)> <arg2> ...]
* e.g. faithd telnet /usr/local/v6/sbin/telnetd telnetd
*/
+#define HAVE_GETIFADDRS
#include <sys/param.h>
#include <sys/types.h>
@@ -44,7 +47,9 @@
#include <sys/stat.h>
#include <sys/time.h>
#include <sys/ioctl.h>
+#ifdef __FreeBSD__
#include <libutil.h>
+#endif
#include <stdio.h>
#include <stdlib.h>
@@ -68,6 +73,9 @@
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
+#ifdef HAVE_GETIFADDRS
+#include <ifaddrs.h>
+#endif
#ifdef FAITH4
#include <resolv.h>
@@ -95,8 +103,11 @@ static int sockfd = 0;
#endif
int dflag = 0;
static int pflag = 0;
+static int inetd = 0;
int main __P((int, char **));
+static int inetd_main __P((int, char **));
+static int daemon_main __P((int, char **));
static void play_service __P((int));
static void play_child __P((int, struct sockaddr *));
static int faith_prefix __P((struct sockaddr *));
@@ -107,24 +118,17 @@ static int map4to6 __P((struct sockaddr_in *, struct sockaddr_in6 *));
static void sig_child __P((int));
static void sig_terminate __P((int));
static void start_daemon __P((void));
+#ifndef HAVE_GETIFADDRS
static unsigned int if_maxindex __P((void));
+#endif
static void grab_myaddrs __P((void));
static void free_myaddrs __P((void));
static void update_myaddrs __P((void));
static void usage __P((void));
int
-main(int argc, char *argv[])
+main(int argc, char **argv)
{
- struct addrinfo hints, *res;
- int s_wld, error, i, serverargc, on = 1;
- int family = AF_INET6;
- int c;
-#ifdef FAITH_NS
- char *ns;
-#endif /* FAITH_NS */
- extern int optind;
- extern char *optarg;
/*
* Initializing stuff
@@ -136,6 +140,87 @@ main(int argc, char *argv[])
else
faithdname = argv[0];
+ if (strcmp(faithdname, "faithd") != 0) {
+ inetd = 1;
+ return inetd_main(argc, argv);
+ } else
+ return daemon_main(argc, argv);
+}
+
+static int
+inetd_main(int argc, char **argv)
+{
+ char path[MAXPATHLEN];
+ struct sockaddr_storage me;
+ struct sockaddr_storage from;
+ int melen, fromlen;
+ int i;
+ int error;
+ const int on = 1;
+ char sbuf[NI_MAXSERV], snum[NI_MAXSERV];
+
+ if (strrchr(argv[0], '/') == NULL)
+ snprintf(path, sizeof(path), "%s/%s", DEFAULT_DIR, argv[0]);
+ else
+ snprintf(path, sizeof(path), "%s", argv[0]);
+
+#ifdef USE_ROUTE
+ grab_myaddrs();
+
+ sockfd = socket(PF_ROUTE, SOCK_RAW, PF_UNSPEC);
+ if (sockfd < 0) {
+ exit_error("socket(PF_ROUTE): %s", ERRSTR);
+ /*NOTREACHED*/
+ }
+#endif
+
+ melen = sizeof(me);
+ if (getsockname(STDIN_FILENO, (struct sockaddr *)&me, &melen) < 0)
+ exit_error("getsockname");
+ fromlen = sizeof(from);
+ if (getpeername(STDIN_FILENO, (struct sockaddr *)&from, &fromlen) < 0)
+ exit_error("getpeername");
+ if (getnameinfo((struct sockaddr *)&me, melen, NULL, 0,
+ sbuf, sizeof(sbuf), NI_NUMERICHOST) == 0)
+ service = sbuf;
+ else
+ service = DEFAULT_PORT_NAME;
+ if (getnameinfo((struct sockaddr *)&me, melen, NULL, 0,
+ snum, sizeof(snum), NI_NUMERICHOST) != 0)
+ snprintf(snum, sizeof(snum), "?");
+
+ snprintf(logname, sizeof(logname), "faithd %s", snum);
+ snprintf(procname, sizeof(procname), "accepting port %s", snum);
+ openlog(logname, LOG_PID | LOG_NOWAIT, LOG_DAEMON);
+
+ if (argc >= MAXARGV)
+ exit_failure("too many augments");
+ serverarg[0] = serverpath = path;
+ for (i = 1; i < argc; i++)
+ serverarg[i] = argv[i];
+ serverarg[i] = NULL;
+
+ error = setsockopt(STDIN_FILENO, SOL_SOCKET, SO_OOBINLINE, &on,
+ sizeof(on));
+ if (error < 0)
+ exit_error("setsockopt(SO_OOBINLINE): %s", ERRSTR);
+
+ play_child(STDIN_FILENO, (struct sockaddr *)&from);
+ exit_failure("should not reach here");
+ return 0; /*dummy!*/
+}
+
+static int
+daemon_main(int argc, char **argv)
+{
+ struct addrinfo hints, *res;
+ int s_wld, error, i, serverargc, on = 1;
+ int family = AF_INET6;
+ int c;
+#ifdef FAITH_NS
+ char *ns;
+#endif /* FAITH_NS */
+
while ((c = getopt(argc, argv, "dp46")) != -1) {
switch (c) {
case 'd':
@@ -191,17 +276,17 @@ main(int argc, char *argv[])
break;
default:
serverargc = argc - NUMARG;
- if (serverargc > MAXARGV)
- exit_error("too many arguments");
+ if (serverargc >= MAXARGV)
+ exit_error("too many augments");
- serverpath = malloc(strlen(argv[NUMPRG]));
+ serverpath = malloc(strlen(argv[NUMPRG]) + 1);
strcpy(serverpath, argv[NUMPRG]);
for (i = 0; i < serverargc; i++) {
- serverarg[i] = malloc(strlen(argv[i + NUMARG]));
+ serverarg[i] = malloc(strlen(argv[i + NUMARG]) + 1);
strcpy(serverarg[i], argv[i + NUMARG]);
}
serverarg[i] = NULL;
- /* FALLTHROUGH */
+ /* fall throuth */
case 1: /* no local service */
service = argv[NUMPRT];
break;
@@ -217,12 +302,8 @@ main(int argc, char *argv[])
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = 0;
error = getaddrinfo(NULL, service, &hints, &res);
- if (error) {
- fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(error));
- if (error == EAI_SYSTEM)
- exit_error("getaddrinfo: %s\n", strerror(errno));
- exit(EXIT_FAILURE);
- }
+ if (error)
+ exit_error("getaddrinfo: %s", gai_strerror(error));
s_wld = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
if (s_wld == -1)
@@ -278,10 +359,10 @@ main(int argc, char *argv[])
snprintf(logname, sizeof(logname), "faithd %s", service);
snprintf(procname, sizeof(procname), "accepting port %s", service);
openlog(logname, LOG_PID | LOG_NOWAIT, LOG_DAEMON);
- syslog(LOG_INFO, "starting faith daemon for %s port", service);
+ syslog(LOG_INFO, "Staring faith daemon for %s port", service);
play_service(s_wld);
- /*NOTREACHED*/
+ /*NOTRECHED*/
exit(1); /*pacify gcc*/
}
@@ -354,7 +435,7 @@ again:
static void
play_child(int s_src, struct sockaddr *srcaddr)
{
- struct sockaddr_storage dstaddr6;
+ struct sockaddr_storage dstaddr6;
struct sockaddr_storage dstaddr4;
char src[MAXHOSTNAMELEN];
char dst6[MAXHOSTNAMELEN];
@@ -385,10 +466,12 @@ play_child(int s_src, struct sockaddr *srcaddr)
* Local service
*/
syslog(LOG_INFO, "executing local %s", serverpath);
- dup2(s_src, 0);
- close(s_src);
- dup2(0, 1);
- dup2(0, 2);
+ if (!inetd) {
+ dup2(s_src, 0);
+ close(s_src);
+ dup2(0, 1);
+ dup2(0, 2);
+ }
execv(serverpath, serverarg);
syslog(LOG_ERR, "execv %s: %s", serverpath, ERRSTR);
_exit(EXIT_FAILURE);
@@ -597,9 +680,6 @@ map4to6(struct sockaddr_in *dst4, struct sockaddr_in6 *dst6)
if ((ai_errno = getaddrinfo(host, serv, &hints, &res)) != 0) {
syslog(LOG_INFO, "%s %s: %s", host, serv, gai_strerror(ai_errno));
- if (ai_errno == EAI_SYSTEM)
- syslog(LOG_INFO, "%s %s: %s", host, serv,
- strerror(errno));
return 0;
}
@@ -625,7 +705,7 @@ sig_child(int sig)
void
sig_terminate(int sig)
{
- syslog(LOG_INFO, "terminating faith daemon");
+ syslog(LOG_INFO, "Terminating faith daemon");
exit(EXIT_SUCCESS);
}
@@ -664,7 +744,7 @@ exit_failure(const char *fmt, ...)
va_start(ap, fmt);
vsnprintf(buf, sizeof(buf), fmt, ap);
va_end(ap);
- syslog(LOG_ERR, buf);
+ syslog(LOG_ERR, "%s", buf);
exit(EXIT_FAILURE);
}
@@ -677,11 +757,12 @@ exit_success(const char *fmt, ...)
va_start(ap, fmt);
vsnprintf(buf, sizeof(buf), fmt, ap);
va_end(ap);
- syslog(LOG_INFO, buf);
+ syslog(LOG_INFO, "%s", buf);
exit(EXIT_SUCCESS);
}
#ifdef USE_ROUTE
+#ifndef HAVE_GETIFADDRS
static unsigned int
if_maxindex()
{
@@ -696,17 +777,73 @@ if_maxindex()
if_freenameindex(p0);
return max;
}
+#endif
static void
grab_myaddrs()
{
+#ifdef HAVE_GETIFADDRS
+ struct ifaddrs *ifap, *ifa;
+ struct myaddrs *p;
+ struct sockaddr_in6 *sin6;
+
+ if (getifaddrs(&ifap) != 0) {
+ exit_failure("getifaddrs");
+ /*NOTREACHED*/
+ }
+
+ for (ifa = ifap; ifa; ifa = ifa->ifa_next) {
+ switch (ifa->ifa_addr->sa_family) {
+ case AF_INET:
+ case AF_INET6:
+ break;
+ default:
+ continue;
+ }
+
+ p = (struct myaddrs *)malloc(sizeof(struct myaddrs) +
+ ifa->ifa_addr->sa_len);
+ if (!p) {
+ exit_failure("not enough core");
+ /*NOTREACHED*/
+ }
+ memcpy(p + 1, ifa->ifa_addr, ifa->ifa_addr->sa_len);
+ p->next = myaddrs;
+ p->addr = (struct sockaddr *)(p + 1);
+#ifdef __KAME__
+ if (ifa->ifa_addr->sa_family == AF_INET6) {
+ sin6 = (struct sockaddr_in6 *)p->addr;
+ if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)
+ || IN6_IS_ADDR_SITELOCAL(&sin6->sin6_addr)) {
+ sin6->sin6_scope_id =
+ ntohs(*(u_int16_t *)&sin6->sin6_addr.s6_addr[2]);
+ sin6->sin6_addr.s6_addr[2] = 0;
+ sin6->sin6_addr.s6_addr[3] = 0;
+ }
+ }
+#endif
+ myaddrs = p;
+ if (dflag) {
+ char hbuf[NI_MAXHOST];
+ getnameinfo(p->addr, p->addr->sa_len,
+ hbuf, sizeof(hbuf), NULL, 0,
+ NI_NUMERICHOST);
+ syslog(LOG_INFO, "my interface: %s %s", hbuf,
+ ifa->ifa_name);
+ }
+ }
+
+ freeifaddrs(ifap);
+#else
int s;
unsigned int maxif;
struct ifreq *iflist;
struct ifconf ifconf;
- struct ifreq *ifr, *ifr_end;
+ struct ifreq *ifr, *ifrp, *ifr_end;
struct myaddrs *p;
struct sockaddr_in6 *sin6;
+ size_t siz;
+ char ifrbuf[sizeof(struct ifreq) + 1024];
maxif = if_maxindex() + 1;
iflist = (struct ifreq *)malloc(maxif * BUFSIZ); /* XXX */
@@ -730,10 +867,21 @@ grab_myaddrs()
/* Look for this interface in the list */
ifr_end = (struct ifreq *) (ifconf.ifc_buf + ifconf.ifc_len);
- for (ifr = ifconf.ifc_req;
- ifr < ifr_end;
- ifr = (struct ifreq *) ((char *) &ifr->ifr_addr
- + ifr->ifr_addr.sa_len)) {
+ for (ifrp = ifconf.ifc_req;
+ ifrp < ifr_end;
+ ifrp = (struct ifreq *)((char *)ifrp + siz)) {
+ memcpy(ifrbuf, ifrp, sizeof(*ifrp));
+ ifr = (struct ifreq *)ifrbuf;
+ siz = ifr->ifr_addr.sa_len;
+ if (siz < sizeof(ifr->ifr_addr))
+ siz = sizeof(ifr->ifr_addr);
+ siz += (sizeof(*ifrp) - sizeof(ifr->ifr_addr));
+ if (siz > sizeof(ifrbuf)) {
+ /* ifr too big */
+ break;
+ }
+ memcpy(ifrbuf, ifrp, siz);
+
switch (ifr->ifr_addr.sa_family) {
case AF_INET:
case AF_INET6:
@@ -773,6 +921,7 @@ grab_myaddrs()
}
free(iflist);
+#endif
}
static void
OpenPOWER on IntegriCloud