#!/usr/bin/perl # # ##################################################################### # # netsymbols.pl version 0.10 9-21-16, michael@bizsystems.com # # # # # # COPYRIGHT 2008-2016 Michael Robinton # # # # This program is free software; you can redistribute it and/or modify # # it under the terms of either: # # # # a) the GNU General Public License as published by the Free # # Software Foundation; either version 2, or (at your option) any # # later version, or # # # # b) the "Artistic License" which comes with this distribution. # # # # 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 either # # the GNU General Public License or the Artistic License for more # # details. # # # # You should have received a copy of the Artistic License with this # # distribution, in the file named "Artistic". If not, I'll be glad # # to provide one. # # # # You should also have received a copy of the GNU General Public # # License along with this program in the file named "Copying". If not, # # write to the # # # # Free Software Foundation, Inc. # # 59 Temple Place, Suite 330 # # Boston, MA 02111-1307, USA # # # # or visit their web page on the internet at: # # # # http://www.gnu.org/copyleft/gpl.html. # # ##################################################################### # package NetSymbols; use diagnostics; use Config; my $doprint = 0; my $conf = \%Config; my $include = $conf->{usrinc}; sub new { return bless {}, __PACKAGE__; } my $grep = qx/which grep/; chop $grep while $grep =~ /\n$/; my $gfp = sub { my($mtch,$include) = @_; my $cmd = $grep . $mtch . $include .'/*'."\n"; my @lines = qx/$cmd/; print STDERR '# ', $cmd if $doprint; foreach (@lines) { chop $_ while $_ =~ /\s$/; print STDERR $_, "\n" if $doprint; } return @lines; }; my (@fileAFs,@fileIFs,@fileIN6s); sub mksymblArrays { @fileAFs = $gfp->(' -rEl "define[[:space:]]+[AP]F_" ',$include); @fileIFs = $gfp->(' -rEl "define[[:space:]]+IF" ',$include); @fileIN6s = $gfp->(' -rEl "define[[:space:]]+IN6_IF" ',$include); } ### generate AF/PF families # list of troublesome symbols to ignore my @donotuse = qw( AF_NETGRAPH PF_NETGRAPH ); # list of wanted AF/PF symbols, ignore the rest # this list should reflect the SOCKADDR's present # in the header file "ni_fixups.h" plus a few symbols # my @wantafsyms = qw( AF_UNSPEC AF_INET AF_INET6 AF_LOCAL AF_FILE AF_UNIX AF_MAX AF_PACKET AF_ROUTE AF_APPLETALK AF_ASH AF_X25 AF_ECONET AF_IPX AF_ROSE AF_LINK AF_ISO AF_NUTSS AF_AX25 AF_DECnet PF_UNSPEC PF_INET PF_INET6 PF_LOCAL PF_FILE PF_UNIX PF_MAX PF_PACKET PF_ROUTE PF_APPLETALK PF_ASH PF_X25 PF_ECONET PF_IPX PF_ROSE PF_LINK PF_ISO PF_NUTSS PF_AX25 PF_DECnet ); my(@slurp,%slurped,%fam,%unique); my $endv = 0; # maximum value found in defines sub cleanslurp { undef @slurp; %slurped = (); } # file string, slurp switch full filename = 1 sub slurp { my($in,$sw) = @_;; $sw = 0 unless defined $sw; #print STDERR "slurping $in\n"; return if $slurped{$in}; $slurped{$in} = 1; local *F; my $file = ($sw) ? $in : $Config{usrinc} .'/'. $in; open (F,$file) or return; my @new = ; close F; #foreach (@new) { # print STDERR "$file => $_\n"; #} push @slurp, @new; } sub fslurp { foreach (@_) { #print STDERR $_,"\n"; slurp($_,1); # tell slurp to use absolute file name } } # input: hash pointer, # unique hash pointer or false # regular expression, # secondary regexp if enum (else undef) # sub fill { my($hp,$unique,$rgx1,$rgx2) = @_; my %enum; # enumeration cache foreach(@slurp) { if ($_ =~ /^#\s*include\s+\<\s*([^\s>]+)/) { #print STDERR "\tincfile $1\n"; slurp($1); next; } if ($rgx2 && $_ =~ /$rgx2/) { my $pri = $1; my $sec = $2; #print STDERR "IFF pri=$pri, sec=$sec\n"; next if $2 =~ /[^0-9x]/; # must be numeric or hex $sec = eval "$sec"; $enum{$pri} = $sec; $endv = $sec if $endv < $sec; # track maximum value next; } next unless $_ =~ /$rgx1/; my $pri = $1; my $sec = $2; #print STDERR "pri=$pri, sec=$sec\n"; if ($rgx2 && exists $enum{$pri} && $pri eq $sec) { $hp->{$pri} = $enum{$pri}; next; } elsif ($sec =~ /[^0-9x]/) { # if this is not a number next unless exists $hp->{$sec}; # should not happen $hp->{$pri} = $hp->{$sec}; } else { $sec = eval "$sec"; $hp->{$pri} = $sec; $endv = $sec if $endv < $sec; # track maximum value next unless $unique; next if exists $unique->{$sec}; #print STDERR "unique $sec\t=> $pri\n"; $unique->{$sec} = $pri; # track 1st definition } } } # input: filehandle, # symbol hash # array of symbols synonyms # sub extradef { my($F,$sym,@syn) = @_; #print STDERR "extra defs @syn\n"; my $x; foreach(0..$#syn) { # check each synonym if (exists $sym->{$syn[$_]}) { $x = $_; last; } } #print STDERR qq|\n\tadvisory warning\n"@syn"\n\tnot defined\n| unless defined $x; return unless defined $x; # define all undefined synonyms # foreach(0..$#syn) { next if $_ == $x; my $newsym = $syn[$_]; print $F "#ifndef $newsym\n# define $syn[$_] $syn[$x]\n#endif\n"; $sym->{$newsym} = $sym->{$syn[$x]}; } } my $XX = 1; # 1 = original, 0 = new sub gensyms { mksymblArrays(); cleanslurp(); if ($XX) { slurp('sys/socket.h'); # parse sys/socket.h and its #includes } else { fslurp(@fileAFs); } fill(\%fam,\%unique,'^#\s*define\s+((?:A|P)F_[^\s]+)\s+([^\s]+)'); # fill(\%fam,\%unique,'^#\s*define\s+((?:A|P)F_[^\s]{2,})\s+([^\s]+)'); # repeat in case symbol dependencies are out of order cleanslurp(); if ($XX) { slurp('sys/socket.h'); #slurp('sys/types.h'); } else { fslurp(@fileAFs); } fill(\%fam,'','^#\s*define\s+((?:A|P)F_[^\s]+)\s+([^\s]+)'); # fill(\%fam,'','^#\s*define\s+((?:A|P)F_[^\s]{2,})\s+([^\s]+)'); my %ifs; cleanslurp(); if ($XX) { slurp('net/if.h'); slurp('netinet/in.h') if -e '/usr/include/netinet/in.h'; slurp('netinet/in_var.h') if -e '/usr/include/netinet/in_var.h'; } else { fslurp(@fileIFs); fslurp(@fileIN6s); } fill(\%ifs,\%unique,'^#\s*define\s+(IF[^\s]+)\s+([^\s]+)','(IF[^\s]+)\s*\=\s*([^\s,]+)'); fill(\%ifs,\%unique,'^#\s*define\s+(IN6_IF[^\s]+)\s+([^\s]+)','(IN6_IF[^\s]+)\s*\=\s*([^\s,]+)'); #foreach (keys %unique) { #print STDERR "$_\t=> $unique{$_}\n"; #} cleanslurp(); if ($XX) { slurp('net/if.h'); slurp('netinet/in.h') if -e '/usr/include/netinet/in.h'; slurp('netinet/in_var.h') if -e '/usr/include/netinet/in_var.h'; } else { fslurp(@fileIFs); fslurp(@fileIN6s); } fill(\%ifs,'','^#\s*define\s+(IF[^\s]+)\s+([^\s]+)','(IF[^\s]+)\s*\=\s*([^\s,]+)'); fill(\%ifs,'','^#\s*define\s+(IN6_IF[^\s]+)\s+([^\s]+)','(IN6_IF[^\s]+)\s*\=\s*([^\s,]+)'); # dispose of troublesome symbols my %ru = reverse %unique; foreach my $symhsh (\%ifs,\%fam,\%ru) { foreach(@donotuse) { # remove the ones that cause trouble delete $symhsh->{$_} if exists $symhsh->{$_}; } } foreach my $symhsh(\%fam) { my @allsyms = keys %$symhsh; foreach my $havsym (@allsyms) { unless (grep {/$havsym/} @wantafsyms) { delete $symhsh->{$havsym}; # delete unneeded symbol here delete $ru{$havsym}; # and in unique hash } } } %unique = reverse %ru; # fill done, bump max value ++$endv; # we're going to ignore all that end value tracking because IFF's exceed I32 # I32 size. Use the max number that fits in an I32 and do IFF's another way $endv = (2**31) -1; mkdir 'lib' unless -e 'lib' && -d 'lib'; mkdir 'lib/Net' unless -e 'lib/Net' && -d 'lib/Net'; mkdir 'lib/Net/Interface' unless -e 'lib/Net/Interface' && -d 'lib/Net/Interface'; open(NFe,'>lib/Net/Interface/NetSymbols.pm') or die "could not open NetSymbols.pm for write"; open(NFx,'>netsymbolXS.inc') or die "could not open netsymbolXS.inc for write"; open(NFc,'>netsymbolC.inc') or die "could not open netsymbolC.inc for write"; open(NFt,'>ni_IFF_inc.c') or die "could not open ni_IFF_inc.c for write"; open(NFz,'>ni_XStabs_inc.c') or die "could not open ni_XStabs_inc.c for write"; print NFz q|/* BEGIN ni_XStabs_inc.c * ************************************************************ * * DO NOT ALTER THIS FILE * * IT IS WRITTEN BY Makefile.PL & inst/netsymbols.pl * * EDIT THOSE INSTEAD * * ************************************************************ * * some of these symbols may be redundant * * ************************************************************ */ |; # make defines for synonyms extradef(*NFc,\%fam,qw( PF_LOCAL PF_UNIX PF_FILE AF_LOCAL AF_FILE AF_UNIX )); # are all synonyms extradef(*NFc,\%fam,qw( PF_MAX AF_MAX )); extradef(*NFc,\%fam,qw( AF_PACKET PF_PACKET AF_ROUTE PF_ROUTE )); extradef(*NFc,\%fam,qw( AF_ISO PF_ISO AF_BRIDGE PF_BRIDGE )); # this one is not correct... extradef(*NFc,\%fam,qw( AF_NS PF_NS AF_NUTSS PF_NUTSS AF_ATM PF_ATM )); extradef(*NFc,\%ifs,qw( IFNAMSIZ IF_NAMESIZE )); # Fix missing definition print NFc "#ifndef IFHWADDRLEN\n#define IFHWADDRLEN 6\n#endif\n"; $ifs{IFHWADDRLEN} = 6; # Add opening definition print NFc qq| #define __NI_AF_TEST $endv |; print NFz q| const ni_iff_t ni_af_sym_tab[] = { |; ### populate exports print NFe q|#!|. $conf->{perlpath} .q| # # DO NOT ALTER THIS FILE # IT IS WRITTEN BY Makefile.PL and inst/netsymbols.pl # EDIT THOSE INSTEAD # package Net::Interface::NetSymbols; use vars qw($VERSION @EXPORT_OK %EXPORT_TAGS); $VERSION = 1.01; |; print NFx q|void _net_af_syms() ALIAS: |; ### populate IFF flags # print NFt q| /* BEGIN ni_IFF_inc.c include **************************************************************** * DO NOT ALTER THIS FILE * * IT IS WRITTEN BY Makefile.PL & inst/netsymbols.pl * * EDIT THOSE INSTEAD * **************************************************************** */ const ni_iff_t ni_iff_tab[] = { |; ### populate C portion # my @tmp = grep {/^AF/} keys %fam; # tmp store AFs my @afs = sort { $fam{$a} <=> $fam{$b} } @tmp; @tmp = grep {/^PF/} keys %fam; my @pfs = sort { $fam{$a} <=> $fam{$b} } @tmp; my @ifs = keys %ifs; # iffs are not unique so we can safely purge unwanted symbols here my @iffs = sort grep {/^IFF_/ && $_ !~ /IFF_DRV/} keys %ifs; my @iffIN6 = sort grep {/^IN6_IFF/} keys %ifs; #foreach (@iffs) { # print STDERR "$_\t=> $ifs{$_}\n"; #} print NFe q|my @afs = qw( |; foreach(@afs) { $_ =~ /AF_([^\s]+)/; print NFx "\t$_ = _NI_$_\n"; print NFe "\t$_\n"; print NFc qq|#ifdef $_\n\# define _NI_$_ $fam{$_}\n#else\n# define _NI_$_ $endv\n#endif\n|; print NFz qq|\t{$_,\t"|, (lc $1), qq|"},\n|; } print NFe q|); my @pfs = qw( |; foreach(@pfs) { $_ =~ /PF_([^\s]+)/; print NFx "\t$_ = _NI_$_\n"; print NFe "\t$_\n"; print NFc qq|#ifdef $_\n\# define _NI_$_ $fam{$_}\n#else\n# define _NI_$_ $endv\n#endif\n|; print NFz qq|\t{$_,\t"|, (lc $1), qq|"},\n|; } print NFz qq|\t{__NI_AF_TEST,\t"placeholder"} }; |; print NFx qq|\t_NI_AF_TEST = __NI_AF_TEST PREINIT: SV * rv; int n, i; PPCODE: if (ix >= $endv) { croak("%s is not implemented on this architecture", GvNAME(CvGV(cv))); } rv = sv_2mortal(newSViv(ix)); n = sizeof(ni_af_sym_tab) / sizeof(ni_iff_t); for (i=0; i= $endv) { croak("%s is not implemented on this architecture", GvNAME(CvGV(cv))); } RETVAL = bigsymvals[ix]; OUTPUT: RETVAL void _net_i2f_syms() ALIAS: |; $comma = ''; foreach(sort @iffs) { $_ =~ /IFF_([^\s]+)/; print NFc qq|#ifdef $_\n\# define _NI_$_ $_\n#else\n# define _NI_$_ $endv\n#endif\n|; print NFz qq|\t{$_,\t"|, (lc $1), qq|"},\n|; print NFe "\t$_\n"; # print NFx "\t$_ = _NI_$_\n"; print NFx "\t$_ = $ifidx\n"; $idxary .= "$icoma\n\t$ifs{$_}"; $ifidx++; next if $_ eq 'IFF_UP'; # special case handled separately print NFt qq|$comma\n\t\{$_,\t"$1"\}|; $comma = ','; } print NFt q| }; #ifdef HAVE_STRUCT_IN6_IFREQ const ni_iff_t ni_iff_tabIN6[] = { |; print NFe q|); my @iffIN6 = qw( |; $comma = ''; foreach(sort @iffIN6) { $_ =~ /IFF_([^\s]+)/; print NFc qq|#ifdef $_\n\# define _NI_$_ $_\n#else\n# define _NI_$_ $endv\n#endif\n|; print NFz qq|\t{$_,\t"|. (lc $1). qq|"},\n|; next if $_ eq 'IFF_UP'; # special case handled separately print NFe "\t$_\n"; # print NFx "\t$_ = _NI_$_\n"; print NFx "\t$_ = $ifidx\n"; $idxary .= "$icoma\n\t$ifs{$_}"; $ifidx++; print NFt qq|$comma\n\t\{$_,\t"$1"\}|; $comma = ','; } print NFz qq|\t{__NI_AF_TEST,\t"placeholder"} }; $idxary }; |; print NFt q| }; #endif /* END ni_IFF_inc.c include */ |; print NFe q|); my %unique = ( |; my $utxt = ''; foreach(sort {$a <=> $b} keys %unique) { $utxt .= "\t$_\t=> '". $unique{$_} ."',\n"; } print NFe $utxt, q|); my @iftype = qw( IPV6_ADDR_ANY IPV6_ADDR_UNICAST IPV6_ADDR_MULTICAST IPV6_ADDR_ANYCAST IPV6_ADDR_LOOPBACK IPV6_ADDR_LINKLOCAL IPV6_ADDR_SITELOCAL IPV6_ADDR_COMPATv4 IPV6_ADDR_SCOPE_MASK IPV6_ADDR_MAPPED IPV6_ADDR_RESERVED IPV6_ADDR_ULUA IPV6_ADDR_6TO4 IPV6_ADDR_6BONE IPV6_ADDR_AGU IPV6_ADDR_UNSPECIFIED IPV6_ADDR_SOLICITED_NODE IPV6_ADDR_ISATAP IPV6_ADDR_PRODUCTIVE IPV6_ADDR_6TO4_MICROSOFT IPV6_ADDR_TEREDO IPV6_ADDR_ORCHID IPV6_ADDR_NON_ROUTE_DOC ); my @scope = qw( RFC2373_GLOBAL RFC2373_ORGLOCAL RFC2373_SITELOCAL RFC2373_LINKLOCAL RFC2373_NODELOCAL LINUX_COMPATv4 ); @EXPORT_OK = (@afs,@pfs,@ifs,@iftype,@scope); %EXPORT_TAGS = ( all => [@afs,@pfs,@ifs,@iftype,@scope], afs => [@afs], pfs => [@pfs], ifs => [@ifs], iffs => [@iffs], iffIN6 => [@iffIN6], iftype => [@iftype], scope => [@scope], ); sub NI_ENDVAL {return |. $endv .q|}; sub NI_UNIQUE {return \%unique}; sub DESTROY {}; 1; __END__ =head1 NAME Net::Interface::NetSymbols - AF_ PF_ IFxxx type symbols =head1 SYNOPSIS This module is built for this specific architecture during the F process using F. Do not edit this module, edit F instead. This module contains symbols arrays only for use by Net::Interface, in all other respects it is NOT functional. It contains documentation and data arrays for this specific architecture. B WARNING !! usage is Net::Interface B Net::Interface::NetSymbols use Net::Interface qw( Net::Interface::NetSymbols::NI_ENDVAL(); Net::Interface::NetSymbols::NI_UNIQUE(); |; print NFe qq|@afs @pfs @ifs @iffs |; if (@iffIN6) { print NFe qq| @iffIN6 populated for BSD flavored systems :all :afs :pfs :ifs :iffs :iffIN6 :iftype :scope ); |; } else { print NFe qq| :all :afs :pfs :ifs :iffs :iftype :scope ); |; } print NFe q| =head1 DESCRIPTION All of the AF_XXX and PF_XXX symbols available in local C plus usual aliases for AF_LOCAL i.e. (AF_FILE AF_UNIX PF_LOCAL PF_FILE PF_UNIX) All of the IFxxxx and IN6_IF symbols in C and their includes. Symbols may be accessed for their numeric value or their string name. i.e. if ($family == AF_INET) do something... or print AF_INET will product the string "inet" The same holds true for: printf("family is %s",AF_INET); or sprint("family is %s",AF_INET); To print the numeric value of the SYMBOL do: print (0 + SYMBOL), "\n"; |; if (exists $fam{AF_INET6}) { print NFe q|On systems supporting IPV6, these additional symbols are available which may be applied to the address I to determine the address attributes. IPV6_ADDR_ANY unknown IPV6_ADDR_UNICAST unicast IPV6_ADDR_MULTICAST multicast IPV6_ADDR_ANYCAST anycast IPV6_ADDR_LOOPBACK loopback IPV6_ADDR_LINKLOCAL link-local IPV6_ADDR_SITELOCAL site-local IPV6_ADDR_COMPATv4 compat-v4 IPV6_ADDR_SCOPE_MASK scope-mask IPV6_ADDR_MAPPED mapped IPV6_ADDR_RESERVED reserved IPV6_ADDR_ULUA uniq-lcl-unicast IPV6_ADDR_6TO4 6to4 IPV6_ADDR_6BONE 6bone IPV6_ADDR_AGU global-unicast IPV6_ADDR_UNSPECIFIED unspecified IPV6_ADDR_SOLICITED_NODE solicited-node IPV6_ADDR_ISATAP ISATAP IPV6_ADDR_PRODUCTIVE productive IPV6_ADDR_6TO4_MICROSOFT 6to4-ms IPV6_ADDR_TEREDO teredo IPV6_ADDR_ORCHID orchid IPV6_ADDR_NON_ROUTE_DOC non-routeable-doc if ($type & IPV6_ADDR_xxxx) { print IPV6_ADDR_xxxx,"\n"; } These symbols may be equated to the I of the address. RFC2373_GLOBAL global-scope RFC2373_ORGLOCAL org-local RFC2373_SITELOCAL site-local RFC2373_LINKLOCAL link-local RFC2373_NODELOCAL loopback LINUX_COMPATv4 lx-compat-v4 if ($scope eq RFC2373_xxxx) { print RFC2373_xxxx,"\n"; } |; } print NFe q| =over 4 =item * :all Import all symbols =item * :afs Import all AF_XXX symbols =item * :pfs Import all PF_XXX symbols =item * :ifs Import all IFxxxx symbols =item * :iffs Import all IFF symbols |; if (@iffIN6) { print NFe q| =item * :iffIN6 Import all IN6_IFF symbols (BSD flavors only) |; } if (exists $fam{AF_INET6}) { print NFe q| =item * :iftype Import all IPV6 type symbols =item * :scope Import all IPV6 scope symbols |; } print NFe q| =back =head1 non EXPORT functions =over 4 =item * Net::Interface::NetSymbols::NI_ENDVAL(); Reports the highest symbol value +1 of :all symbols above. Used for testing. =item * Net::Interface::NetSymbols::NI_UNIQUE(); Returns a hash pointer to the AF_ or PF_ symbol values mapped to their character strings as defined for this architecture. i.e. |, $utxt, q| =head1 AUTHOR Michael Robinton =head1 COPYRIGHT |. ((localtime())[5] +1900) .q| Michael Robinton, all rights reserved. This library is free software. You can distribute it and/or modify it under the same terms as Perl itself. =cut 1; |; # add test element and complete print NFx qq| PREINIT: SV * rv; int n, i; PPCODE: if (ix >= $endv) { croak("%s is not implemented on this architecture", GvNAME(CvGV(cv))); } rv = sv_2mortal(newSVnv(bigsymvals[ix])); n = sizeof(ni_sym_iff_tab) / sizeof(ni_iff_t); for (i=0; i