Browse code

Add iface option to --broadcast

git-svn-id: file:///var/lib/svn/clamav-devel/trunk/clamav-devel@934 77e5149b-7576-45b1-b177-96237e5ba77b

Nigel Horne authored on 2004/09/28 02:09:00
Showing 4 changed files
... ...
@@ -504,6 +504,7 @@ Changes
504 504
 0.80b	27/9/04	Added quit() routine to tidy when shutting down
505 505
 		honour HAVE_IN_ADDR_T
506 506
 		Added --broadcast option
507
+0.80c	27/9/04	Added iface option to --broadcast
507 508
 
508 509
 INTERNATIONALISATION
509 510
 
... ...
@@ -26,6 +26,9 @@
26 26
  *
27 27
  * Change History:
28 28
  * $Log: clamav-milter.c,v $
29
+ * Revision 1.134  2004/09/27 17:08:31  nigelhorne
30
+ * Add iface option to --broadcast
31
+ *
29 32
  * Revision 1.133  2004/09/27 12:43:23  nigelhorne
30 33
  * Added --broadcast
31 34
  *
... ...
@@ -410,9 +413,9 @@
410 410
  * Revision 1.6  2003/09/28 16:37:23  nigelhorne
411 411
  * Added -f flag use MaxThreads if --max-children not set
412 412
  */
413
-static	char	const	rcsid[] = "$Id: clamav-milter.c,v 1.133 2004/09/27 12:43:23 nigelhorne Exp $";
413
+static	char	const	rcsid[] = "$Id: clamav-milter.c,v 1.134 2004/09/27 17:08:31 nigelhorne Exp $";
414 414
 
415
-#define	CM_VERSION	"0.80b"
415
+#define	CM_VERSION	"0.80c"
416 416
 
417 417
 /*#define	CONFDIR	"/usr/local/etc"*/
418 418
 
... ...
@@ -444,6 +447,7 @@ static	char	const	rcsid[] = "$Id: clamav-milter.c,v 1.133 2004/09/27 12:43:23 ni
444 444
 #include <assert.h>
445 445
 #include <sys/socket.h>
446 446
 #include <netinet/in.h>
447
+#include <net/if.h>
447 448
 #include <arpa/inet.h>
448 449
 #include <sys/un.h>
449 450
 #include <stdarg.h>
... ...
@@ -641,10 +645,11 @@ static	int	bflag = 0;	/*
641 641
 				 * sender. This probably isn't a good idea
642 642
 				 * since most reply addresses will be fake
643 643
 				 */
644
-static	int	Bflag = 0;	/*
644
+static	const	char	*iface;	/*
645 645
 				 * Broadcast a message when a virus is found,
646 646
 				 * this allows remote network management
647 647
 				 */
648
+static	int	broadcastSock = -1;
648 649
 static	int	pflag = 0;	/*
649 650
 				 * Send a warning to the postmaster only,
650 651
 				 * this means user's won't be told when someone
... ...
@@ -774,7 +779,7 @@ help(void)
774 774
 
775 775
 	puts(_("\t--advisory\t\t-A\tFlag viruses rather than deleting them."));
776 776
 	puts(_("\t--bounce\t\t-b\tSend a failure message to the sender."));
777
-	puts(_("\t--broadcast\t\t-B\tBroadcast to a network manager when a virus is found."));
777
+	puts(_("\t--broadcast\t\t-B [IFACE]\tBroadcast to a network manager when a virus is found."));
778 778
 	puts(_("\t--config-file=FILE\t-c FILE\tRead configuration from FILE."));
779 779
 	puts(_("\t--debug\t\t\t-D\tPrint debug messages."));
780 780
 	puts(_("\t--dont-log-clean\t-C\tDon't add an entry to syslog that a mail is clean."));
... ...
@@ -812,7 +817,7 @@ int
812 812
 main(int argc, char **argv)
813 813
 {
814 814
 	extern char *optarg;
815
-	int i;
815
+	int i, Bflag = 0;
816 816
 	const char *cfgfile = CL_DEFAULT_CFG;
817 817
 	struct cfgstruct *cpt;
818 818
 	struct passwd *user;
... ...
@@ -860,9 +865,9 @@ main(int argc, char **argv)
860 860
 	for(;;) {
861 861
 		int opt_index = 0;
862 862
 #ifdef	CL_DEBUG
863
-		const char *args = "a:AbBc:CDfF:lm:nNop:PqQ:dhHs:St:T:U:Vx:";
863
+		const char *args = "a:AbB:c:CDfF:lm:nNop:PqQ:dhHs:St:T:U:Vx:";
864 864
 #else
865
-		const char *args = "a:AbBc:CDfF:lm:nNop:PqQ:dhHs:St:T:U:V";
865
+		const char *args = "a:AbB:c:CDfF:lm:nNop:PqQ:dhHs:St:T:U:V";
866 866
 #endif
867 867
 
868 868
 		static struct option long_options[] = {
... ...
@@ -876,7 +881,7 @@ main(int argc, char **argv)
876 876
 				"bounce", 0, NULL, 'b'
877 877
 			},
878 878
 			{
879
-				"broadcast", 0, NULL, 'B'
879
+				"broadcast", 2, NULL, 'B'
880 880
 			},
881 881
 			{
882 882
 				"config-file", 1, NULL, 'c'
... ...
@@ -983,6 +988,8 @@ main(int argc, char **argv)
983 983
 				break;
984 984
 			case 'B':	/* broadcast */
