Net-ARP-1.0.12/0000755000175000017500000000000014236677036011745 5ustar bastibastiNet-ARP-1.0.12/README0000755000175000017500000000236714236656561012640 0ustar bastibasti-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- Net::ARP Programmed by Bastian Ballmann Web: http://www.codekid.net Mail: balle@codekid.net -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- ---:[ Description This module is a Perl extension to create and send ARP packets and lookup local or remote mac addresses. You do not need to install any additional libraries like Libnet to compile this extension. It uses kernel header files to create the packets. ---:[ Installation To install this module type the following: perl Makefile.PL make make test make install ---:[ Usage Please read the POD documentation: perldoc Net::ARP. If you've still any questions feel free to ask. ---:[ Want to contribute? Please drop me a mail and if you want to submit patches please generate them using "diff -Nru" on the latest version or use the exellent github pull request feature! https://github.com/balle/Net-ARP There is also the possibility to use the CPAN bugtracker https://rt.cpan.org Last but not least new code for new features should be commented and I like test code ;) ---:[ COPYRIGHT AND LICENCE Copyright (C) 2004-2022 by Bastian Ballmann This software is licensed under GPLv2 Net-ARP-1.0.12/test.pl0000755000175000017500000000271714236664374013274 0ustar bastibasti#!/usr/bin/perl # # Perl ARP Extension test file # # Programmed by Bastian Ballmann # Last update: 28.04.2020 # # This program is free software; you can redistribute # it and/or modify it under the terms of the # GNU General Public License version 2 as published # by the Free Software Foundation. # # This program is distributed in the hope that it will # be useful, but WITHOUT ANY WARRANTY; without even # the implied warranty of MERCHANTABILITY or FITNESS # FOR A PARTICULAR PURPOSE. # See the GNU General Public License for more details. use ExtUtils::testlib; use Net::ARP; BEGIN { eval{ require Net::Pcap; }; if($@ =~ /^Can\'t\slocate/) { $dev = "enp3s0f1"; } else { import Net::Pcap; $dev = Net::Pcap::lookupdev(\$errbuf); } } print "Sending ARP reply packet via dev $dev... "; $ret = Net::ARP::send_packet($dev, # network interface '127.0.0.1', # source ip '127.0.0.1', # destination ip 'aa:bb:cc:aa:bb:cc', # source mac 'ff:ff:ff:ff:ff:ff', # destination mac 'reply'); # ARP operation print $ret ? "ok\n" : "failed\n"; $mac = Net::ARP::get_mac($dev); print "MAC $mac\n"; $mac = Net::ARP::arp_lookup($dev, "192.168.1.1"); print "192.168.1.1 has got mac $mac\n"; Net-ARP-1.0.12/Makefile.PL0000755000175000017500000000250114236676604013720 0ustar bastibasti# # Perl ARP Extension makefile # # Programmed by Bastian Ballmann # Last update: 27.04.2020 # # This program is free software; you can redistribute # it and/or modify it under the terms of the # GNU General Public License version 2 as published # by the Free Software Foundation. # # This program is distributed in the hope that it will # be useful, but WITHOUT ANY WARRANTY; without even # the implied warranty of MERCHANTABILITY or FITNESS # FOR A PARTICULAR PURPOSE. # See the GNU General Public License for more details. use ExtUtils::MakeMaker; use Config; BEGIN { eval { require Net::Pcap }; if($@) { print "Module Net::Pcap is required for make test!\n"; } } if($Config{'osname'} =~ /linux/i) { $flags = "-DLINUX"; $objects = "ARP.o send_packet_linux.o get_mac_linux.o arp_lookup_linux.o"; } elsif($Config{'osname'} =~ /bsd|darwin/i) { $flags = "-DBSD"; $objects = "ARP.o send_packet_bsd.o get_mac_bsd.o arp_lookup_bsd.o"; } else { $flags = "-DBSD"; $objects = "ARP.o get_mac_bsd.o arp_lookup_bsd.o"; } WriteMakefile( NAME => 'Net::ARP', VERSION => '1.0.12', AUTHOR => 'Bastian Ballmann', DEFINE => $flags, OBJECT => $objects, TEST_REQUIRES => { "Net::Pcap" => 0, } ); Net-ARP-1.0.12/ARP.pm0000755000175000017500000000654514236666552012743 0ustar bastibasti# # Perl ARP Extension # # Programmed by Bastian Ballmann # Last update: 11.05.2022 # # This program is free software; you can redistribute # it and/or modify it under the terms of the # GNU General Public License version 2 as published # by the Free Software Foundation. # # This program is distributed in the hope that it will # be useful, but WITHOUT ANY WARRANTY; without even # the implied warranty of MERCHANTABILITY or FITNESS # FOR A PARTICULAR PURPOSE. # See the GNU General Public License for more details. package Net::ARP; use strict; use warnings; require Exporter; our @ISA = qw(Exporter); # Items to export into callers namespace by default. Note: do not export # names by default without a very good reason. Use EXPORT_OK instead. # Do not simply export all your public functions/methods/constants. # This allows declaration use ARP ':all'; # If you do not need this, moving things directly into @EXPORT or @EXPORT_OK # will save memory. our %EXPORT_TAGS = ( 'all' => [ qw( ) ] ); our @EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} } ); our @EXPORT = qw( ); our $VERSION = '1.0.12'; require XSLoader; XSLoader::load('Net::ARP', $VERSION); # Preloaded methods go here. 1; __END__ =head1 NAME ARP - Perl extension for creating ARP packets =head1 SYNOPSIS use Net::ARP; Net::ARP::send_packet('lo', # Device '127.0.0.1', # Source IP '127.0.0.1', # Destination IP 'aa:bb:cc:aa:bb:cc', # Source MAC 'aa:bb:cc:aa:bb:cc', # Destinaton MAC 'reply'); # ARP operation $mac = Net::ARP::get_mac("enp3s0f1"); print "$mac\n"; $mac = Net::ARP::arp_lookup($dev,"192.168.1.1"); print "192.168.1.1 has got mac $mac\n"; =head2 IMPORTANT Version 1.0 will break with the API of PRE-1.0 versions, because the return value of arp_lookup() and get_mac() will no longer be passed as parameter, but returned! I hope this decision is ok as long as we get a cleaner and more perlish API. =head2 DESCRIPTION This module can be used to create and send ARP packets and to get the mac address of an ethernet interface or ip address. =over =item B Net::ARP::send_packet('lo', # Device '127.0.0.1', # Source IP '127.0.0.1', # Destination IP 'aa:bb:cc:aa:bb:cc', # Source MAC 'aa:bb:cc:aa:bb:cc', # Destinaton MAC 'reply'); # ARP operation I think this is self documentating. ARP operation can be one of the following values: request, reply, revrequest, revreply, invrequest, invreply. =item B $mac = Net::ARP::get_mac("enp3s0f1"); This gets the MAC address of the enp3s0f1 interface and stores it in the variable $mac. The return value is "unknown" if the mac cannot be looked up. =item B $mac = Net::ARP::arp_lookup($dev,"192.168.1.1"); This looks up the MAC address for the ip address 192.168.1.1 and stores it in the variable $mac. The return value is "unknown" if the mac cannot be looked up. =back =head1 SEE ALSO man -a arp =head1 AUTHOR Bastian Ballmann [ balle@codekid.net ] http://www.codekid.net =head1 COPYRIGHT AND LICENSE Copyright (C) 2004-2022 by Bastian Ballmann License: GPLv2 =cut Net-ARP-1.0.12/send_packet_bsd.c0000755000175000017500000000260414236671555015226 0ustar bastibasti/* Perl ARP Extension Send the packet BSD code Programmed by Bastian Ballmann Last update: 11.05.2022 This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License version 2 as published by the Free Software Foundation. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. */ #include #include #include #include #include #include #include #include #include #include "arp.h" int send_packet_bsd(const char *dev, u_char *packet, u_int packetsize) { int bpffd, i; char bpfdev[12]; if( (strlen(dev) == 0) || (packetsize == 0) ) return 0; // Open a bpf device for(i = 0; i < 512; i++) { sprintf(bpfdev, "/dev/bpf%d", i); if((bpffd = open(bpfdev, O_WRONLY)) > 0) { break; } } if(bpffd < 0) { perror("open bpf"); return 0; } else { // Lock it flock(bpffd, LOCK_EX); // Bind it to a device ioctl(bpffd, BIOCSETIF, dev); // Send the packet and unlock write(bpffd, packet, packetsize); flock(bpffd, LOCK_UN); close(bpffd); } return 1; } Net-ARP-1.0.12/get_mac_linux.c0000755000175000017500000000356214236655773014744 0ustar bastibasti/* Perl ARP Extension Get the MAC address of an interface Linux code Programmed by Bastian Ballmann Last update: 11.05.2022 This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License version 2 as published by the Free Software Foundation. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. */ #include #include #include #include #include #include #include #include #include "arp.h" int get_mac_linux(const char *dev, char *mac) { int sock; struct ifreq iface; if ( !strlen(mac) || !strlen(dev) ) return -1; /* Set hardware address as unknown */ strncpy(mac,"unknown", HEX_HW_ADDR_LEN); mac[HEX_HW_ADDR_LEN - 1] = '\0'; /* Copy device name into the ifreq strcture so that we can look for its * hardware address through an ioctl request */ strncpy(iface.ifr_name, dev, IFNAMSIZ); iface.ifr_name[IFNAMSIZ - 1] = '\0'; // Open a socket if((sock = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { perror("socket"); return -1; } else { // Get the interface hardware address if((ioctl(sock, SIOCGIFHWADDR, &iface)) < 0) { perror("ioctl SIOCGIFHWADDR"); close(sock); return -1; } else { sprintf(mac,"%02x:%02x:%02x:%02x:%02x:%02x", iface.ifr_hwaddr.sa_data[0] & 0xff, iface.ifr_hwaddr.sa_data[1] & 0xff, iface.ifr_hwaddr.sa_data[2] & 0xff, iface.ifr_hwaddr.sa_data[3] & 0xff, iface.ifr_hwaddr.sa_data[4] & 0xff, iface.ifr_hwaddr.sa_data[5] & 0xff); } } close(sock); return 0; } Net-ARP-1.0.12/META.json0000644000175000017500000000157014236677036013371 0ustar bastibasti{ "abstract" : "unknown", "author" : [ "Bastian Ballmann" ], "dynamic_config" : 1, "generated_by" : "ExtUtils::MakeMaker version 7.44, CPAN::Meta::Converter version 2.150010", "license" : [ "unknown" ], "meta-spec" : { "url" : "http://search.cpan.org/perldoc?CPAN::Meta::Spec", "version" : 2 }, "name" : "Net-ARP", "no_index" : { "directory" : [ "t", "inc" ] }, "prereqs" : { "build" : { "requires" : { "ExtUtils::MakeMaker" : "0" } }, "configure" : { "requires" : { "ExtUtils::MakeMaker" : "0" } }, "test" : { "requires" : { "Net::Pcap" : "0" } } }, "release_status" : "stable", "version" : "v1.0.12", "x_serialization_backend" : "JSON::PP version 4.04" } Net-ARP-1.0.12/ppport.h0000755000175000017500000006232114236653565013452 0ustar bastibasti /* ppport.h -- Perl/Pollution/Portability Version 2.007 * * Automatically Created by Devel::PPPort on Fri Oct 24 16:45:45 2003 * * Do NOT edit this file directly! -- Edit PPPort.pm instead. * * Version 2.x, Copyright (C) 2001, Paul Marquess. * Version 1.x, Copyright (C) 1999, Kenneth Albanowski. * This code may be used and distributed under the same license as any * version of Perl. * * This version of ppport.h is designed to support operation with Perl * installations back to 5.004, and has been tested up to 5.8.1. * * If this version of ppport.h is failing during the compilation of this * module, please check if a newer version of Devel::PPPort is available * on CPAN before sending a bug report. * * If you are using the latest version of Devel::PPPort and it is failing * during compilation of this module, please send a report to perlbug@perl.com * * Include all following information: * * 1. The complete output from running "perl -V" * * 2. This file. * * 3. The name & version of the module you were trying to build. * * 4. A full log of the build that failed. * * 5. Any other information that you think could be relevant. * * * For the latest version of this code, please retreive the Devel::PPPort * module from CPAN. * */ /* If you use one of a few functions that were not present in earlier * versions of Perl, please add a define before the inclusion of ppport.h * for a static include, or use the GLOBAL request in a single module to * produce a global definition that can be referenced from the other * modules. * * Function: Static define: Extern define: * newCONSTSUB() NEED_newCONSTSUB NEED_newCONSTSUB_GLOBAL * */ /* To verify whether ppport.h is needed for your module, and whether any * special defines should be used, ppport.h can be run through Perl to check * your source code. Simply say: * * perl -x ppport.h *.c *.h *.xs foo/bar*.c [etc] * * The result will be a list of patches suggesting changes that should at * least be acceptable, if not necessarily the most efficient solution, or a * fix for all possible problems. It won't catch where dTHR is needed, and * doesn't attempt to account for global macro or function definitions, * nested includes, typemaps, etc. * * In order to test for the need of dTHR, please try your module under a * recent version of Perl that has threading compiled-in. * */ /* #!/usr/bin/perl @ARGV = ("*.xs") if !@ARGV; %badmacros = %funcs = %macros = (); $replace = 0; foreach () { $funcs{$1} = 1 if /Provide:\s+(\S+)/; $macros{$1} = 1 if /^#\s*define\s+([a-zA-Z0-9_]+)/; $replace = $1 if /Replace:\s+(\d+)/; $badmacros{$2}=$1 if $replace and /^#\s*define\s+([a-zA-Z0-9_]+).*?\s+([a-zA-Z0-9_]+)/; $badmacros{$1}=$2 if /Replace (\S+) with (\S+)/; } foreach $filename (map(glob($_),@ARGV)) { unless (open(IN, "<$filename")) { warn "Unable to read from $file: $!\n"; next; } print "Scanning $filename...\n"; $c = ""; while () { $c .= $_; } close(IN); $need_include = 0; %add_func = (); $changes = 0; $has_include = ($c =~ /#.*include.*ppport/m); foreach $func (keys %funcs) { if ($c =~ /#.*define.*\bNEED_$func(_GLOBAL)?\b/m) { if ($c !~ /\b$func\b/m) { print "If $func isn't needed, you don't need to request it.\n" if $changes += ($c =~ s/^.*#.*define.*\bNEED_$func\b.*\n//m); } else { print "Uses $func\n"; $need_include = 1; } } else { if ($c =~ /\b$func\b/m) { $add_func{$func} =1 ; print "Uses $func\n"; $need_include = 1; } } } if (not $need_include) { foreach $macro (keys %macros) { if ($c =~ /\b$macro\b/m) { print "Uses $macro\n"; $need_include = 1; } } } foreach $badmacro (keys %badmacros) { if ($c =~ /\b$badmacro\b/m) { $changes += ($c =~ s/\b$badmacro\b/$badmacros{$badmacro}/gm); print "Uses $badmacros{$badmacro} (instead of $badmacro)\n"; $need_include = 1; } } if (scalar(keys %add_func) or $need_include != $has_include) { if (!$has_include) { $inc = join('',map("#define NEED_$_\n", sort keys %add_func)). "#include \"ppport.h\"\n"; $c = "$inc$c" unless $c =~ s/#.*include.*XSUB.*\n/$&$inc/m; } elsif (keys %add_func) { $inc = join('',map("#define NEED_$_\n", sort keys %add_func)); $c = "$inc$c" unless $c =~ s/^.*#.*include.*ppport.*$/$inc$&/m; } if (!$need_include) { print "Doesn't seem to need ppport.h.\n"; $c =~ s/^.*#.*include.*ppport.*\n//m; } $changes++; } if ($changes) { open(OUT,">/tmp/ppport.h.$$"); print OUT $c; close(OUT); open(DIFF, "diff -u $filename /tmp/ppport.h.$$|"); while () { s!/tmp/ppport\.h\.$$!$filename.patched!; print STDOUT; } close(DIFF); unlink("/tmp/ppport.h.$$"); } else { print "Looks OK\n"; } } __DATA__ */ #ifndef _P_P_PORTABILITY_H_ #define _P_P_PORTABILITY_H_ #ifndef PERL_REVISION # ifndef __PATCHLEVEL_H_INCLUDED__ # include # endif # if !(defined(PERL_VERSION) || (SUBVERSION > 0 && defined(PATCHLEVEL))) # include # endif # ifndef PERL_REVISION # define PERL_REVISION (5) /* Replace: 1 */ # define PERL_VERSION PATCHLEVEL # define PERL_SUBVERSION SUBVERSION /* Replace PERL_PATCHLEVEL with PERL_VERSION */ /* Replace: 0 */ # endif #endif #define PERL_BCDVERSION ((PERL_REVISION * 0x1000000L) + (PERL_VERSION * 0x1000L) + PERL_SUBVERSION) /* It is very unlikely that anyone will try to use this with Perl 6 (or greater), but who knows. */ #if PERL_REVISION != 5 # error ppport.h only works with Perl version 5 #endif /* PERL_REVISION != 5 */ #ifndef ERRSV # define ERRSV perl_get_sv("@",FALSE) #endif #if (PERL_VERSION < 4) || ((PERL_VERSION == 4) && (PERL_SUBVERSION <= 5)) /* Replace: 1 */ # define PL_Sv Sv # define PL_compiling compiling # define PL_copline copline # define PL_curcop curcop # define PL_curstash curstash # define PL_defgv defgv # define PL_dirty dirty # define PL_dowarn dowarn # define PL_hints hints # define PL_na na # define PL_perldb perldb # define PL_rsfp_filters rsfp_filters # define PL_rsfpv rsfp # define PL_stdingv stdingv # define PL_sv_no sv_no # define PL_sv_undef sv_undef # define PL_sv_yes sv_yes /* Replace: 0 */ #endif #ifndef dNOOP # define NOOP (void)0 #endif #ifndef dTHR # define dTHR dNOOP #endif #ifndef dTHX # define dTHX dNOOP # define dTHXa(x) dNOOP # define dTHXoa(x) dNOOP #endif #ifndef pTHX # define pTHX void # define pTHX_ # define aTHX # define aTHX_ #endif /* IV could also be a quad (say, a long long), but Perls * capable of those should have IVSIZE already. */ #if !defined(IVSIZE) && defined(LONGSIZE) # define IVSIZE LONGSIZE #endif #ifndef IVSIZE # define IVSIZE 4 /* A bold guess, but the best we can make. */ #endif #ifndef UVSIZE # define UVSIZE IVSIZE #endif #ifndef NVTYPE # if defined(USE_LONG_DOUBLE) && defined(HAS_LONG_DOUBLE) # define NVTYPE long double # else # define NVTYPE double # endif typedef NVTYPE NV; #endif #ifndef INT2PTR #if (IVSIZE == PTRSIZE) && (UVSIZE == PTRSIZE) # define PTRV UV # define INT2PTR(any,d) (any)(d) #else # if PTRSIZE == LONGSIZE # define PTRV unsigned long # else # define PTRV unsigned # endif # define INT2PTR(any,d) (any)(PTRV)(d) #endif #define NUM2PTR(any,d) (any)(PTRV)(d) #define PTR2IV(p) INT2PTR(IV,p) #define PTR2UV(p) INT2PTR(UV,p) #define PTR2NV(p) NUM2PTR(NV,p) #if PTRSIZE == LONGSIZE # define PTR2ul(p) (unsigned long)(p) #else # define PTR2ul(p) INT2PTR(unsigned long,p) #endif #endif /* !INT2PTR */ #ifndef boolSV # define boolSV(b) ((b) ? &PL_sv_yes : &PL_sv_no) #endif #ifndef gv_stashpvn # define gv_stashpvn(str,len,flags) gv_stashpv(str,flags) #endif #ifndef newSVpvn # define newSVpvn(data,len) ((len) ? newSVpv ((data), (len)) : newSVpv ("", 0)) #endif #ifndef newRV_inc /* Replace: 1 */ # define newRV_inc(sv) newRV(sv) /* Replace: 0 */ #endif /* DEFSV appears first in 5.004_56 */ #ifndef DEFSV # define DEFSV GvSV(PL_defgv) #endif #ifndef SAVE_DEFSV # define SAVE_DEFSV SAVESPTR(GvSV(PL_defgv)) #endif #ifndef newRV_noinc # ifdef __GNUC__ # define newRV_noinc(sv) \ ({ \ SV *nsv = (SV*)newRV(sv); \ SvREFCNT_dec(sv); \ nsv; \ }) # else # if defined(USE_THREADS) static SV * newRV_noinc (SV * sv) { SV *nsv = (SV*)newRV(sv); SvREFCNT_dec(sv); return nsv; } # else # define newRV_noinc(sv) \ (PL_Sv=(SV*)newRV(sv), SvREFCNT_dec(sv), (SV*)PL_Sv) # endif # endif #endif /* Provide: newCONSTSUB */ /* newCONSTSUB from IO.xs is in the core starting with 5.004_63 */ #if (PERL_VERSION < 4) || ((PERL_VERSION == 4) && (PERL_SUBVERSION < 63)) #if defined(NEED_newCONSTSUB) static #else extern void newCONSTSUB(HV * stash, char * name, SV *sv); #endif #if defined(NEED_newCONSTSUB) || defined(NEED_newCONSTSUB_GLOBAL) void newCONSTSUB(stash,name,sv) HV *stash; char *name; SV *sv; { U32 oldhints = PL_hints; HV *old_cop_stash = PL_curcop->cop_stash; HV *old_curstash = PL_curstash; line_t oldline = PL_curcop->cop_line; PL_curcop->cop_line = PL_copline; PL_hints &= ~HINT_BLOCK_SCOPE; if (stash) PL_curstash = PL_curcop->cop_stash = stash; newSUB( #if (PERL_VERSION < 3) || ((PERL_VERSION == 3) && (PERL_SUBVERSION < 22)) /* before 5.003_22 */ start_subparse(), #else # if (PERL_VERSION == 3) && (PERL_SUBVERSION == 22) /* 5.003_22 */ start_subparse(0), # else /* 5.003_23 onwards */ start_subparse(FALSE, 0), # endif #endif newSVOP(OP_CONST, 0, newSVpv(name,0)), newSVOP(OP_CONST, 0, &PL_sv_no), /* SvPV(&PL_sv_no) == "" -- GMB */ newSTATEOP(0, Nullch, newSVOP(OP_CONST, 0, sv)) ); PL_hints = oldhints; PL_curcop->cop_stash = old_cop_stash; PL_curstash = old_curstash; PL_curcop->cop_line = oldline; } #endif #endif /* newCONSTSUB */ #ifndef START_MY_CXT /* * Boilerplate macros for initializing and accessing interpreter-local * data from C. All statics in extensions should be reworked to use * this, if you want to make the extension thread-safe. See ext/re/re.xs * for an example of the use of these macros. * * Code that uses these macros is responsible for the following: * 1. #define MY_CXT_KEY to a unique string, e.g. "DynaLoader_guts" * 2. Declare a typedef named my_cxt_t that is a structure that contains * all the data that needs to be interpreter-local. * 3. Use the START_MY_CXT macro after the declaration of my_cxt_t. * 4. Use the MY_CXT_INIT macro such that it is called exactly once * (typically put in the BOOT: section). * 5. Use the members of the my_cxt_t structure everywhere as * MY_CXT.member. * 6. Use the dMY_CXT macro (a declaration) in all the functions that * access MY_CXT. */ #if defined(MULTIPLICITY) || defined(PERL_OBJECT) || \ defined(PERL_CAPI) || defined(PERL_IMPLICIT_CONTEXT) /* This must appear in all extensions that define a my_cxt_t structure, * right after the definition (i.e. at file scope). The non-threads * case below uses it to declare the data as static. */ #define START_MY_CXT #if (PERL_VERSION < 4 || (PERL_VERSION == 4 && PERL_SUBVERSION < 68 )) /* Fetches the SV that keeps the per-interpreter data. */ #define dMY_CXT_SV \ SV *my_cxt_sv = perl_get_sv(MY_CXT_KEY, FALSE) #else /* >= perl5.004_68 */ #define dMY_CXT_SV \ SV *my_cxt_sv = *hv_fetch(PL_modglobal, MY_CXT_KEY, \ sizeof(MY_CXT_KEY)-1, TRUE) #endif /* < perl5.004_68 */ /* This declaration should be used within all functions that use the * interpreter-local data. */ #define dMY_CXT \ dMY_CXT_SV; \ my_cxt_t *my_cxtp = INT2PTR(my_cxt_t*,SvUV(my_cxt_sv)) /* Creates and zeroes the per-interpreter data. * (We allocate my_cxtp in a Perl SV so that it will be released when * the interpreter goes away.) */ #define MY_CXT_INIT \ dMY_CXT_SV; \ /* newSV() allocates one more than needed */ \ my_cxt_t *my_cxtp = (my_cxt_t*)SvPVX(newSV(sizeof(my_cxt_t)-1));\ Zero(my_cxtp, 1, my_cxt_t); \ sv_setuv(my_cxt_sv, PTR2UV(my_cxtp)) /* This macro must be used to access members of the my_cxt_t structure. * e.g. MYCXT.some_data */ #define MY_CXT (*my_cxtp) /* Judicious use of these macros can reduce the number of times dMY_CXT * is used. Use is similar to pTHX, aTHX etc. */ #define pMY_CXT my_cxt_t *my_cxtp #define pMY_CXT_ pMY_CXT, #define _pMY_CXT ,pMY_CXT #define aMY_CXT my_cxtp #define aMY_CXT_ aMY_CXT, #define _aMY_CXT ,aMY_CXT #else /* single interpreter */ #define START_MY_CXT static my_cxt_t my_cxt; #define dMY_CXT_SV dNOOP #define dMY_CXT dNOOP #define MY_CXT_INIT NOOP #define MY_CXT my_cxt #define pMY_CXT void #define pMY_CXT_ #define _pMY_CXT #define aMY_CXT #define aMY_CXT_ #define _aMY_CXT #endif #endif /* START_MY_CXT */ #ifndef IVdf # if IVSIZE == LONGSIZE # define IVdf "ld" # define UVuf "lu" # define UVof "lo" # define UVxf "lx" # define UVXf "lX" # else # if IVSIZE == INTSIZE # define IVdf "d" # define UVuf "u" # define UVof "o" # define UVxf "x" # define UVXf "X" # endif # endif #endif #ifndef NVef # if defined(USE_LONG_DOUBLE) && defined(HAS_LONG_DOUBLE) && \ defined(PERL_PRIfldbl) /* Not very likely, but let's try anyway. */ # define NVef PERL_PRIeldbl # define NVff PERL_PRIfldbl # define NVgf PERL_PRIgldbl # else # define NVef "e" # define NVff "f" # define NVgf "g" # endif #endif #ifndef AvFILLp /* Older perls (<=5.003) lack AvFILLp */ # define AvFILLp AvFILL #endif #ifdef SvPVbyte # if PERL_REVISION == 5 && PERL_VERSION < 7 /* SvPVbyte does not work in perl-5.6.1, borrowed version for 5.7.3 */ # undef SvPVbyte # define SvPVbyte(sv, lp) \ ((SvFLAGS(sv) & (SVf_POK|SVf_UTF8)) == (SVf_POK) \ ? ((lp = SvCUR(sv)), SvPVX(sv)) : my_sv_2pvbyte(aTHX_ sv, &lp)) static char * my_sv_2pvbyte(pTHX_ register SV *sv, STRLEN *lp) { sv_utf8_downgrade(sv,0); return SvPV(sv,*lp); } # endif #else # define SvPVbyte SvPV #endif #ifndef SvPV_nolen # define SvPV_nolen(sv) \ ((SvFLAGS(sv) & (SVf_POK)) == SVf_POK \ ? SvPVX(sv) : sv_2pv_nolen(sv)) static char * sv_2pv_nolen(pTHX_ register SV *sv) { STRLEN n_a; return sv_2pv(sv, &n_a); } #endif #ifndef get_cv # define get_cv(name,create) perl_get_cv(name,create) #endif #ifndef get_sv # define get_sv(name,create) perl_get_sv(name,create) #endif #ifndef get_av # define get_av(name,create) perl_get_av(name,create) #endif #ifndef get_hv # define get_hv(name,create) perl_get_hv(name,create) #endif #ifndef call_argv # define call_argv perl_call_argv #endif #ifndef call_method # define call_method perl_call_method #endif #ifndef call_pv # define call_pv perl_call_pv #endif #ifndef call_sv # define call_sv perl_call_sv #endif #ifndef PERL_SCAN_GREATER_THAN_UV_MAX # define PERL_SCAN_GREATER_THAN_UV_MAX 0x02 #endif #ifndef PERL_SCAN_SILENT_ILLDIGIT # define PERL_SCAN_SILENT_ILLDIGIT 0x04 #endif #ifndef PERL_SCAN_ALLOW_UNDERSCORES # define PERL_SCAN_ALLOW_UNDERSCORES 0x01 #endif #ifndef PERL_SCAN_DISALLOW_PREFIX # define PERL_SCAN_DISALLOW_PREFIX 0x02 #endif #if (PERL_VERSION >= 6) #define I32_CAST #else #define I32_CAST (I32*) #endif #ifndef grok_hex static UV _grok_hex (char *string, STRLEN *len, I32 *flags, NV *result) { NV r = scan_hex(string, *len, I32_CAST len); if (r > UV_MAX) { *flags |= PERL_SCAN_GREATER_THAN_UV_MAX; if (result) *result = r; return UV_MAX; } return (UV)r; } # define grok_hex(string, len, flags, result) \ _grok_hex((string), (len), (flags), (result)) #endif #ifndef grok_oct static UV _grok_oct (char *string, STRLEN *len, I32 *flags, NV *result) { NV r = scan_oct(string, *len, I32_CAST len); if (r > UV_MAX) { *flags |= PERL_SCAN_GREATER_THAN_UV_MAX; if (result) *result = r; return UV_MAX; } return (UV)r; } # define grok_oct(string, len, flags, result) \ _grok_oct((string), (len), (flags), (result)) #endif #ifndef grok_bin static UV _grok_bin (char *string, STRLEN *len, I32 *flags, NV *result) { NV r = scan_bin(string, *len, I32_CAST len); if (r > UV_MAX) { *flags |= PERL_SCAN_GREATER_THAN_UV_MAX; if (result) *result = r; return UV_MAX; } return (UV)r; } # define grok_bin(string, len, flags, result) \ _grok_bin((string), (len), (flags), (result)) #endif #ifndef IN_LOCALE # define IN_LOCALE \ (PL_curcop == &PL_compiling ? IN_LOCALE_COMPILETIME : IN_LOCALE_RUNTIME) #endif #ifndef IN_LOCALE_RUNTIME # define IN_LOCALE_RUNTIME (PL_curcop->op_private & HINT_LOCALE) #endif #ifndef IN_LOCALE_COMPILETIME # define IN_LOCALE_COMPILETIME (PL_hints & HINT_LOCALE) #endif #ifndef IS_NUMBER_IN_UV # define IS_NUMBER_IN_UV 0x01 # define IS_NUMBER_GREATER_THAN_UV_MAX 0x02 # define IS_NUMBER_NOT_INT 0x04 # define IS_NUMBER_NEG 0x08 # define IS_NUMBER_INFINITY 0x10 # define IS_NUMBER_NAN 0x20 #endif #ifndef grok_numeric_radix # define GROK_NUMERIC_RADIX(sp, send) grok_numeric_radix(sp, send) #define grok_numeric_radix Perl_grok_numeric_radix bool Perl_grok_numeric_radix(pTHX_ const char **sp, const char *send) { #ifdef USE_LOCALE_NUMERIC #if (PERL_VERSION >= 6) if (PL_numeric_radix_sv && IN_LOCALE) { STRLEN len; char* radix = SvPV(PL_numeric_radix_sv, len); if (*sp + len <= send && memEQ(*sp, radix, len)) { *sp += len; return TRUE; } } #else /* pre5.6.0 perls don't have PL_numeric_radix_sv so the radix * must manually be requested from locale.h */ #include struct lconv *lc = localeconv(); char *radix = lc->decimal_point; if (radix && IN_LOCALE) { STRLEN len = strlen(radix); if (*sp + len <= send && memEQ(*sp, radix, len)) { *sp += len; return TRUE; } } #endif /* PERL_VERSION */ #endif /* USE_LOCALE_NUMERIC */ /* always try "." if numeric radix didn't match because * we may have data from different locales mixed */ if (*sp < send && **sp == '.') { ++*sp; return TRUE; } return FALSE; } #endif /* grok_numeric_radix */ #ifndef grok_number #define grok_number Perl_grok_number int Perl_grok_number(pTHX_ const char *pv, STRLEN len, UV *valuep) { const char *s = pv; const char *send = pv + len; const UV max_div_10 = UV_MAX / 10; const char max_mod_10 = UV_MAX % 10; int numtype = 0; int sawinf = 0; int sawnan = 0; while (s < send && isSPACE(*s)) s++; if (s == send) { return 0; } else if (*s == '-') { s++; numtype = IS_NUMBER_NEG; } else if (*s == '+') s++; if (s == send) return 0; /* next must be digit or the radix separator or beginning of infinity */ if (isDIGIT(*s)) { /* UVs are at least 32 bits, so the first 9 decimal digits cannot overflow. */ UV value = *s - '0'; /* This construction seems to be more optimiser friendly. (without it gcc does the isDIGIT test and the *s - '0' separately) With it gcc on arm is managing 6 instructions (6 cycles) per digit. In theory the optimiser could deduce how far to unroll the loop before checking for overflow. */ if (++s < send) { int digit = *s - '0'; if (digit >= 0 && digit <= 9) { value = value * 10 + digit; if (++s < send) { digit = *s - '0'; if (digit >= 0 && digit <= 9) { value = value * 10 + digit; if (++s < send) { digit = *s - '0'; if (digit >= 0 && digit <= 9) { value = value * 10 + digit; if (++s < send) { digit = *s - '0'; if (digit >= 0 && digit <= 9) { value = value * 10 + digit; if (++s < send) { digit = *s - '0'; if (digit >= 0 && digit <= 9) { value = value * 10 + digit; if (++s < send) { digit = *s - '0'; if (digit >= 0 && digit <= 9) { value = value * 10 + digit; if (++s < send) { digit = *s - '0'; if (digit >= 0 && digit <= 9) { value = value * 10 + digit; if (++s < send) { digit = *s - '0'; if (digit >= 0 && digit <= 9) { value = value * 10 + digit; if (++s < send) { /* Now got 9 digits, so need to check each time for overflow. */ digit = *s - '0'; while (digit >= 0 && digit <= 9 && (value < max_div_10 || (value == max_div_10 && digit <= max_mod_10))) { value = value * 10 + digit; if (++s < send) digit = *s - '0'; else break; } if (digit >= 0 && digit <= 9 && (s < send)) { /* value overflowed. skip the remaining digits, don't worry about setting *valuep. */ do { s++; } while (s < send && isDIGIT(*s)); numtype |= IS_NUMBER_GREATER_THAN_UV_MAX; goto skip_value; } } } } } } } } } } } } } } } } } } numtype |= IS_NUMBER_IN_UV; if (valuep) *valuep = value; skip_value: if (GROK_NUMERIC_RADIX(&s, send)) { numtype |= IS_NUMBER_NOT_INT; while (s < send && isDIGIT(*s)) /* optional digits after the radix */ s++; } } else if (GROK_NUMERIC_RADIX(&s, send)) { numtype |= IS_NUMBER_NOT_INT | IS_NUMBER_IN_UV; /* valuep assigned below */ /* no digits before the radix means we need digits after it */ if (s < send && isDIGIT(*s)) { do { s++; } while (s < send && isDIGIT(*s)); if (valuep) { /* integer approximation is valid - it's 0. */ *valuep = 0; } } else return 0; } else if (*s == 'I' || *s == 'i') { s++; if (s == send || (*s != 'N' && *s != 'n')) return 0; s++; if (s == send || (*s != 'F' && *s != 'f')) return 0; s++; if (s < send && (*s == 'I' || *s == 'i')) { s++; if (s == send || (*s != 'N' && *s != 'n')) return 0; s++; if (s == send || (*s != 'I' && *s != 'i')) return 0; s++; if (s == send || (*s != 'T' && *s != 't')) return 0; s++; if (s == send || (*s != 'Y' && *s != 'y')) return 0; s++; } sawinf = 1; } else if (*s == 'N' || *s == 'n') { /* XXX TODO: There are signaling NaNs and quiet NaNs. */ s++; if (s == send || (*s != 'A' && *s != 'a')) return 0; s++; if (s == send || (*s != 'N' && *s != 'n')) return 0; s++; sawnan = 1; } else return 0; if (sawinf) { numtype &= IS_NUMBER_NEG; /* Keep track of sign */ numtype |= IS_NUMBER_INFINITY | IS_NUMBER_NOT_INT; } else if (sawnan) { numtype &= IS_NUMBER_NEG; /* Keep track of sign */ numtype |= IS_NUMBER_NAN | IS_NUMBER_NOT_INT; } else if (s < send) { /* we can have an optional exponent part */ if (*s == 'e' || *s == 'E') { /* The only flag we keep is sign. Blow away any "it's UV" */ numtype &= IS_NUMBER_NEG; numtype |= IS_NUMBER_NOT_INT; s++; if (s < send && (*s == '-' || *s == '+')) s++; if (s < send && isDIGIT(*s)) { do { s++; } while (s < send && isDIGIT(*s)); } else return 0; } } while (s < send && isSPACE(*s)) s++; if (s >= send) return numtype; if (len == 10 && memEQ(pv, "0 but true", 10)) { if (valuep) *valuep = 0; return IS_NUMBER_IN_UV; } return 0; } #endif /* grok_number */ #endif /* _P_P_PORTABILITY_H_ */ /* End of File ppport.h */ Net-ARP-1.0.12/arp.h0000755000175000017500000000421314236672354012701 0ustar bastibasti/* Perl ARP Extension header file Programmed by Bastian Ballmann Last update: 11.05.2022 This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License version 2 as published by the Free Software Foundation. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. */ #define ARPOP_REQUEST 1 #define ARPOP_REPLY 2 #define ARPOP_REVREQUEST 3 #define ARPOP_REVREPLY 4 #define ARPOP_INVREQUEST 8 #define ARPOP_INVREPLY 9 #define ARPHDR_ETHER 1 #ifndef ETH_ALEN #define ETH_ALEN 6 #endif #ifndef ETH_P_IP #define ETH_P_IP 0x0800 #endif #ifndef ETH_P_ARP #define ETH_P_ARP 0x0806 #endif #ifndef ETH_P_ALL #define ETH_P_ALL 0x0000 #endif #define IP_ALEN 4 /* Length of the hardware address in the standard hex-digits-and-colons * notation (null terminated string) */ #define HEX_HW_ADDR_LEN 18 // ARP Header Struktur struct my_arphdr { u_short hw_type; // hardware type u_short proto_type; // protocol type u_char ha_len; // hardware address len u_char pa_len; // protocol address len u_short opcode; // arp opcode u_char source_add[ETH_ALEN]; // source mac u_char source_ip[IP_ALEN]; // source ip u_char dest_add[ETH_ALEN]; // dest mac u_char dest_ip[IP_ALEN]; // dest ip }; #if defined(LINUX) && defined(__THROW) extern struct ether_addr *ether_aton (__const char *__asc) __THROW; #else #define LINUX 0 extern struct ether_addr *ether_aton (__const char *__asc); #endif extern int get_mac_linux(const char *dev, char *mac); extern int get_mac_bsd(const char *dev, char *mac); extern int arp_lookup_linux(const char *dev, const char *ip, char *mac); extern int arp_lookup_bsd(const char *dev, const char *ip, char *mac); extern int send_packet_linux(const char *dev, u_char *packet, u_int packetsize); extern int send_packet_bsd(const char *dev, u_char *packet, u_int packetsize); Net-ARP-1.0.12/ARP.xs0000644000175000017500000001143014236663330012732 0ustar bastibasti/* Perl ARP Extension Create and send an arp packets, lookup mac addresses Programmed by Bastian Ballmann Last update: 11.05.2022 This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License version 2 as published by the Free Software Foundation. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. */ #include "EXTERN.h" #include "perl.h" #include "XSUB.h" #include "ppport.h" #include #include #include #include #include #ifdef BSD #include #else #include #endif #include #include #include "arp.h" MODULE = Net::ARP PACKAGE = Net::ARP int send_packet(dev, sip, dip, smac, dmac, type) const char *dev; const char *sip; const char *dip; const char *smac; const char *dmac; const char *type; CODE: int uid; unsigned int packetsize = sizeof(struct my_arphdr) + sizeof(struct ether_header); unsigned char packet[packetsize]; struct ether_header *ethhdr = (struct ether_header *)packet; struct my_arphdr *arp = (struct my_arphdr *)(packet + sizeof(struct ether_header)); u_short op; in_addr_t ipaddr; RETVAL = 1; // Are you root? uid = getuid(); if(uid != 0) { printf("You must have UID 0 instead of %d.\n", uid); exit(0); } // Initialize packet buffer memset(packet,0,packetsize); // What's the ARP operation type? if(!strcmp(type, "request")) { op = ARPOP_REQUEST; } else if(!strcmp(type, "reply")) { op = ARPOP_REPLY; } else if(!strcmp(type, "revrequest")) { op = ARPOP_REVREQUEST; } else if(!strcmp(type, "revreply")) { op = ARPOP_REVREPLY; } else if(!strcmp(type, "invrequest")) { op = ARPOP_INVREQUEST; } else if(!strcmp(type, "invreply")) { op = ARPOP_INVREPLY; } else { printf("Unknown ARP operation\n"); RETVAL = 0; } if(smac == NULL) { printf("Parameter smac is NULL! Terminating.\n"); RETVAL = 0; } if(dmac == NULL) { printf("Parameter dmac is NULL! Terminating.\n"); RETVAL = 0; } // Found a dollar sign? if(strchr(smac, 36)) { printf("Found a $ char in smac! Terminating.\n"); RETVAL = 0; } if(strchr(dmac, 36)) { printf("Found a $ char in dmac! Terminating.\n"); RETVAL = 0; } if(ether_aton(smac) == NULL) { printf("Invalid source mac address! Terminating.\n"); RETVAL = 0; } if(ether_aton(dmac) == NULL) { printf("Invalid destination mac address! Terminating.\n"); RETVAL = 0; } // Check ips if(inet_addr(sip) == INADDR_NONE) { printf("Invalid source ip address! Terminating.\n"); RETVAL = 0; } if(inet_addr(dip) == INADDR_NONE) { printf("Invalid destination ip address! Terminating.\n"); RETVAL = 0; } // Construct and send packet if(RETVAL != 0) { // Ethernet header memcpy(ethhdr->ether_dhost,(u_char *)ether_aton(dmac), ETHER_ADDR_LEN); // Destination MAC memcpy(ethhdr->ether_shost,(u_char *)ether_aton(smac), ETHER_ADDR_LEN); // Source MAC ethhdr->ether_type = htons(ETHERTYPE_ARP); // ARP protocol // ARP header arp->hw_type = htons(ARPHDR_ETHER); // Hardware address type arp->proto_type = htons(ETH_P_IP); // Protocol address type arp->ha_len = ETH_ALEN; // Hardware address length arp->pa_len = IP_ALEN; // Protocol address length arp->opcode = htons(op); // ARP operation memcpy(arp->source_add,(u_char *)ether_aton(smac), ETH_ALEN); // Source MAC memcpy(arp->dest_add,(u_char *)ether_aton(dmac), ETH_ALEN); // Destination MAC ipaddr = inet_addr(sip); memcpy(arp->source_ip, (u_char *)&ipaddr, IP_ALEN); // Source IP ipaddr = inet_addr(dip); memcpy(arp->dest_ip, (u_char *)&ipaddr, IP_ALEN); // Destination IP if(LINUX == 1) { RETVAL = send_packet_linux(dev, packet, packetsize); } else { RETVAL = send_packet_bsd(dev, packet, packetsize); } } OUTPUT: RETVAL char * get_mac(dev) const char *dev; CODE: char tmp[HEX_HW_ADDR_LEN] = "unknown"; if(LINUX == 1) { get_mac_linux(dev, tmp); } else { get_mac_bsd(dev, tmp); } RETVAL = tmp; OUTPUT: RETVAL char * arp_lookup(dev, ip) const char *dev; const char *ip; CODE: char tmp[HEX_HW_ADDR_LEN] = "unknown"; if(LINUX == 1) { arp_lookup_linux(dev, ip, tmp); } else { arp_lookup_bsd(dev, ip, tmp); } RETVAL = tmp; OUTPUT: RETVAL Net-ARP-1.0.12/send_packet_linux.c0000755000175000017500000000256114236665727015623 0ustar bastibasti/* Perl ARP Extension Send the packet Linux code Programmed by Bastian Ballmann Last update: 11.05.2022 This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License version 2 as published by the Free Software Foundation. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. */ #include #include #include #include #include #include #include #include "arp.h" int send_packet_linux(const char *dev, u_char *packet, u_int packetsize) { struct sockaddr addr; int sock; if(strlen(dev) == 0) { printf("dev is undefined. Terminating.\n"); return 0; } if(packetsize == 0) { printf("packetsize is zero. Terminating.\n"); return 0; } // Create socket descriptor if( ( sock = socket(AF_PACKET, SOCK_PACKET, htons(ETH_P_ALL))) < 0 ) { perror("socket"); return 0; } // Set dev and send the packet strncpy(addr.sa_data, dev, sizeof(addr.sa_data)); if( (sendto(sock, packet, packetsize, 0, &addr, sizeof(struct sockaddr))) < 0 ) { perror("send"); return 0; } close(sock); return 1; } Net-ARP-1.0.12/arp_lookup_bsd.c0000755000175000017500000000426514236662125015117 0ustar bastibasti/* Perl ARP Extension Lookup the MAC address of an ip address BSD code Programmed by Bastian Ballmann Last update: 11.05.2022 This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License version 2 as published by the Free Software Foundation. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include "arp.h" #define ROUNDUP(a) \ ((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long)) int arp_lookup_bsd(const char *dev, const char *ip, char *mac) { int mib[6]; size_t needed; char *lim, *buf, *next; if ( (mac == NULL) || (dev == NULL) || (ip == NULL) ) return -1; strncpy(mac,"unknown", HEX_HW_ADDR_LEN); mac[HEX_HW_ADDR_LEN-1] = '\0'; mib[0] = CTL_NET; mib[1] = PF_ROUTE; mib[2] = 0; mib[3] = AF_INET; mib[4] = NET_RT_FLAGS; mib[5] = RTF_LLINFO; /* Retrieve routing table */ if(sysctl(mib, 6, NULL, &needed, NULL, 0) < 0) { perror("route-sysctl-estimate"); exit(1); } if((buf = malloc(needed)) == NULL) { perror("malloc"); exit(1); } if(sysctl(mib, 6, buf, &needed, NULL, 0) < 0) { perror("retrieval of routing table"); exit(1); } lim = buf + needed; next = buf; /* Search for the requested ip */ while (next < lim) { struct rt_msghdr *rtm = (struct rt_msghdr *)next; struct sockaddr_inarp *sinarp = (struct sockaddr_inarp *)(rtm + 1); struct sockaddr_dl *sdl = (struct sockaddr_dl *)((char *)sinarp + ROUNDUP(sinarp->sin_len)); if( (sdl->sdl_alen) && (!strcmp(ip,inet_ntoa(sinarp->sin_addr))) ) { sprintf(mac,"%s", ether_ntoa((struct ether_addr *)LLADDR(sdl))); } next += rtm->rtm_msglen; } free(buf); return(0); } Net-ARP-1.0.12/META.yml0000644000175000017500000000077114236677036013223 0ustar bastibasti--- abstract: unknown author: - 'Bastian Ballmann' build_requires: ExtUtils::MakeMaker: '0' Net::Pcap: '0' configure_requires: ExtUtils::MakeMaker: '0' dynamic_config: 1 generated_by: 'ExtUtils::MakeMaker version 7.44, CPAN::Meta::Converter version 2.150010' license: unknown meta-spec: url: http://module-build.sourceforge.net/META-spec-v1.4.html version: '1.4' name: Net-ARP no_index: directory: - t - inc version: v1.0.12 x_serialization_backend: 'CPAN::Meta::YAML version 0.018' Net-ARP-1.0.12/MANIFEST0000755000175000017500000000043014236677036013076 0ustar bastibastiARP.xs arp.h Changes Makefile.PL MANIFEST ppport.h README t/ARP.t ARP.pm arp_lookup_bsd.c arp_lookup_linux.c get_mac_bsd.c get_mac_linux.c send_packet_bsd.c send_packet_linux.c test.pl META.json META.yml Module YAML meta-data (added by MakeMaker) Net-ARP-1.0.12/Changes0000644000175000017500000000657514236667241013252 0ustar bastibastiChanges between 1.0.11 and 1.0.12 - removed warnings - sock family on Linux is now AF_PACKET - added missing bsd includes Changes between 1.0.10 and 1.0.11 - fixed tests Changes between 1.0.9 and 1.0.10 - fixed compilation errors on macOS Changes between 1.0.8 and 1.0.9 - support for mac os x (thanks to Jose Palao) -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- Changes between 1.0.7 and 1.0.8 - fixed bug (see https://rt.cpan.org/Ticket/Display.html?id=86223) -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- Changes between 1.0.6 and 1.0.7 - fixed unnecessary memcpy of dest addr (see https://rt.cpan.org/Ticket/Display.html?id=86223) Thanks to Daniel Black - abort on unknown arp operation - get_mac linux forgot to close socket - see https://rt.cpan.org/Public/Bug/Display.html?id=86221 -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- Changes between 1.0.5 and 1.0.6 new linux arp lookup via ioctl by Franck Joncourt -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- Changes between 1.0.4 and 1.0.5 buffer overflow patch by Franck Joncourt -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- Changes between 1.0.3 and 1.0.4 fix FTBFS due to unaligned assignment problems by Niko Tyni get_mac unknown device fix by Franck Joncourt -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- Changes between 1.0.2 and 1.0.3 Fixed possible buffer overflow in get_mac_linux() FreeBSD 7 amd64 patches by mitsuru@riken.jp -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- Changes between 1.0.1 and 1.0.2 FreeBSD 7 bugfixes by Niels Bakker -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- Changes between 1.0 and 1.0.1 Segfault bugfix on 64 bit cpus by Paul Kolano -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- Changes between 0.8 and 1.0 API Change for get_mac() and arp_lookup() - see perldoc Updated test script (Net::Pcap not needed if unavailable) New test suite to test for unwanted input. Fixed possible segfault in send_packet() because of not checking src / dst ip values -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- Changes between 0.7 and 0.8 Fixed typo in return value of arp_lookup() and get_mac() Fixed a segfault in send_packet() -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- Changes between 0.6 and 0.7 arp_lookup bugfix by Jeff Pinyan -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- Changes between 0.5 and 0.6 Filedescriptor Bugfixes in arp_lookup by Sigmund Augdal Helberg -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- Changes between 0.4 and 0.5 Bugfixes in function send_packet by Jonas Nagel fireball@zerouptime.ch -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- Changes between 0.3 and 0.4 ARP broadcast -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- Changes between 0.2 and 0.3 Check in all functions if we got all parameter we need -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- Changes between 0.1 and 0.2 Alexander Mueller visus@portsonline.net updated the arp lookup function for linux to make use of the proc fs. -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- Net-ARP-1.0.12/t/0000755000175000017500000000000014236677036012210 5ustar bastibastiNet-ARP-1.0.12/t/ARP.t0000755000175000017500000000071007753203772013016 0ustar bastibasti# Before `make install' is performed this script should be runnable with # `make test'. After `make install' it should work as `perl ARP.t' ######################### # change 'tests => 1' to 'tests => last_test_to_print'; use Test::More tests => 1; BEGIN { use_ok('ARP') }; ######################### # Insert your test code below, the Test::More module is use()ed here so read # its man page ( perldoc Test::More ) for help writing this test script. Net-ARP-1.0.12/get_mac_bsd.c0000755000175000017500000000270214236655662014345 0ustar bastibasti/* Perl ARP Extension Get the MAC address of an interface BSD code Programmed by Bastian Ballmann Last update: 09.02.2006 Fixed for FreeBSD by Niels Bakker Last update: 2007-12-26 This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License version 2 as published by the Free Software Foundation. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. */ #include #include #include #include #include #include #include #include #include "arp.h" int get_mac_bsd(const char *dev, char *mac) { struct ifaddrs *iface, *iffirst; if ( (mac == NULL) || (dev == NULL) ) return -1; strncpy(mac,"unknown", HEX_HW_ADDR_LEN); mac[HEX_HW_ADDR_LEN - 1] = '\0'; if (getifaddrs(&iface)) return -1; iffirst = iface; while(iface->ifa_next != NULL) { if(!strcmp(iface->ifa_name,dev)) { if (iface->ifa_addr->sa_family == AF_LINK) { struct sockaddr_dl *sdl = (struct sockaddr_dl *) iface->ifa_addr; sprintf(mac, "%s", ether_ntoa((struct ether_addr *)LLADDR(sdl))); break; } } iface = iface->ifa_next; } freeifaddrs(iffirst); return 0; } Net-ARP-1.0.12/arp_lookup_linux.c0000755000175000017500000000613614236665374015516 0ustar bastibasti/* Perl ARP Extension Lookup the MAC address of an ip address Linux code Programmed by Bastian Ballmann and Alexander Mueller Last update: 20.09.2006 This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License version 2 as published by the Free Software Foundation. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. */ #include #include #include #include #include #include #include #include #include #include /* * Search for a hardware address linked to an IP address on a device * * @device: network interface name we are going to query * @ip: ip address (IPv4 numbers-and-dots notation) whose hardware address * is going to be looked for * @hw_addr: buffer containing the hardware mac_address * * \returns 0 if a hardware address has been found. @mac is set accordingly as * a null terminated string. * 1 if an error occured */ int arp_lookup_linux ( const char *device, const char *ip, char *hw_addr) { int s; unsigned char err; struct in_addr ipaddr; struct arpreq areq; struct sockaddr_in *sin; err = 1; /* A device name must be a null terminated string whose length is less * than 16 bytes */ if ( !strlen(device) || (strlen(device) >= 16) ) fprintf(stderr, "No valid device name found.\n"); /* Is there a buffer allocated to store the hardware address? */ else if (hw_addr == NULL) fprintf(stderr, "No memory allocated to store the hardware address.\n"); /* Make sure the ip address is valid */ else if ( !strlen(ip) || (inet_aton(ip, &ipaddr) == 0) ) fprintf(stderr, "Invalid ip address.\n"); /* Create the socket */ else if ((s = socket(AF_INET, SOCK_DGRAM, 0)) == -1) perror("Socket"); else { /* Set up the protocol address */ memset(&areq, 0, sizeof(areq)); sin = (struct sockaddr_in *) &areq.arp_pa; sin->sin_family = AF_INET; sin->sin_addr = ipaddr; /* Set up the hardware address */ sin = (struct sockaddr_in *) &areq.arp_ha; sin->sin_family = ARPHRD_ETHER; strcpy(areq.arp_dev, device); /* Carry out the request */ if (ioctl(s, SIOCGARP, &areq) == -1) perror("SIOCGARP"); else { sprintf(hw_addr, "%02x:%02x:%02x:%02x:%02x:%02x", areq.arp_ha.sa_data[0] & 0xFF, areq.arp_ha.sa_data[1] & 0xFF, areq.arp_ha.sa_data[2] & 0xFF, areq.arp_ha.sa_data[3] & 0xFF, areq.arp_ha.sa_data[4] & 0xFF, areq.arp_ha.sa_data[5] & 0xFF); err = 0; } /* Close the current socket */ close(s); } return err; }