8 require './access_list.pl';
15 vec($bits, fileno($fh), 1) = 1;
20 # used for rate limiting
24 sub cache_cidrlookup {
25 my ($addr, $net) = @_;
26 my $key = $addr . " " . $net;
28 if (!exists($cidrcache{$key})) {
29 $cidrcache{$key} = Net::CIDR::cidrlookup($addr, $net);
31 return $cidrcache{$key};
38 if (!exists($rangecache{$net})) {
39 ($rangecache{$net}) = Net::CIDR::cidr2range($net);
42 return $rangecache{$net};
45 open LOG, ">>", "mbd.log";
47 my @ports = mbd::find_all_ports();
49 # Open a socket for each port
51 my $udp = getprotobyname("udp");
54 socket($sock, PF_INET, SOCK_DGRAM, $udp);
55 bind($sock, sockaddr_in($p, INADDR_ANY));
59 my $sendsock = Net::RawIP->new({udp => {}});
61 print "Listening on " . scalar @ports . " ports.\n";
65 my $rin = fhbits(@socks);
68 my $nfound = select($rout=$rin, undef, undef, undef);
69 for my $sock (@socks) {
70 next unless (vec($rout, fileno($sock), 1) == 1);
73 my $addr = recv($sock, $data, 8192, 0); # jumbo broadcast! :-P
74 my ($sport, $saddr) = sockaddr_in($addr);
75 my ($dport, $daddr) = sockaddr_in(getsockname($sock));
76 my $size = length($data);
79 my $now = [Time::HiRes::gettimeofday];
80 if (exists($last_sent{$saddr}{$dport})) {
81 my $elapsed = Time::HiRes::tv_interval($last_sent{$saddr}{$dport}, $now);
83 print LOG "$dport $size 2\n";
84 print inet_ntoa($saddr), ", $dport, $size bytes => rate-limited ($elapsed secs since last)\n";
89 # We don't get the packet's destination address, but I guess this should do...
90 # Check against the ACL.
92 for my $rule (@Config::access_list) {
93 next unless (mbd::match_ranges($dport, $rule->{'ports'}));
94 next unless (mbd::match_ranges($size, $rule->{'sizes'}));
96 if ($rule->{'filter'}) {
97 next unless ($rule->{'filter'}($data));
104 print LOG "$dport $size $pass\n";
107 print inet_ntoa($saddr), ", $dport, $size bytes => filtered\n";
111 $last_sent{$saddr}{$dport} = $now;
115 for my $net (@Config::networks) {
116 next if (cache_cidrlookup(inet_ntoa($saddr), $net));
118 my ($range) = cache_cidrrange($net);
124 saddr => inet_ntoa($saddr),
136 print inet_ntoa($saddr), ", $dport, $size bytes => ($num_nets networks)\n";