985 985
 				Bflag++;
986
+				if(optarg)
987
+					iface = optarg;
986 988
 				break;
987 989
 			case 'c':	/* where is clamd.conf? */
988 990
 				cfgfile = optarg;
... ...
@@ -1093,10 +1100,39 @@ main(int argc, char **argv)
1093 1093
 		return EX_CONFIG;
1094 1094
 	}
1095 1095
 
1096
+	if(Bflag) {
1097
+		int on;
1098
+
1099
+		broadcastSock = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
1100
+		/*
1101
+		 * SO_BROADCAST doesn't sent to all NICs on Linux, it only
1102
+		 * broadcasts on eth0, which is why there's an optional argument
1103
+		 * to --broadcast to say which NIC to broadcast on. You can use
1104
+		 * SO_BINDTODEVICE to get around that, but you need to have
1105
+		 * uid == 0 for that
1106
+		 */
1107
+		on = 1;
1108
+		if(setsockopt(broadcastSock, SOL_SOCKET, SO_BROADCAST, (int *)&on, sizeof(on)) < 0) {
1109
+			perror("setsockopt");
1110
+			return EX_UNAVAILABLE;
1111
+		}
1112
+		shutdown(broadcastSock, SHUT_RD);
1113
+	}
1114
+
1096 1115
 	/*
1097 1116
 	 * Drop privileges
1098 1117
 	 */
1099 1118
 	if(getuid() == 0) {
1119
+		if(iface) {
1120
+			struct ifreq ifr;
1121
+
1122
+			memset(&ifr, '\0', sizeof(struct ifreq));
1123
+			strncpy(ifr.ifr_name, iface, sizeof(ifr.ifr_name) - 1);
1124
+			if(setsockopt(broadcastSock, SOL_SOCKET, SO_BINDTODEVICE, &ifr, sizeof(ifr)) < 0) {
1125
+				perror(iface);
1126
+				return EX_UNAVAILABLE;
1127
+			}
1128
+		}
1100 1129
 		if((cpt = cfgopt(copt, "User")) != NULL) {
1101 1130
 			if((user = getpwnam(cpt->strarg)) == NULL) {
1102 1131
 				fprintf(stderr, _("%s: Can't get information about user %s\n"), argv[0], cpt->strarg);
... ...
@@ -1131,7 +1167,11 @@ main(int argc, char **argv)
1131 1131
 					cpt->strarg, user->pw_uid, user->pw_gid);
1132 1132
 		} else
1133 1133
 			fprintf(stderr, _("%s: running as root is not recommended (check \"User\" in clamd.conf)\n"), argv[0]);
1134
+	} else if(iface) {
1135
+		fprintf(stderr, _("%s: Only root can set an interface for --broadcast\n"), argv[0]);
1136
+		return EX_USAGE;
1134 1137
 	}
