diff --git a/common/device.c b/common/device.c index 9131092..95a1595 100644 --- a/common/device.c +++ b/common/device.c @@ -166,7 +166,17 @@ deviceOpen(ifname, proto, trans) p->eaddr[4]= tmp.eaddr[4]; p->eaddr[5]= tmp.eaddr[5]; #endif /* DEV_NEW_CONF */ - + + switch (proto) { + case MOP_K_PROTO_RC: + pfAddMulti(-1,p->if_name,&rc_mcst[0]); + break; + case MOP_K_PROTO_DL: + pfAddMulti(-1,p->if_name,&dl_mcst[0]); + break; + default: + break; + } } } diff --git a/common/pf-linux.c b/common/pf-linux.c index f02dfef..58f7740 100644 --- a/common/pf-linux.c +++ b/common/pf-linux.c @@ -30,8 +30,10 @@ * */ +#include #include #include +#include #include #include #include @@ -94,10 +96,29 @@ struct socklist { struct ifreq ifr; extern int errno; -extern int promisc; +extern int nomulti; struct RDS RDS[NUMRDS]; +struct mcastent { + char *interface; + u_char addr[6]; + struct mcastent *next; +}; + +struct mcastent *mcastlist = NULL; +int mcastreg = 0; + +void reg_cleanup(); +void sig_cleanup(); + +volatile sig_atomic_t sig_in_progress = 0; +void (*hnd_hup)(); +void (*hnd_int)(); +void (*hnd_quit)(); +void (*hnd_segv)(); +void (*hnd_term)(); + /* * establish protocol filter * @@ -189,6 +210,33 @@ u_char *addr; return(0); } +/* + * add an interface, multicast address pair + * to the prune-on-exit list + * + */ + +void +pfRegMulti(interface, addr) +char *interface; +u_char *addr; +{ + struct mcastent **ml = &mcastlist; + + while (*ml != NULL) + ml = &((*ml)->next); + if ((*ml = malloc(sizeof(struct mcastent))) == NULL) { + syslog(LOG_ERR, "pfRegMulti: %s: malloc: %m", interface); + exit(1); + } + (*ml)->next = NULL; + if (((*ml)->interface = strdup(interface)) == NULL) { + syslog(LOG_ERR, "pfRegMulti: %s: strdup: %m", interface); + exit(1); + } + memcpy(&((*ml)->addr), addr, 6); +} + /* * add a multicast address to the interface * @@ -203,6 +251,8 @@ u_char *addr; int sock; #ifdef USE_SADDMULTI + if (nomulti) + return(0); strncpy(ifr.ifr_name, interface, sizeof (ifr.ifr_name) - 1); ifr.ifr_name[sizeof(ifr.ifr_name)] = 0; @@ -215,11 +265,6 @@ u_char *addr; } #endif UPFILT - - - ifr.ifr_addr.sa_family = AF_UNSPEC; - bcopy((char *)addr, ifr.ifr_addr.sa_data, 6); - /* * open a socket, temporarily, to use for SIOC* ioctls * @@ -228,11 +273,24 @@ u_char *addr; syslog(LOG_ERR, "pfAddMulti: %s: socket: %m", interface); return(-1); } - if (ioctl(sock, SIOCADDMULTI, (caddr_t)&ifr) < 0) { - syslog(LOG_ERR, "pfAddMulti: %s: SIOCADDMULTI: %m", interface); - close(sock); + if (ioctl(sock, SIOCGIFFLAGS, &ifr) < 0) { + syslog(LOG_ERR, "pfAddMulti: %s: SIOCGIFFLAGS: %m", interface); return(-1); } + if (ifr.ifr_flags & IFF_MULTICAST) { + if (!mcastreg) { + reg_cleanup(); + mcastreg = 1; + } + ifr.ifr_addr.sa_family = AF_UNSPEC; + bcopy((char *)addr, ifr.ifr_addr.sa_data, 6); + if (ioctl(sock, SIOCADDMULTI, (caddr_t)&ifr) < 0) { + syslog(LOG_ERR, "pfAddMulti: %s: SIOCADDMULTI: %m", interface); + close(sock); + return(-1); + } else + pfRegMulti(interface, addr); + } close(sock); #endif USE_SADDMULTI return(0); @@ -256,9 +314,6 @@ u_char *addr; strncpy(ifr.ifr_name, interface, sizeof (ifr.ifr_name) - 1); ifr.ifr_name[sizeof(ifr.ifr_name)] = 0; - ifr.ifr_addr.sa_family = AF_UNSPEC; - bcopy((char *)addr, ifr.ifr_addr.sa_data, 6); - /* * open a socket, temporarily, to use for SIOC* ioctls * @@ -267,11 +322,19 @@ u_char *addr; syslog(LOG_ERR, "pfDelMulti: %s: socket: %m", interface); return(-1); } - if (ioctl(sock, SIOCDELMULTI, (caddr_t)&ifr) < 0) { - syslog(LOG_ERR, "pfDelMulti: %s: SIOCDELMULTI: %m", interface); - close(sock); + if (ioctl(sock, SIOCGIFFLAGS, &ifr) < 0) { + syslog(LOG_ERR, "pfDelMulti: %s: SIOCGIFFLAGS: %m", interface); return(-1); } + if (ifr.ifr_flags & IFF_MULTICAST) { + ifr.ifr_addr.sa_family = AF_UNSPEC; + bcopy((char *)addr, ifr.ifr_addr.sa_data, 6); + if (ioctl(sock, SIOCDELMULTI, (caddr_t)&ifr) < 0) { + syslog(LOG_ERR, "pfDelMulti: %s: SIOCDELMULTI: %m", interface); + close(sock); + return(-1); + } + } close(sock); #endif USE_SADDMULTI @@ -279,6 +342,26 @@ u_char *addr; return(0); } +/* + * remove all registered multicast memeberships + * + */ + +void +pfPruneMulti() +{ + struct mcastent **ml = &mcastlist; + + if (!mcastreg) + return; + mcastreg = 0; + + while (*ml != NULL) { + pfDelMulti(-1, (*ml)->interface, (*ml)->addr); + ml = &((*ml)->next); + } +} + /* * return 1 if ethernet interface capable of multiple opens * @@ -360,6 +443,81 @@ u_char *buf; return(-1); } +/* + * remove all registered multicast memeberships + * when killed + * + */ + +void +sig_cleanup(sig) +int sig; +{ + void (*hnd)(); + if (sig_in_progress) + raise(sig); + sig_in_progress = 1; + + pfPruneMulti(); + + switch(sig) { + case SIGHUP: + hnd = hnd_hup; + break; + case SIGINT: + hnd = hnd_int; + break; + case SIGQUIT: + hnd = hnd_quit; + break; + case SIGSEGV: + hnd = hnd_segv; + break; + case SIGTERM: + hnd = hnd_term; + break; + default: + hnd = SIG_DFL; + break; + } + signal(sig, hnd); + raise(sig); +} + +/* + * register multicast clean-up functions + * + */ + +void +reg_cleanup() +{ + if (atexit(pfPruneMulti) < 0) { + syslog(LOG_ERR, "pfAddMulti: atexit: %m"); + exit(1); + } + if ((hnd_hup = signal(SIGHUP, sig_cleanup)) == SIG_IGN) { + signal(SIGHUP, SIG_IGN); + hnd_hup = SIG_DFL; + } + if ((hnd_int = signal(SIGINT, sig_cleanup)) == SIG_IGN) { + signal(SIGINT, SIG_IGN); + hnd_int = SIG_DFL; + } + if ((hnd_quit = signal(SIGQUIT, sig_cleanup)) == SIG_IGN) { + signal(SIGQUIT, SIG_IGN); + hnd_quit = SIG_DFL; + } + if ((hnd_segv = signal(SIGSEGV, sig_cleanup)) == SIG_IGN) { + signal(SIGSEGV, SIG_IGN); + hnd_segv = SIG_DFL; + } + if ((hnd_term = signal(SIGTERM, sig_cleanup)) == SIG_IGN) { + signal(SIGTERM, SIG_IGN); + hnd_term = SIG_DFL; + } +} + /* * Return information to device.c how to open device. * In this case the driver can handle both Ethernet type II and diff --git a/mopchk/mopchk.c b/mopchk/mopchk.c index 065132d..dbdbe25 100644 --- a/mopchk/mopchk.c +++ b/mopchk/mopchk.c @@ -60,7 +60,7 @@ void mopProcess __P((struct if_info *, u_char *)); int AllFlag = 0; /* listen on "all" interfaces */ int VersionFlag = 0; /* Show version */ -int promisc = 0; /* promisc mode not needed */ +int nomulti = 1; /* multicast mode not needed */ char *Program; extern char version[]; diff --git a/mopd/mopd.c b/mopd/mopd.c index 01f31d2..3cf31db 100644 --- a/mopd/mopd.c +++ b/mopd/mopd.c @@ -72,7 +72,7 @@ int ForegroundFlag = 0; /* run in foreground */ int VersionFlag = 0; /* print version */ int Not3Flag = 0; /* Not MOP V3 messages. */ int Not4Flag = 0; /* Not MOP V4 messages. */ -int promisc = 1; /* Need promisc mode */ +int nomulti = 0; /* Need multicast mode */ char *Program; int @@ -94,7 +94,7 @@ main(argc, argv) if (*Program == '-') Program++; - while ((c = getopt(argc, argv, "34adfv")) != EOF) + while ((c = getopt(argc, argv, "34adfmv")) != EOF) switch (c) { case '3': Not3Flag++; @@ -111,6 +111,9 @@ main(argc, argv) case 'f': ForegroundFlag++; break; + case 'm': + nomulti++; + break; case 'v': VersionFlag++; break; @@ -193,8 +196,8 @@ main(argc, argv) void Usage() { - (void) fprintf(stderr, "usage: %s -a [ -d -f -v ] [ -3 | -4 ]\n",Program); - (void) fprintf(stderr, " %s [ -d -f -v ] [ -3 | -4 ] interface\n",Program); + (void) fprintf(stderr, "usage: %s -a [ -d -f -m -v ] [ -3 | -4 ]\n",Program); + (void) fprintf(stderr, " %s [ -d -f -m -v ] [ -3 | -4 ] interface\n",Program); exit(1); } diff --git a/mopprobe/mopprobe.c b/mopprobe/mopprobe.c index f5dcc0a..1e17b77 100644 --- a/mopprobe/mopprobe.c +++ b/mopprobe/mopprobe.c @@ -69,7 +69,7 @@ int DebugFlag = 0; /* print debugging messages */ int Not3Flag = 0; /* Not MOP V3 messages */ int Not4Flag = 0; /* Not MOP V4 messages */ int oflag = 0; /* print only once */ -int promisc = 1; /* Need promisc mode */ +int nomulti = 0; /* Need multicast mode */ char *Program; int @@ -93,7 +93,7 @@ main(argc, argv) openlog(Program, LOG_PID | LOG_CONS, LOG_DAEMON); opterr = 0; - while ((op = getopt(argc, argv, "ado")) != EOF) { + while ((op = getopt(argc, argv, "admo")) != EOF) { switch (op) { case '3': Not3Flag++; @@ -107,6 +107,9 @@ main(argc, argv) case 'd': DebugFlag++; break; + case 'm': + nomulti++; + break; case 'o': oflag++; break; @@ -135,8 +138,8 @@ main(argc, argv) void Usage() { - (void) fprintf(stderr, "usage: %s -a [ -3 | -4 ]\n",Program); - (void) fprintf(stderr, " %s [ -3 | -4 ] interface\n",Program); + (void) fprintf(stderr, "usage: %s -a [ -m ] [ -3 | -4 ]\n",Program); + (void) fprintf(stderr, " %s [ -m ] [ -3 | -4 ] interface\n",Program); exit(1); } diff --git a/moptrace/moptrace.c b/moptrace/moptrace.c index 378e487..961a3a6 100644 --- a/moptrace/moptrace.c +++ b/moptrace/moptrace.c @@ -68,7 +68,7 @@ int AllFlag = 0; /* listen on "all" interfaces */ int DebugFlag = 0; /* print debugging messages */ int Not3Flag = 0; /* Ignore MOP V3 messages */ int Not4Flag = 0; /* Ignore MOP V4 messages */ -int promisc = 1; /* Need promisc mode */ +int nomulti = 0; /* Need multicast mode */ char *Program; int @@ -93,7 +93,7 @@ main(argc, argv) openlog(Program, LOG_PID | LOG_CONS, LOG_DAEMON); opterr = 0; - while ((op = getopt(argc, argv, "34ad")) != EOF) { + while ((op = getopt(argc, argv, "34adm")) != EOF) { switch (op) { case '3': Not3Flag++; @@ -107,6 +107,9 @@ main(argc, argv) case 'd': DebugFlag++; break; + case 'm': + nomulti++; + break; default: Usage(); /* NOTREACHED */ @@ -132,8 +135,8 @@ main(argc, argv) void Usage() { - (void) fprintf(stderr, "usage: %s -a [ -d ] [ -3 | -4 ]\n",Program); - (void) fprintf(stderr, " %s [ -d ] [ -3 | -4 ] interface\n", + (void) fprintf(stderr, "usage: %s -a [ -d -m ] [ -3 | -4 ]\n",Program); + (void) fprintf(stderr, " %s [ -d -m ] [ -3 | -4 ] interface\n", Program); exit(1); }