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... | ... |
@@ -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 |