X-Git-Url: http://dolda2000.com/gitweb/?a=blobdiff_plain;f=src%2Fmctap.c;h=9d183f983e1340a1c755bf93c022d377b353638d;hb=8cac99017b835d215e0b90e54ddf478000fe559a;hp=472af0124ca4e12cbf3a47fad3d9c6f337cd81de;hpb=4969792065275ee0b997a4fa8841b00a93781a8e;p=mctap.git diff --git a/src/mctap.c b/src/mctap.c index 472af01..9d183f9 100644 --- a/src/mctap.c +++ b/src/mctap.c @@ -11,12 +11,16 @@ #include #include #include +#include +#include #include "utils.h" +static int quit = 0; + static void usage(FILE *out) { - fprintf(out, "usage: mctap [-h] [-D TAPNAME] MCASTGROUP PORT\n"); + fprintf(out, "usage: mctap [-hdpk] [-P PIDFILE] [-D TAPNAME] MCASTGROUP PORT\n"); } static __attribute__ ((unused)) char *formataddress(struct sockaddr *arg, socklen_t arglen) @@ -118,7 +122,7 @@ static void bridge(int sock, int tap, struct sockaddr *dst, socklen_t dstlen) fcntl(sock, F_SETFL, fcntl(sock, F_GETFL) | O_NONBLOCK); fcntl(tap, F_SETFL, fcntl(tap, F_GETFL) | O_NONBLOCK); - while(1) { + while(!quit) { pfds[0].fd = sock; pfds[0].events = POLLIN; pfds[1].fd = tap; @@ -126,7 +130,7 @@ static void bridge(int sock, int tap, struct sockaddr *dst, socklen_t dstlen) ret = poll(pfds, 2, -1); if(ret < 0) { if(errno != EINTR) { - fprintf(stderr, "mctap: poll: %s\n", strerror(errno)); + syslog(LOG_ERR, "mctap: poll: %s", strerror(errno)); exit(1); } continue; @@ -135,7 +139,7 @@ static void bridge(int sock, int tap, struct sockaddr *dst, socklen_t dstlen) ret = read(sock, buf, sizeof(buf)); if(ret < 0) { if((errno != EINTR) && (errno != EAGAIN)) { - fprintf(stderr, "mctap: mcast packet: %s\n", strerror(errno)); + syslog(LOG_ERR, "mctap: mcast packet: %s", strerror(errno)); exit(1); } } else { @@ -146,7 +150,7 @@ static void bridge(int sock, int tap, struct sockaddr *dst, socklen_t dstlen) pi.flags = 0; pi.proto = 0; memcpy(buf, &pi, sizeof(pi)); - write(tap, buf, ret); + write(tap, buf, sizeof(pi) + ret); } } } @@ -154,7 +158,7 @@ static void bridge(int sock, int tap, struct sockaddr *dst, socklen_t dstlen) ret = read(tap, buf, sizeof(buf)); if(ret < 0) { if((errno != EINTR) && (errno != EAGAIN)) { - fprintf(stderr, "mctap: mcast packet: %s\n", strerror(errno)); + syslog(LOG_ERR, "mctap: mcast packet: %s", strerror(errno)); exit(1); } } else { @@ -188,6 +192,35 @@ static int maketap(char *name) return(fd); } +static void sighand(int sig) +{ + switch(sig) { + case SIGINT: + case SIGTERM: + quit = 1; + break; + case SIGHUP: + break; + } +} + +static void killrunning(char *pidfile) +{ + FILE *pidfd; + int pid; + + if((pidfd = fopen(pidfile, "r")) == NULL) { + fprintf(stderr, "mctab -k: could not read PID file %s: %s\n", pidfile, strerror(errno)); + exit(1); + } + fscanf(pidfd, "%i", &pid); + if(kill(pid, SIGTERM)) { + fprintf(stderr, "mctab -k: could not kill %i: %s\n", pid, strerror(errno)); + exit(1); + } + fclose(pidfd); +} + int main(int argc, char **argv) { int c; @@ -195,14 +228,33 @@ int main(int argc, char **argv) struct in_addr group; int port; char *tapname; + char *pidfile; + int daemonize, killold; struct sockaddr_in dst; + FILE *pidfd; tapname = "mctap"; - while((c = getopt(argc, argv, "hD:")) >= 0) { + daemonize = killold = 0; + pidfile = NULL; + while((c = getopt(argc, argv, "hD:dpP:k")) >= 0) { switch(c) { case 'D': tapname = optarg; break; + case 'd': + daemonize = 1; + break; + case 'p': + pidfile = (void *)-1; + break; + case 'P': + pidfile = optarg; + break; + case 'k': + killold = 1; + if(pidfile == NULL) + pidfile = (void *)-1; + break; case 'h': usage(stdout); return(0); @@ -211,6 +263,12 @@ int main(int argc, char **argv) exit(1); } } + if(pidfile == (void *)-1) + pidfile = sprintf2("/var/run/mctap.%s.pid", tapname); + if(killold) { + killrunning(pidfile); + return(0); + } if(argc - optind < 2) { usage(stderr); exit(1); @@ -228,11 +286,32 @@ int main(int argc, char **argv) fprintf(stderr, "mctap: could not create TAP device: %s\n", strerror(errno)); exit(1); } + openlog(sprintf2("mctap-%s", tapname), LOG_PID, LOG_DAEMON); + + pidfd = NULL; + if((pidfile != NULL) && ((pidfd = fopen(pidfile, "w")) == NULL)) { + fprintf(stderr, "mctap: could not create PID file %s: %s\n", pidfile, strerror(errno)); + exit(1); + } + if(daemonize) + daemon(0, 0); + if(pidfd != NULL) { + fprintf(pidfd, "%i\n", getpid()); + fclose(pidfd); + } + + signal(SIGTERM, sighand); + signal(SIGINT, sighand); + signal(SIGHUP, sighand); memset(&dst, 0, sizeof(dst)); dst.sin_family = AF_INET; dst.sin_addr = group; dst.sin_port = htons(port); bridge(sock, tap, (struct sockaddr *)&dst, sizeof(dst)); + syslog(LOG_INFO, "exiting"); + + if(pidfile != NULL) + unlink(pidfile); return(0); }