1#!/usr/bin/perl
2#
3# #####################################################################	#
4# netsymbols.pl	version 0.10	9-21-16, michael@bizsystems.com		#
5#									#
6#									#
7#     COPYRIGHT 2008-2016 Michael Robinton <michael@bizsystems.com>	#
8#									#
9# This program is free software; you can redistribute it and/or modify	#
10# it under the terms of either:						#
11#									#
12#  a) the GNU General Public License as published by the Free		#
13#  Software Foundation; either version 2, or (at your option) any	#
14#  later version, or							#
15#									#
16#  b) the "Artistic License" which comes with this distribution.	#
17#									#
18# This program is distributed in the hope that it will be useful,	#
19# but WITHOUT ANY WARRANTY; without even the implied warranty of	#
20# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See either	#
21# the GNU General Public License or the Artistic License for more 	#
22# details.								#
23#									#
24# You should have received a copy of the Artistic License with this	#
25# distribution, in the file named "Artistic".  If not, I'll be glad 	#
26# to provide one.							#
27#									#
28# You should also have received a copy of the GNU General Public 	#
29# License along with this program in the file named "Copying". If not,	#
30# write to the 								#
31#									#
32#	Free Software Foundation, Inc.					#
33#	59 Temple Place, Suite 330					#
34#	Boston, MA  02111-1307, USA					#
35#									#
36# or visit their web page on the internet at:				#
37#									#
38#	http://www.gnu.org/copyleft/gpl.html.				#
39# #####################################################################	#
40
41package NetSymbols;
42use diagnostics;
43use Config;
44
45my $doprint = 0;
46
47my $conf = \%Config;
48
49my $include = $conf->{usrinc};
50
51sub new {
52  return bless {}, __PACKAGE__;
53}
54
55my $grep = qx/which grep/;
56chop $grep while $grep =~ /\n$/;
57
58my $gfp = sub {
59  my($mtch,$include) = @_;
60  my $cmd = $grep . $mtch . $include .'/*'."\n";
61  my @lines = qx/$cmd/;
62  print STDERR '# ', $cmd if $doprint;
63  foreach (@lines) {
64    chop $_ while $_ =~ /\s$/;
65    print STDERR $_, "\n" if $doprint;
66  }
67  return @lines;
68};
69
70my (@fileAFs,@fileIFs,@fileIN6s);
71
72sub mksymblArrays {
73  @fileAFs  = $gfp->(' -rEl "define[[:space:]]+[AP]F_" ',$include);
74  @fileIFs  = $gfp->(' -rEl "define[[:space:]]+IF" ',$include);
75  @fileIN6s = $gfp->(' -rEl "define[[:space:]]+IN6_IF" ',$include);
76}
77
78### generate AF/PF families
79
80# list of troublesome symbols to ignore
81my @donotuse = qw(
82	AF_NETGRAPH
83	PF_NETGRAPH
84);
85
86# list of wanted AF/PF symbols, ignore the rest
87# this list should reflect the SOCKADDR's present
88# in the header file "ni_fixups.h" plus a few symbols
89#
90my @wantafsyms = qw(
91	AF_UNSPEC
92	AF_INET
93	AF_INET6
94	AF_LOCAL
95	AF_FILE
96	AF_UNIX
97	AF_MAX
98	AF_PACKET
99	AF_ROUTE
100	AF_APPLETALK
101	AF_ASH
102	AF_X25
103	AF_ECONET
104	AF_IPX
105	AF_ROSE
106	AF_LINK
107	AF_ISO
108	AF_NUTSS
109	AF_AX25
110	AF_DECnet
111	PF_UNSPEC
112	PF_INET
113	PF_INET6
114	PF_LOCAL
115	PF_FILE
116	PF_UNIX
117	PF_MAX
118	PF_PACKET
119	PF_ROUTE
120	PF_APPLETALK
121	PF_ASH
122	PF_X25
123	PF_ECONET
124	PF_IPX
125	PF_ROSE
126	PF_LINK
127	PF_ISO
128	PF_NUTSS
129	PF_AX25
130	PF_DECnet
131);
132
133
134my(@slurp,%slurped,%fam,%unique);
135my $endv = 0;			# maximum value found in defines
136
137sub cleanslurp {
138  undef @slurp;
139  %slurped = ();
140}
141
142# file string, slurp switch full filename = 1
143sub slurp {
144  my($in,$sw) = @_;;
145  $sw = 0 unless defined $sw;
146#print STDERR "slurping $in\n";
147  return if $slurped{$in};
148  $slurped{$in} = 1;
149  local *F;
150  my $file = ($sw) ?
151	$in : $Config{usrinc} .'/'. $in;
152  open (F,$file) or return;
153  my @new = <F>;
154  close F;
155#foreach (@new) {
156#  print STDERR "$file => $_\n";
157#}
158  push @slurp, @new;
159}
160
161sub fslurp {
162  foreach (@_) {
163#print STDERR $_,"\n";
164    slurp($_,1);	# tell slurp to use absolute file name
165  }
166}
167
168
169# input:	hash pointer,
170#		unique hash pointer or false
171#		regular expression,
172#		secondary regexp if enum (else undef)
173#
174sub fill {
175  my($hp,$unique,$rgx1,$rgx2) = @_;
176  my %enum;				# enumeration cache
177  foreach(@slurp) {
178    if ($_ =~ /^#\s*include\s+\<\s*([^\s>]+)/) {
179#print STDERR "\tincfile $1\n";
180      slurp($1);
181      next;
182    }
183    if ($rgx2 && $_ =~ /$rgx2/) {
184      my $pri = $1;
185      my $sec = $2;
186#print STDERR "IFF pri=$pri, sec=$sec\n";
187     next if $2 =~ /[^0-9x]/;		# must be numeric or hex
188      $sec = eval "$sec";
189      $enum{$pri} = $sec;
190      $endv = $sec if $endv < $sec;	# track maximum value
191      next;
192    }
193    next unless $_ =~ /$rgx1/;
194    my $pri = $1;
195    my $sec = $2;
196#print STDERR "pri=$pri, sec=$sec\n";
197   if ($rgx2 && exists $enum{$pri} && $pri eq $sec) {
198      $hp->{$pri} = $enum{$pri};
199      next;
200    } elsif ($sec =~ /[^0-9x]/) {	# if this is not a number
201      next unless exists $hp->{$sec};	# should not happen
202      $hp->{$pri} = $hp->{$sec};
203    } else {
204      $sec = eval "$sec";
205      $hp->{$pri} = $sec;
206      $endv = $sec if $endv < $sec;	# track maximum value
207      next unless $unique;
208      next if exists $unique->{$sec};
209#print STDERR "unique $sec\t=> $pri\n";
210      $unique->{$sec} = $pri;		# track 1st definition
211    }
212  }
213}
214
215
216# input: filehandle,
217#	 symbol hash
218#	 array of symbols synonyms
219#
220sub extradef {
221  my($F,$sym,@syn) = @_;
222#print STDERR "extra defs @syn\n";
223  my $x;
224  foreach(0..$#syn) {			# check each synonym
225    if (exists $sym->{$syn[$_]}) {
226      $x = $_;
227      last;
228    }
229  }
230#print STDERR qq|\n\tadvisory warning\n"@syn"\n\tnot defined\n| unless defined $x;
231  return unless defined $x;
232
233# define all undefined synonyms
234#
235  foreach(0..$#syn) {
236    next if $_ == $x;
237    my $newsym = $syn[$_];
238    print $F "#ifndef $newsym\n# define $syn[$_] $syn[$x]\n#endif\n";
239    $sym->{$newsym} = $sym->{$syn[$x]};
240  }
241}
242
243my $XX = 1;	# 1 = original, 0 = new
244
245sub gensyms {
246  mksymblArrays();
247
248  cleanslurp();
249if ($XX) {
250  slurp('sys/socket.h');			# parse sys/socket.h and its #includes
251} else {
252  fslurp(@fileAFs);
253}
254  fill(\%fam,\%unique,'^#\s*define\s+((?:A|P)F_[^\s]+)\s+([^\s]+)');
255#  fill(\%fam,\%unique,'^#\s*define\s+((?:A|P)F_[^\s]{2,})\s+([^\s]+)');
256# repeat in case symbol dependencies are out of order
257  cleanslurp();
258if ($XX) {
259  slurp('sys/socket.h');
260#slurp('sys/types.h');
261} else {
262  fslurp(@fileAFs);
263}
264  fill(\%fam,'','^#\s*define\s+((?:A|P)F_[^\s]+)\s+([^\s]+)');
265#  fill(\%fam,'','^#\s*define\s+((?:A|P)F_[^\s]{2,})\s+([^\s]+)');
266
267
268  my %ifs;
269  cleanslurp();
270if ($XX) {
271  slurp('net/if.h');
272  slurp('netinet/in.h') if -e '/usr/include/netinet/in.h';
273  slurp('netinet/in_var.h') if -e '/usr/include/netinet/in_var.h';
274} else {
275  fslurp(@fileIFs);
276  fslurp(@fileIN6s);
277}
278  fill(\%ifs,\%unique,'^#\s*define\s+(IF[^\s]+)\s+([^\s]+)','(IF[^\s]+)\s*\=\s*([^\s,]+)');
279  fill(\%ifs,\%unique,'^#\s*define\s+(IN6_IF[^\s]+)\s+([^\s]+)','(IN6_IF[^\s]+)\s*\=\s*([^\s,]+)');
280
281#foreach (keys %unique) {
282#print STDERR "$_\t=> $unique{$_}\n";
283#}
284  cleanslurp();
285if ($XX) {
286  slurp('net/if.h');
287  slurp('netinet/in.h') if -e '/usr/include/netinet/in.h';
288  slurp('netinet/in_var.h') if -e '/usr/include/netinet/in_var.h';
289} else {
290  fslurp(@fileIFs);
291  fslurp(@fileIN6s);
292}
293  fill(\%ifs,'','^#\s*define\s+(IF[^\s]+)\s+([^\s]+)','(IF[^\s]+)\s*\=\s*([^\s,]+)');
294  fill(\%ifs,'','^#\s*define\s+(IN6_IF[^\s]+)\s+([^\s]+)','(IN6_IF[^\s]+)\s*\=\s*([^\s,]+)');
295
296# dispose of troublesome symbols
297  my %ru = reverse %unique;
298  foreach my $symhsh (\%ifs,\%fam,\%ru) {
299    foreach(@donotuse) {		# remove the ones that cause trouble
300      delete $symhsh->{$_} if exists $symhsh->{$_};
301    }
302  }
303  foreach my $symhsh(\%fam) {
304    my @allsyms = keys %$symhsh;
305    foreach my $havsym (@allsyms) {
306      unless (grep {/$havsym/} @wantafsyms) {
307        delete $symhsh->{$havsym};	# delete unneeded symbol here
308        delete $ru{$havsym};		# and in unique hash
309      }
310    }
311  }
312  %unique = reverse %ru;
313
314# fill done, bump max value
315  ++$endv;
316# we're going to ignore all that end value tracking because IFF's exceed I32
317# I32 size. Use the max number that fits in an I32 and do IFF's another way
318  $endv = (2**31) -1;
319
320  mkdir 'lib' unless -e 'lib' && -d 'lib';
321  mkdir 'lib/Net' unless -e 'lib/Net' && -d 'lib/Net';
322  mkdir 'lib/Net/Interface' unless -e 'lib/Net/Interface' && -d 'lib/Net/Interface';
323
324  open(NFe,'>lib/Net/Interface/NetSymbols.pm') or die "could not open NetSymbols.pm for write";
325  open(NFx,'>netsymbolXS.inc') or die "could not open netsymbolXS.inc for write";
326  open(NFc,'>netsymbolC.inc') or die "could not open netsymbolC.inc for write";
327  open(NFt,'>ni_IFF_inc.c') or die "could not open ni_IFF_inc.c for write";
328  open(NFz,'>ni_XStabs_inc.c') or die "could not open ni_XStabs_inc.c for write";
329
330  print NFz q|/*	BEGIN ni_XStabs_inc.c
331 * ************************************************************	*
332 *	DO NOT ALTER THIS FILE					*
333 *	IT IS WRITTEN BY Makefile.PL & inst/netsymbols.pl	*
334 *	EDIT THOSE INSTEAD					*
335 * ************************************************************	*
336 * 	some of these symbols may be redundant			*
337 * ************************************************************	*/
338
339|;
340# make defines for synonyms
341  extradef(*NFc,\%fam,qw( PF_LOCAL PF_UNIX PF_FILE AF_LOCAL AF_FILE AF_UNIX )); # are all synonyms
342  extradef(*NFc,\%fam,qw( PF_MAX AF_MAX ));
343  extradef(*NFc,\%fam,qw( AF_PACKET PF_PACKET AF_ROUTE PF_ROUTE ));
344  extradef(*NFc,\%fam,qw( AF_ISO PF_ISO AF_BRIDGE PF_BRIDGE ));
345# this one is not correct...  extradef(*NFc,\%fam,qw( AF_NS PF_NS AF_NUTSS PF_NUTSS AF_ATM PF_ATM ));
346
347  extradef(*NFc,\%ifs,qw( IFNAMSIZ IF_NAMESIZE ));
348
349# Fix missing definition
350  print NFc "#ifndef IFHWADDRLEN\n#define IFHWADDRLEN 6\n#endif\n";
351  $ifs{IFHWADDRLEN} = 6;
352
353# Add opening definition
354  print NFc qq|
355#define __NI_AF_TEST $endv
356|;
357  print NFz q|
358const ni_iff_t ni_af_sym_tab[] = {
359|;
360### populate exports
361
362  print NFe q|#!|. $conf->{perlpath} .q|
363#
364# DO NOT ALTER THIS FILE
365# IT IS WRITTEN BY Makefile.PL and inst/netsymbols.pl
366# EDIT THOSE INSTEAD
367#
368package Net::Interface::NetSymbols;
369use vars qw($VERSION @EXPORT_OK %EXPORT_TAGS);
370
371$VERSION = 1.01;
372
373|;
374
375  print NFx q|void
376_net_af_syms()
377    ALIAS:
378|;
379
380### populate IFF flags
381#
382  print NFt q|
383/*	BEGIN ni_IFF_inc.c	include
384 ****************************************************************
385 *	DO NOT ALTER THIS FILE					*
386 *	IT IS WRITTEN BY Makefile.PL & inst/netsymbols.pl	*
387 *	EDIT THOSE INSTEAD					*
388 ****************************************************************
389 */
390
391const ni_iff_t ni_iff_tab[] = {
392|;
393
394### populate C portion
395#
396  my @tmp = grep {/^AF/} keys %fam;	# tmp store AFs
397  my @afs = sort { $fam{$a} <=> $fam{$b} } @tmp;
398
399  @tmp = grep {/^PF/} keys %fam;
400  my @pfs = sort { $fam{$a} <=> $fam{$b} } @tmp;
401
402  my @ifs = keys %ifs;
403# iffs are not unique so we can safely purge unwanted symbols here
404  my @iffs = sort grep {/^IFF_/ && $_ !~ /IFF_DRV/} keys %ifs;
405  my @iffIN6 = sort grep {/^IN6_IFF/} keys %ifs;
406
407#foreach (@iffs) {
408#  print STDERR "$_\t=> $ifs{$_}\n";
409#}
410  print NFe q|my @afs = qw(
411|;
412
413  foreach(@afs) {
414    $_ =~ /AF_([^\s]+)/;
415    print NFx "\t$_ = _NI_$_\n";
416    print NFe "\t$_\n";
417    print NFc qq|#ifdef $_\n\# define _NI_$_ $fam{$_}\n#else\n# define _NI_$_ $endv\n#endif\n|;
418    print NFz qq|\t{$_,\t"|, (lc $1), qq|"},\n|;
419  }
420  print NFe q|);
421my @pfs = qw(
422|;
423  foreach(@pfs) {
424    $_ =~ /PF_([^\s]+)/;
425    print NFx "\t$_ = _NI_$_\n";
426    print NFe "\t$_\n";
427    print NFc qq|#ifdef $_\n\# define _NI_$_ $fam{$_}\n#else\n# define _NI_$_ $endv\n#endif\n|;
428    print NFz qq|\t{$_,\t"|, (lc $1), qq|"},\n|;
429  }
430  print NFz qq|\t{__NI_AF_TEST,\t"placeholder"}
431};
432|;
433
434  print NFx qq|\t_NI_AF_TEST = __NI_AF_TEST
435    PREINIT:
436	SV * rv;
437	int n, i;
438    PPCODE:
439	if (ix >= $endv) {
440	    croak("%s is not implemented on this architecture", GvNAME(CvGV(cv)));
441	}
442	rv = sv_2mortal(newSViv(ix));
443	n = sizeof(ni_af_sym_tab) / sizeof(ni_iff_t);
444	for (i=0; i<n; i++) {
445	    if (ni_af_sym_tab[i].iff_val == ix) {
446		sv_setpv(rv,ni_af_sym_tab[i].iff_nam);
447		break;
448	    }
449	}
450	SvIOK_on(rv);
451	XPUSHs(rv);
452	XSRETURN(1);
453
454
455int
456_net_if_syms()
457    ALIAS:
458|;
459
460  print NFe q|);
461my @ifs = qw(
462|;
463
464  my $ifidx = 0;
465  my $idxary = q|
466const u_int64_t bigsymvals[] = {|;
467  my $icoma = '';
468
469  foreach (@ifs) {
470    print NFe "\t$_\n";
471    next if $_ =~ /IFF_/;
472    print NFc qq|#ifdef $_\n\# define _NI_$_ $_\n#else\n# define _NI_$_ $endv\n#endif\n|;
473#  print NFx "\t$_ = _NI_$_\n";
474    print NFx "\t$_ = $ifidx\n";
475    $idxary .= "$icoma\n\t$ifs{$_}";
476    $icoma = ',';
477    $ifidx++;
478  }
479
480  print NFz qq|
481const ni_iff_t ni_sym_iff_tab[] = {
482|;
483
484  print NFe q|);
485my @iffs = qw(
486|;
487
488  print NFx qq|    CODE:
489	if (ix >= $endv) {
490	    croak("%s is not implemented on this architecture", GvNAME(CvGV(cv)));
491	}
492	RETVAL = bigsymvals[ix];
493    OUTPUT:
494	RETVAL
495
496
497void
498_net_i2f_syms()
499    ALIAS:
500|;
501
502  $comma = '';
503  foreach(sort @iffs) {
504    $_ =~ /IFF_([^\s]+)/;
505    print NFc qq|#ifdef $_\n\# define _NI_$_ $_\n#else\n# define _NI_$_ $endv\n#endif\n|;
506    print NFz qq|\t{$_,\t"|, (lc $1), qq|"},\n|;
507    print NFe "\t$_\n";
508#  print NFx "\t$_ = _NI_$_\n";
509    print NFx "\t$_ = $ifidx\n";
510    $idxary .= "$icoma\n\t$ifs{$_}";
511    $ifidx++;
512    next if $_ eq 'IFF_UP';	# special case handled separately
513    print NFt qq|$comma\n\t\{$_,\t"$1"\}|;
514    $comma = ',';
515  }
516  print NFt q|
517};
518
519#ifdef HAVE_STRUCT_IN6_IFREQ
520const ni_iff_t ni_iff_tabIN6[] = {
521|;
522
523  print NFe q|);
524my @iffIN6 = qw(
525|;
526
527  $comma = '';
528  foreach(sort @iffIN6) {
529    $_ =~ /IFF_([^\s]+)/;
530    print NFc qq|#ifdef $_\n\# define _NI_$_ $_\n#else\n# define _NI_$_ $endv\n#endif\n|;
531    print NFz qq|\t{$_,\t"|. (lc $1). qq|"},\n|;
532    next if $_ eq 'IFF_UP';	# special case handled separately
533    print NFe "\t$_\n";
534#  print NFx "\t$_ = _NI_$_\n";
535    print NFx "\t$_ = $ifidx\n";
536    $idxary .= "$icoma\n\t$ifs{$_}";
537    $ifidx++;
538    print NFt qq|$comma\n\t\{$_,\t"$1"\}|;
539    $comma = ',';
540  }
541  print NFz qq|\t{__NI_AF_TEST,\t"placeholder"}
542};
543
544$idxary
545};
546|;
547
548  print NFt q|
549};
550#endif
551/*	END ni_IFF_inc.c	include		*/
552|;
553
554  print NFe q|);
555my %unique = (
556|;
557
558  my $utxt = '';
559  foreach(sort {$a <=> $b} keys %unique) {
560    $utxt .= "\t$_\t=> '". $unique{$_} ."',\n";
561  }
562
563  print NFe $utxt, q|);
564
565my @iftype = qw(
566    IPV6_ADDR_ANY
567    IPV6_ADDR_UNICAST
568    IPV6_ADDR_MULTICAST
569    IPV6_ADDR_ANYCAST
570    IPV6_ADDR_LOOPBACK
571    IPV6_ADDR_LINKLOCAL
572    IPV6_ADDR_SITELOCAL
573    IPV6_ADDR_COMPATv4
574    IPV6_ADDR_SCOPE_MASK
575    IPV6_ADDR_MAPPED
576    IPV6_ADDR_RESERVED
577    IPV6_ADDR_ULUA
578    IPV6_ADDR_6TO4
579    IPV6_ADDR_6BONE
580    IPV6_ADDR_AGU
581    IPV6_ADDR_UNSPECIFIED
582    IPV6_ADDR_SOLICITED_NODE
583    IPV6_ADDR_ISATAP
584    IPV6_ADDR_PRODUCTIVE
585    IPV6_ADDR_6TO4_MICROSOFT
586    IPV6_ADDR_TEREDO
587    IPV6_ADDR_ORCHID
588    IPV6_ADDR_NON_ROUTE_DOC
589);
590
591my @scope = qw(
592    RFC2373_GLOBAL
593    RFC2373_ORGLOCAL
594    RFC2373_SITELOCAL
595    RFC2373_LINKLOCAL
596    RFC2373_NODELOCAL
597    LINUX_COMPATv4
598);
599
600@EXPORT_OK = (@afs,@pfs,@ifs,@iftype,@scope);
601%EXPORT_TAGS = (
602	all	=> [@afs,@pfs,@ifs,@iftype,@scope],
603	afs	=> [@afs],
604	pfs	=> [@pfs],
605	ifs	=> [@ifs],
606	iffs	=> [@iffs],
607	iffIN6	=> [@iffIN6],
608	iftype	=> [@iftype],
609	scope	=> [@scope],
610);
611
612sub NI_ENDVAL {return |. $endv .q|};
613sub NI_UNIQUE {return \%unique};
614sub DESTROY {};
615
6161;
617__END__
618
619=head1 NAME
620
621Net::Interface::NetSymbols - AF_ PF_ IFxxx type symbols
622
623=head1 SYNOPSIS
624
625This module is built for this specific architecture during the F<make>
626process using F<inst/netsymbols.pl>. Do not edit this module, edit
627F<inst/netsymbols.pl> instead.
628
629This module contains symbols arrays only for use by Net::Interface, in all other
630respects it is NOT functional. It contains documentation and data arrays
631for this specific architecture.
632
633B<NOTE:>	WARNING !!
634
635     usage is Net::Interface
636
637B<NOT>  Net::Interface::NetSymbols
638
639use Net::Interface qw(
640
641	Net::Interface::NetSymbols::NI_ENDVAL();
642	Net::Interface::NetSymbols::NI_UNIQUE();
643|;
644
645  print NFe qq|@afs
646
647@pfs
648
649@ifs
650
651@iffs
652|;
653
654  if (@iffIN6) {
655    print NFe qq|
656@iffIN6	populated for BSD flavored systems
657
658:all :afs :pfs :ifs :iffs :iffIN6 :iftype :scope
659
660);
661|;
662  } else {
663    print NFe qq|
664:all :afs :pfs :ifs :iffs :iftype :scope
665
666);
667|;
668  }
669  print NFe q|
670=head1 DESCRIPTION
671
672All of the AF_XXX and PF_XXX symbols available in local C<sys/socket.h> plus
673usual aliases for AF_LOCAL i.e. (AF_FILE AF_UNIX PF_LOCAL PF_FILE PF_UNIX)
674
675All of the IFxxxx and IN6_IF symbols in C<net/if.h, netinet/in.h, netinet/in_var.h> and
676their includes.
677
678Symbols may be accessed for their numeric value or their string name.
679
680  i.e.	if ($family == AF_INET)
681	    do something...
682
683    or	print AF_INET
684    will product the string "inet"
685
686The same holds true for:
687
688	printf("family is %s",AF_INET);
689    or	sprint("family is %s",AF_INET);
690
691To print the numeric value of the SYMBOL do:
692
693	print (0 + SYMBOL), "\n";
694
695|;
696
697  if (exists $fam{AF_INET6}) {
698    print NFe q|On systems supporting IPV6, these additional symbols are available which
699may be applied to the address I<type> to determine the address attributes.
700
701    IPV6_ADDR_ANY		unknown
702    IPV6_ADDR_UNICAST		unicast
703    IPV6_ADDR_MULTICAST		multicast
704    IPV6_ADDR_ANYCAST		anycast
705    IPV6_ADDR_LOOPBACK		loopback
706    IPV6_ADDR_LINKLOCAL		link-local
707    IPV6_ADDR_SITELOCAL		site-local
708    IPV6_ADDR_COMPATv4		compat-v4
709    IPV6_ADDR_SCOPE_MASK	scope-mask
710    IPV6_ADDR_MAPPED		mapped
711    IPV6_ADDR_RESERVED		reserved
712    IPV6_ADDR_ULUA		uniq-lcl-unicast
713    IPV6_ADDR_6TO4		6to4
714    IPV6_ADDR_6BONE		6bone
715    IPV6_ADDR_AGU		global-unicast
716    IPV6_ADDR_UNSPECIFIED	unspecified
717    IPV6_ADDR_SOLICITED_NODE	solicited-node
718    IPV6_ADDR_ISATAP		ISATAP
719    IPV6_ADDR_PRODUCTIVE	productive
720    IPV6_ADDR_6TO4_MICROSOFT	6to4-ms
721    IPV6_ADDR_TEREDO		teredo
722    IPV6_ADDR_ORCHID		orchid
723    IPV6_ADDR_NON_ROUTE_DOC	non-routeable-doc
724
725    if ($type & IPV6_ADDR_xxxx) {
726	print IPV6_ADDR_xxxx,"\n";
727    }
728
729These symbols may be equated to the I<scope> of the address.
730
731    RFC2373_GLOBAL		global-scope
732    RFC2373_ORGLOCAL		org-local
733    RFC2373_SITELOCAL		site-local
734    RFC2373_LINKLOCAL		link-local
735    RFC2373_NODELOCAL		loopback
736    LINUX_COMPATv4		lx-compat-v4
737
738    if ($scope eq RFC2373_xxxx) {
739	print RFC2373_xxxx,"\n";
740    }
741
742|;
743  }
744
745  print NFe q|
746=over 4
747
748=item * :all	Import all symbols
749
750=item * :afs	Import all AF_XXX symbols
751
752=item * :pfs	Import all PF_XXX symbols
753
754=item * :ifs	Import all IFxxxx symbols
755
756=item * :iffs	Import all IFF symbols
757|;
758
759  if (@iffIN6) {
760    print NFe q|
761=item * :iffIN6	Import all IN6_IFF symbols (BSD flavors only)
762|;
763  }
764
765  if (exists $fam{AF_INET6}) {
766    print NFe q|
767=item * :iftype	Import all IPV6 type symbols
768
769=item * :scope	Import all IPV6 scope symbols
770|;
771  }
772
773  print NFe q|
774=back
775
776=head1 non EXPORT functions
777
778=over 4
779
780=item * Net::Interface::NetSymbols::NI_ENDVAL();
781
782Reports the highest symbol value +1 of :all symbols above. Used for testing.
783
784=item * Net::Interface::NetSymbols::NI_UNIQUE();
785
786Returns a hash pointer to the AF_ or PF_ symbol values mapped to their
787character strings as defined for this architecture.
788
789  i.e.
790|, $utxt, q|
791=head1 AUTHOR	Michael Robinton <michael@bizsystems.com>
792
793=head1 COPYRIGHT	|. ((localtime())[5] +1900) .q|
794
795Michael Robinton, all rights reserved.
796
797This library is free software. You can distribute it and/or modify it under
798the same terms as Perl itself.
799
800=cut
801
8021;
803|;
804
805# add test element and complete
806  print NFx qq|    PREINIT:
807	SV * rv;
808	int n, i;
809    PPCODE:
810	if (ix >= $endv) {
811	    croak("%s is not implemented on this architecture", GvNAME(CvGV(cv)));
812	}
813	rv = sv_2mortal(newSVnv(bigsymvals[ix]));
814	n = sizeof(ni_sym_iff_tab) / sizeof(ni_iff_t);
815	for (i=0; i<n; i++) {
816	    if (ni_sym_iff_tab[i].iff_val == bigsymvals[ix]) {
817		sv_setpv(rv,ni_sym_iff_tab[i].iff_nam);
818		break;
819	    }
820	}
821	SvNOK_on(rv);
822	XPUSHs(rv);
823	XSRETURN(1);
824
825|;
826
827# usually _LOCAL is defined on modern systems
828#
829
830  close NFe;
831  close NFx;
832  close NFc;
833  close NFt;
834#  exit;
835}
836gensyms();
8371;
838