7 require './access_list.pl';
14 vec($bits, fileno($fh), 1) = 1;
20 sub cache_cidrlookup {
21 my ($addr, $net) = @_;
22 my $key = $addr . " " . $net;
24 if (!exists($cidrcache{$key})) {
25 $cidrcache{$key} = Net::CIDR::cidrlookup($addr, $net);
27 return $cidrcache{$key};
34 if (!exists($rangecache{$net})) {
35 ($rangecache{$net}) = Net::CIDR::cidr2range($net);
38 return $rangecache{$net};
41 open LOG, ">>", "mbd.log";
43 my @ports = mbd::find_all_ports();
45 # Open a socket for each port
47 my $udp = getprotobyname("udp");
50 socket($sock, PF_INET, SOCK_DGRAM, $udp);
51 bind($sock, sockaddr_in($p, INADDR_ANY));
55 my $sendsock = Net::RawIP->new({udp => {}});
57 print "Listening on " . scalar @ports . " ports.\n";
61 my $rin = fhbits(@socks);
64 my $nfound = select($rout=$rin, undef, undef, undef);
65 for my $sock (@socks) {
66 next unless (vec($rout, fileno($sock), 1) == 1);
69 my $addr = recv($sock, $data, 8192, 0); # jumbo broadcast! :-P
70 my ($sport, $saddr) = sockaddr_in($addr);
71 my ($dport, $daddr) = sockaddr_in(getsockname($sock));
72 my $size = length($data);
74 # We don't get the packet's destination address, but I guess this should do...
75 # Check against the ACL.
77 for my $rule (@Config::access_list) {
78 next unless (mbd::match_ranges($dport, $rule->{'ports'}));
79 next unless (mbd::match_ranges($size, $rule->{'sizes'}));
81 if ($rule->{'filter'}) {
82 next unless ($rule->{'filter'}($data));
89 print LOG "$dport $size $pass\n";
92 print "$dport, $size bytes => filtered\n";
97 for my $net (@Config::networks) {
98 next if (cache_cidrlookup(inet_ntoa($saddr), $net));
100 my ($range) = cache_cidrrange($net);
104 print inet_ntoa($saddr), ", $dport, $size bytes => $broadcast\n";
108 saddr => inet_ntoa($saddr),