1138
+
1135 1139
 	if(advisory && quarantine) {
1136 1140
 		fprintf(stderr, _("%s: Advisory mode doesn't work with quarantine mode\n"), argv[0]);
1137 1141
 		return EX_USAGE;
... ...
@@ -2707,7 +2747,7 @@ clamfi_eom(SMFICTX *ctx)
2707 2707
 
2708 2708
 		snprintf(reject, sizeof(reject) - 1, _("%s detected by ClamAV - http://www.clamav.net"), virusname);
2709 2709
 		smfi_setreply(ctx, (char *)privdata->rejectCode, "5.7.1", reject);
2710
-		if(Bflag)
2710
+		if(broadcastSock >= 0)
2711 2711
 			broadcast(mess);
2712 2712
 	}
2713 2713
 	clamfi_cleanup(ctx);
... ...
@@ -4004,41 +4044,20 @@ quit(void)
4004 4004
 	quitting++;
4005 4005
 
4006 4006
 	if(use_syslog)
4007
-		syslog(LOG_INFO, _("Stopping: %s"), clamav_version);
4007
+		syslog(LOG_INFO, _("Stopping %s"), clamav_version);
4008 4008
 #endif
4009 4009
 }
4010 4010
 
4011 4011
 static void
4012 4012
 broadcast(const char *mess)
4013 4013
 {
4014
-	int on;
4015 4014
 	struct sockaddr_in s;
4016
-	const sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
4017
-
4018
-	if(sock < 0) {
4019
-		perror("socket");
4020
-		return;
4021
-	}
4022
-
4023
-	/*
4024
-	 * SO_BROADCAST doesn't sent to all NICs on Linux, it only broadcasts
4025
-	 * on eth0. You can use SO_BINDTODEVICE to get around that, but you
4026
-	 * need to have uid == 0 for that
4027
-	 */
4028
-	on = 1;
4029
-	if(setsockopt(sock, SOL_SOCKET, SO_BROADCAST, (int *)&on, sizeof(on)) < 0) {
4030
-		perror("setsockopt");
4031
-		close(sock);
4032
-		return;
4033
-	}
4034 4015
 
4035 4016
 	memset(&s, '\0', sizeof(struct sockaddr_in));
4036 4017
 	s.sin_family = AF_INET;
4037 4018
 	s.sin_port = (in_port_t)htons(tcpSocket);
4038 4019
 	s.sin_addr.s_addr = htonl(INADDR_BROADCAST);
4039 4020
 
4040
-	if(sendto(sock, mess, strlen(mess), 0, (struct sockaddr *)&s, sizeof(struct sockaddr_in)) < 0)
4021
+	if(sendto(broadcastSock, mess, strlen(mess), 0, (struct sockaddr *)&s, sizeof(struct sockaddr_in)) < 0)
4041 4022
 		perror("sendto");
4042
-
4043
-	close(sock);
4044 4023
 }
... ...
@@ -8,7 +8,7 @@ msgid ""
8 8
 msgstr ""
9 9
 "Project-Id-Version: PACKAGE VERSION\n"
10 10
 "Report-Msgid-Bugs-To: bugs@clamav.net\n"
11
-"POT-Creation-Date: 2004-09-27 14:10+0100\n"
11
+"POT-Creation-Date: 2004-09-27 18:07+0100\n"
12 12
 "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
13 13
 "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
14 14
 "Language-Team: LANGUAGE <LL@li.org>\n"
... ...
@@ -26,7 +26,8 @@ msgstr ""
26 26
 
27 27
 #: clamav-milter.c:779
28 28
 msgid ""
29
-"\t--broadcast\t\t-B\tBroadcast to a network manager when a virus is found."
29
+"\t--broadcast\t\t-B [IFACE]\tBroadcast to a network manager when a virus is "
30
+"found."
30 31
 msgstr ""
31 32
 
32 33
 #: clamav-milter.c:780
... ...
@@ -63,9 +63,12 @@ Send a failure message to the sender, and to the postmaster.
63 63
 fake their source address, so this option is not recommended ].
64 64
 See also \-\-noreject.
65 65
 .TP
66
-\fB\-B, \-\-broadcast\fR
66
+\fB\-B, \-\-broadcast[=<iface>]\fR
67 67
 When a virus is intercepted, broadcast a UDP message to the TCPSocket port set
68 68
 in \fBclamd.conf\fR.
69
+If the optional \fIiface\fR option is given, broadcasts will be sent on
70
+that interface. The default is set by the opertating system, usually to the
71
+first NIC.
69 72
 A future network management program (yet to be written) will intercept these
70 73
 broadcasts to raise a warning on the operator's desk.
71 74
 .TP