X-Git-Url: https://git.whamcloud.com/?a=blobdiff_plain;f=lnet%2Futils%2Facceptor.c;h=a270ad2b7e4828ed336e5745aab325ed6f3a3e13;hb=93040866f878e6fa4e64e4d84dd84632bc1b33c2;hp=e5bb46b0b5e37787f1afd0cffded78e1bf7f8367;hpb=00f255b8c00dff66481a6ab22391869217b5d8af;p=fs%2Flustre-release.git diff --git a/lnet/utils/acceptor.c b/lnet/utils/acceptor.c index e5bb46b..a270ad2 100644 --- a/lnet/utils/acceptor.c +++ b/lnet/utils/acceptor.c @@ -12,6 +12,8 @@ #include #include #include +#include +#include #include #ifdef HAVE_LIBWRAP #include @@ -27,74 +29,170 @@ /* should get this from autoconf somehow */ #ifndef PIDFILE_DIR #define PIDFILE_DIR "/var/run" -#endif +#endif -#define PROGNAME "acceptor" +char progname[] = "acceptor"; +char name_port[40]; /* for signal handler */ #ifdef HAVE_LIBWRAP /* needed because libwrap declares these as externs */ -int allow_severity = LOG_INFO; -int deny_severity = LOG_WARNING; +int allow_severity = LOG_INFO; +int deny_severity = LOG_WARNING; #endif -void create_pidfile(char *name, int port) +void usage(char *progname) +{ + fprintf(stderr, "usage: %s [-N nal_id] [-p] [-l] port\n\n" + " -l\tKeep stdin/stdout open\n" + " -p\tAllow connections from non-privileged ports\n", progname); + exit (1); +} + +void errlog(int level, const char *fmt, ...) +{ + va_list arg; + FILE *out; + + switch (level) { + case LOG_DEBUG: + case LOG_INFO: + case LOG_NOTICE: + out = stdout; + break; + default: + out = stderr; + break; + } + va_start(arg, fmt); + fprintf(out, "%s: ", name_port); + vfprintf(out, fmt, arg); + va_end(arg); + va_start(arg, fmt); + vsyslog(level, fmt, arg); + va_end(arg); +} + +char *pidfile_name(char *name_port) +{ + static char pidfile[1024]; + + snprintf(pidfile, sizeof(pidfile), "%s/%s.pid", PIDFILE_DIR, name_port); + + return pidfile; +} + +int pidfile_create(char *name_port) { - char pidfile[1024]; - FILE *fp; - - snprintf(pidfile, sizeof(pidfile), "%s/%s-%d.pid", - PIDFILE_DIR, name, port); - - if ((fp = fopen(pidfile, "w"))) { - fprintf(fp, "%d\n", getpid()); - fclose(fp); + char *pidfile = pidfile_name(name_port); + int fd, rc; + + if ((fd = open(pidfile, O_CREAT | O_WRONLY)) >= 0) { + char pid[16]; + int size = snprintf(pid, sizeof(pid), "%u\n", getpid()); + if (write(fd, pid, size) != size) { + /* hard error or short write */ + rc = errno ? : EIO; + } else { + rc = 0; + } + close(fd); } else { - syslog(LOG_ERR, "%s: %s\n", pidfile, - strerror(errno)); + rc = errno; } + + if (rc) + errlog(LOG_ERR, " error creating %s: %s\n", + pidfile, strerror(rc)); + + return rc; +} + +int pidfile_cleanup(char *name_port) +{ + char *pidfile = pidfile_name(name_port); + int rc; + + rc = unlink(pidfile); + if (rc && errno != -ENOENT) + fprintf(stderr, "%s: error removing %s: %s\n", + progname, pidfile, strerror(errno)); + errlog(LOG_NOTICE, "exiting\n"); + + return errno; } -int pidfile_exists(char *name, int port) +int pidfile_exists(char *name_port) { - char pidfile[1024]; - - snprintf(pidfile, sizeof(pidfile), "%s/%s-%d.pid", - PIDFILE_DIR, name, port); - - if (!access(pidfile, F_OK)) { - fprintf(stderr, "%s: exists, acceptor already running.\n", - pidfile); + char *pidfile = pidfile_name(name_port); + FILE *fpid; + int pid, rc; + + fpid = fopen(pidfile, "r+"); + if (fpid == NULL) { + if (errno == ENOENT) + return 0; + + fprintf(stderr, "%s: error opening %s: %s.\n", + progname, pidfile, strerror(errno)); return (1); - } + } + + rc = fscanf(fpid, "%i", &pid); + fclose(fpid); + if (rc != 1) { + fprintf(stderr,"%s: %s didn't contain a valid pid, removing.\n", + progname, pidfile); + goto stale; + } + + if (kill(pid, 0) == 0) { + fprintf(stderr, "%s: %s exists, acceptor pid %d running.\n", + progname, pidfile, pid); + return (1); + } + + fprintf(stderr, "%s: stale %s exists, pid %d doesn't, removing.\n", + progname, pidfile, pid); +stale: + pidfile_cleanup(name_port); return (0); } -void -show_connection (int fd, __u32 net_ip) +void handler(int sig) +{ + exit(sig); +} + +void atexit_handler(void) { - struct hostent *h = gethostbyaddr ((char *)&net_ip, sizeof net_ip, AF_INET); - __u32 host_ip = ntohl (net_ip); + pidfile_cleanup(name_port); +} + +void show_connection(int fd, __u32 net_ip) +{ + static long last_time; + static __u32 host_ip; + long now = time(0); + struct hostent *h; int len; char host[1024]; - + + /* Don't show repeats for same host, it adds no value */ + if (host_ip == ntohl(net_ip) && (now - last_time) < 5) + return; + + h = gethostbyaddr((char *)&net_ip, sizeof(net_ip), AF_INET); + last_time = now; + host_ip = ntohl(net_ip); + if (h == NULL) - snprintf (host, sizeof(host), "%d.%d.%d.%d", (host_ip >> 24) & 0xff, - (host_ip >> 16) & 0xff, (host_ip >> 8) & 0xff, host_ip & 0xff); + snprintf(host, sizeof(host), "%d.%d.%d.%d", + (host_ip >> 24) & 0xff, (host_ip >> 16) & 0xff, + (host_ip >> 8) & 0xff, host_ip & 0xff); else - snprintf (host, sizeof(host), "%s", h->h_name); - - syslog (LOG_INFO, "Accepted host: %s\n", host); -} + snprintf(host, sizeof(host), "%s", h->h_name); -void -usage (char *myname) -{ - fprintf (stderr, - "Usage: %s [-N nal_id] [-p] [-l] port\n\n" - " -l\tKeep stdin/stdout open\n" - " -p\tAllow connections from non-privileged ports\n", - myname); - exit (1); + syslog(LOG_INFO, "accepted host: %s\n", host); } int main(int argc, char **argv) @@ -106,7 +204,7 @@ int main(int argc, char **argv) int nal = SOCKNAL; int rport; int require_privports = 1; - + while ((c = getopt (argc, argv, "N:lp")) != -1) { switch (c) { case 'N': @@ -131,8 +229,10 @@ int main(int argc, char **argv) port = atol(argv[optind++]); - if (pidfile_exists(PROGNAME, port)) - exit(1); + snprintf(name_port, sizeof(name_port) - 1, "%s-%d", progname, port); + if (pidfile_exists(name_port)) + return(EEXIST); + openlog(name_port, LOG_PID, LOG_DAEMON); memset(&srvaddr, 0, sizeof(srvaddr)); srvaddr.sin_family = AF_INET; @@ -141,43 +241,56 @@ int main(int argc, char **argv) fd = socket(PF_INET, SOCK_STREAM, 0); if (fd < 0) { - perror("opening socket"); - exit(1); + rc = errno; + errlog(LOG_ERR, "error opening socket: %s\n", strerror(errno)); + return(rc); } o = 1; if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &o, sizeof(o))) { - perror("Cannot set REUSEADDR socket opt"); - exit(1); + rc = errno; + errlog(LOG_ERR, "cannot set REUSEADDR socket opt: %s\n", + strerror(errno)); + return(rc); } rc = bind(fd, (struct sockaddr *)&srvaddr, sizeof(srvaddr)); - if ( rc == -1 ) { - perror("bind: "); - exit(1); + if (rc == -1) { + rc = errno; + errlog(LOG_ERR, "error binding to socket: %s\n", + strerror(errno)); + return(rc); } if (listen(fd, 127)) { + rc = errno; perror("listen: "); - exit(1); + return(rc); } - fprintf(stderr, "listening on port %d\n", port); + printf("listening on port %d\n", port); pfd = open("/dev/portals", O_RDWR); - if ( pfd < 0 ) { - perror("opening portals device"); - exit(1); + if (pfd < 0) { + rc = errno; + errlog(LOG_ERR, "opening portals device: %s\n",strerror(errno)); + return(rc); } rc = daemon(0, noclose); if (rc < 0) { - perror("daemon(): "); - exit(1); + rc = errno; + errlog(LOG_ERR, "error daemonizing: %s\n", strerror(errno)); + return(rc); } - openlog(PROGNAME, LOG_PID, LOG_DAEMON); - syslog(LOG_INFO, "started, listening on port %d\n", port); - create_pidfile(PROGNAME, port); + signal(SIGHUP, SIG_IGN); + signal(SIGINT, handler); + signal(SIGQUIT, handler); + signal(SIGTERM, handler); + + errlog(LOG_NOTICE, "started, listening on port %d\n", port); + if (pidfile_create(name_port) == 0) + atexit(atexit_handler); while (1) { struct sockaddr_in clntaddr; @@ -189,32 +302,32 @@ int main(int argc, char **argv) struct request_info request; #endif char addrstr[INET_ADDRSTRLEN]; - + cfd = accept(fd, (struct sockaddr *)&clntaddr, &len); - if ( cfd < 0 ) { - perror("accept"); - exit(0); - continue; + if (cfd < 0) { + errlog(LOG_ERR, "error accepting connection: %s\n", + strerror(errno)); + break; + //continue; } + inet_ntop(AF_INET, &clntaddr.sin_addr, addrstr,INET_ADDRSTRLEN); #ifdef HAVE_LIBWRAP /* libwrap access control */ request_init(&request, RQ_DAEMON, "lustre", RQ_FILE, cfd, 0); sock_host(&request); if (!hosts_access(&request)) { - inet_ntop(AF_INET, &clntaddr.sin_addr, - addrstr, INET_ADDRSTRLEN); - syslog(LOG_WARNING, "Unauthorized access from %s:%hd\n", + errlog(LOG_WARNING, "unauthorized access from %s:%hd\n", addrstr, ntohs(clntaddr.sin_port)); close (cfd); continue; } #endif - if (require_privports && ntohs(clntaddr.sin_port) >= IPPORT_RESERVED) { - inet_ntop(AF_INET, &clntaddr.sin_addr, - addrstr, INET_ADDRSTRLEN); - syslog(LOG_ERR, "Closing non-privileged connection from %s:%d\n", + if (require_privports && + ntohs(clntaddr.sin_port) >= IPPORT_RESERVED) { + errlog(LOG_ERR, + "closing non-privileged connection from %s:%d\n", addrstr, ntohs(clntaddr.sin_port)); rc = close(cfd); if (rc) @@ -228,22 +341,23 @@ int main(int argc, char **argv) pcfg.pcfg_nal = nal; pcfg.pcfg_fd = cfd; pcfg.pcfg_misc = SOCKNAL_CONN_NONE; /* == incoming connection */ - + PORTAL_IOC_INIT(data); data.ioc_pbuf1 = (char*)&pcfg; data.ioc_plen1 = sizeof(pcfg); - + if (ioctl(pfd, IOC_PORTAL_NAL_CMD, &data) < 0) { - perror("ioctl failed"); + errlog(LOG_ERR, "portals ioctl failed for %s: %s\n", + addrstr, strerror(errno)); } else { - printf("client registered\n"); + errlog(LOG_DEBUG, "client %s registered\n", addrstr); } rc = close(cfd); if (rc) - perror ("close failed"); + perror("close failed"); } closelog(); - exit(0); + return (0); }