#!/usr/bin/perl ################## # Copyright (c) 2003, Anthony Volodkin # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # 1. Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # 2. Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE # ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS # OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) # HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY # OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF # SUCH DAMAGE. ################### # Rewrites diverted UDP broadcasts to be sent directly to certain hosts. #note that the custom Net::Divert is required. Maybe it will be v0.02? use Net::Divert; use NetPacket::IP qw(IP_PROTO_UDP); use NetPacket::UDP; #this is the list of all desired recipients of the received broadcast packets. @master_target_list=("10.10.10.2", "192.168.44.2" ); #target_list is the dynamic array where each entry that #already received a packet is removed. @target_list=@master_target_list; #makes a DIVERT socket on host 192.168.1.1 port 9999 and defines the handler function $divobj = Net::Divert->new('192.168.1.1',9999); $divobj->getPackets(\&alterPacket); sub alterPacket { #separate the packet from the ipfw rule tag my ($data, $fwtag) = @_; #create proper IP and UDP objects for packet processing $ip_obj = NetPacket::IP->decode($data); $udp_obj = NetPacket::UDP->decode($ip_obj->{data}); #not really necessary but it does make sure this is a #udp packet. if($ip_obj->{proto} == IP_PROTO_UDP) { #if there is more than 1 ip left in the array -- #this matters because depending on the number of #elements in the array, we have to either reinitialize it #and tell the Divert module that this is our last packet to be copied #or send another packet. if ( $target_list[1] ) { $ip = shift(@target_list); #makes sure we dont send the packet where it came from unless ($ip eq $ip_obj->{src_ip}) { #changes the destination ip to one from the array #and recalculates the checksums, etc of the packet $ip_obj->{dest_ip}=$ip; $ip_obj->{data} = $udp_obj->encode($ip_obj); $data= $ip_obj->encode; #the 1 in the arguments indicates there are more #packet copies to follow. $divobj->putPacket($data,$fwtag,1); } else { #get rid of it by sending to localhost. $ip_obj->{dest_ip}="127.0.0.1"; $ip_obj->{data} = $udp_obj->encode($ip_obj); $data= $ip_obj->encode; $divobj->putPacket($data,$fwtag,1); } #if the array is empty, then load it with a copy of master_target_list #and start anew. This occurs when the program is started or #when a _BRAND_NEW_ packet is received. } elsif (! $target_list[0]) { @target_list=@master_target_list; $ip = shift(@target_list); unless ($ip eq $ip_obj->{src_ip}) { $ip_obj->{dest_ip}=$ip; $ip_obj->{data} = $udp_obj->encode($ip_obj); $data= $ip_obj->encode; $divobj->putPacket($data,$fwtag,1); } else { $ip_obj->{dest_ip}="127.0.0.1"; $ip_obj->{data} = $udp_obj->encode($ip_obj); $data= $ip_obj->encode; $divobj->putPacket($data,$fwtag,1); } #we have exactly 1 destination left to send to } else { $ip = shift(@target_list); unless ($ip eq $ip_obj->{src_ip}) { $ip_obj->{dest_ip}=$ip; $ip_obj->{data} = $udp_obj->encode($ip_obj); $data= $ip_obj->encode; #the 0 is set to indicate that this is the last packet #in the series of re-transmissions to different hosts. #the module discards the packet and then waits for a new one. $divobj->putPacket($data,$fwtag,0); } else { $ip_obj->{dest_ip}="127.0.0.1"; $ip_obj->{data} = $udp_obj->encode($ip_obj); $data= $ip_obj->encode; $divobj->putPacket($data,$fwtag,0); } } } }