| line | stmt | bran | cond | sub | pod | time | code | 
| 1 |  |  |  |  |  |  | package Net::DNS::ToolKit::RR; | 
| 2 |  |  |  |  |  |  |  | 
| 3 |  |  |  |  |  |  | #use 5.006; | 
| 4 | 14 |  |  | 14 |  | 10363 | use strict; | 
|  | 14 |  |  |  |  | 27 |  | 
|  | 14 |  |  |  |  | 1011 |  | 
| 5 |  |  |  |  |  |  | #use diagnostics; | 
| 6 |  |  |  |  |  |  | #use warnings; | 
| 7 |  |  |  |  |  |  |  | 
| 8 | 14 |  |  | 14 |  | 77 | use Net::DNS::Codes qw(:RRs); | 
|  | 14 |  |  |  |  | 21 |  | 
|  | 14 |  |  |  |  | 8632 |  | 
| 9 | 14 |  |  |  |  | 1117 | use Net::DNS::ToolKit qw( | 
| 10 |  |  |  |  |  |  | get16 | 
| 11 |  |  |  |  |  |  | get32 | 
| 12 |  |  |  |  |  |  | put16 | 
| 13 |  |  |  |  |  |  | put32 | 
| 14 |  |  |  |  |  |  | getstring | 
| 15 |  |  |  |  |  |  | dn_comp | 
| 16 |  |  |  |  |  |  | dn_expand | 
| 17 | 14 |  |  | 14 |  | 193 | ); | 
|  | 14 |  |  |  |  | 31 |  | 
| 18 | 14 |  |  | 14 |  | 83 | use vars qw($VERSION $autoload *sub); | 
|  | 14 |  |  |  |  | 25 |  | 
|  | 14 |  |  |  |  | 17115 |  | 
| 19 |  |  |  |  |  |  | require Net::DNS::ToolKit::Question; | 
| 20 |  |  |  |  |  |  |  | 
| 21 |  |  |  |  |  |  | $VERSION = do { my @r = (q$Revision: 0.09 $ =~ /\d+/g); sprintf "%d."."%02d" x $#r, @r }; | 
| 22 |  |  |  |  |  |  |  | 
| 23 |  |  |  |  |  |  | sub remoteload { | 
| 24 |  |  |  |  |  |  | #    *sub = $autoload; | 
| 25 | 23 |  |  | 23 | 0 | 151 | (my $RRtype = $autoload ) =~ s/.*::(\w+):://; | 
| 26 |  |  |  |  |  |  | # function = $1, one of get,put,parse | 
| 27 | 23 |  |  |  |  | 41 | local $_; | 
| 28 | 23 |  |  |  |  | 76 | ($autoload,$_) = instantiate($RRtype,$1); | 
| 29 |  |  |  |  |  |  | #    my $code = 'package '. __PACKAGE__ .'::'. $1 .'; '.'*'. $RRtype .'=\&'. $autoload; | 
| 30 | 23 |  |  |  |  | 128 | my $code = 'package '. __PACKAGE__ .'::'. $1 .'; '.'*'. $RRtype . | 
| 31 |  |  |  |  |  |  | q| = sub { unshift @_,'|. $autoload . q|'; &|. $_ .'};'; | 
| 32 | 23 |  |  | 0 |  | 1967 | eval "$code"; | 
|  | 0 |  |  |  |  | 0 |  | 
|  | 0 |  |  |  |  | 0 |  | 
|  | 0 |  |  |  |  | 0 |  | 
|  | 0 |  |  |  |  | 0 |  | 
|  | 0 |  |  |  |  | 0 |  | 
|  | 0 |  |  |  |  | 0 |  | 
| 33 |  |  |  |  |  |  |  | 
| 34 |  |  |  |  |  |  | # print "AUTOLOAD=",*sub,";\n"; | 
| 35 |  |  |  |  |  |  | # print "subname=$autoload RRtype=$RRtype func=$1\n"; | 
| 36 |  |  |  |  |  |  | # print 'code=', $code, "\n"; | 
| 37 |  |  |  |  |  |  |  | 
| 38 |  |  |  |  |  |  | #    no strict; | 
| 39 |  |  |  |  |  |  | #    eval { *sub = sub { unshift @_,$autoload; &$_ } }; | 
| 40 |  |  |  |  |  |  | #    goto &{*sub}; | 
| 41 | 23 |  |  |  |  | 83 | unshift @_,$autoload; | 
| 42 | 23 |  |  |  |  | 127 | goto &$_; | 
| 43 |  |  |  |  |  |  | } | 
| 44 |  |  |  |  |  |  |  | 
| 45 |  |  |  |  |  |  | # return target function, target interpreter | 
| 46 |  |  |  |  |  |  | sub instantiate { | 
| 47 | 28 |  |  | 28 | 0 | 76 | my($RRtype,$func) = @_; | 
| 48 | 28 | 50 |  |  |  | 85 | if ($RRtype eq 'DESTROY') {	# should never get here | 
| 49 | 0 |  |  |  |  | 0 | die __PACKAGE__.".pm: DESTROY must be defined internally in the calling package\n"; | 
| 50 |  |  |  |  |  |  | } else { | 
| 51 | 28 |  |  |  |  | 80 | my $filename = __PACKAGE__.'::'.$RRtype.'.pm'; | 
| 52 | 28 |  |  |  |  | 123 | $filename =~ s#::#/#g; | 
| 53 | 28 |  |  |  |  | 51 | my $save = $@; | 
| 54 | 28 |  |  |  |  | 46 | eval { local $SIG{__DIE__}; require $filename }; | 
|  | 28 |  |  |  |  | 102 |  | 
|  | 28 |  |  |  |  | 13765 |  | 
| 55 | 28 | 100 |  |  |  | 138 | if ($@) { | 
| 56 |  |  |  |  |  |  | #	    die __PACKAGE__.'::RR'.$func.' not implemented' | 
| 57 |  |  |  |  |  |  | #		if $func eq 'put'; | 
| 58 |  |  |  |  |  |  | #	    $@ = $save; | 
| 59 |  |  |  |  |  |  | #	    $RRtype = 'NotImplemented'; | 
| 60 | 12 |  |  |  |  | 18 | my $generic; | 
| 61 | 12 | 100 | 66 |  |  | 116 | if (	$RRtype =~ /^TYPE(\d+)$/ && | 
|  |  |  | 66 |  |  |  |  | 
| 62 |  |  |  |  |  |  | ($generic = TypeTxt->{$1}) && | 
| 63 |  |  |  |  |  |  | $generic =~ /T_(.+)/) { | 
| 64 | 2 |  |  |  |  | 33 | $generic = __PACKAGE__.'::'. $1; | 
| 65 |  |  |  |  |  |  | } else { | 
| 66 | 10 |  |  |  |  | 95 | $generic = __PACKAGE__.'::TYPE'; | 
| 67 |  |  |  |  |  |  | } | 
| 68 | 12 |  |  |  |  | 34 | local $_ = $generic .'.pm'; | 
| 69 | 12 |  |  |  |  | 51 | s#::#/#g; | 
| 70 | 12 |  |  |  |  | 4994 | require $_; | 
| 71 | 12 |  |  |  |  | 62 | my $code = 'package '. __PACKAGE__ .'::'. $RRtype .'; | 
| 72 |  |  |  |  |  |  | *get = \&'. $generic .'::get; | 
| 73 |  |  |  |  |  |  | *put = \&'. $generic .'::put; | 
| 74 |  |  |  |  |  |  | *parse = \&'. $generic .'::parse;'; | 
| 75 | 12 |  |  |  |  | 1122 | eval "$code"; | 
| 76 |  |  |  |  |  |  | } | 
| 77 |  |  |  |  |  |  | } | 
| 78 |  |  |  |  |  |  | # package from local scope | 
| 79 | 28 |  |  |  |  | 158 | return (__PACKAGE__.'::'.$RRtype.'::'.$func, __PACKAGE__.'::RR'.$func); | 
| 80 |  |  |  |  |  |  | } | 
| 81 |  |  |  |  |  |  |  | 
| 82 |  |  |  |  |  |  | # return instantiated function | 
| 83 |  |  |  |  |  |  | sub make_function { | 
| 84 | 10 |  |  | 10 | 0 | 19 | my $type = shift; | 
| 85 | 10 |  |  |  |  | 87 | (caller(1))[3] =~ /RR(\w+)$/; | 
| 86 | 10 |  |  |  |  | 27 | my $action = $1; | 
| 87 | 10 |  |  |  |  | 19 | local $_; | 
| 88 | 10 | 100 | 66 |  |  | 39 | if (($_ = TypeTxt->{$type}) && $_ =~ /T_(.+)/) {	# type is real? | 
| 89 | 4 |  |  |  |  | 62 | my $function = __PACKAGE__.'::'.$1; | 
| 90 | 4 | 100 |  |  |  | 62 | if ($function->can($action)) {	# if function is instantiated | 
| 91 | 3 |  |  |  |  | 13 | return $function .= '::'.$action; | 
| 92 |  |  |  |  |  |  | } else {				# instantiate it or NotImplemented | 
| 93 | 1 |  |  |  |  | 4 | return (instantiate($1,$action))[0]; | 
| 94 |  |  |  |  |  |  | } | 
| 95 |  |  |  |  |  |  | } else { | 
| 96 |  |  |  |  |  |  | #  return __PACKAGE__.'::NotImplemented::'.$action; | 
| 97 | 6 |  |  |  |  | 55 | my $function = __PACKAGE__.'::TYPE'. $type; | 
| 98 | 6 | 100 |  |  |  | 82 | if ($function->can($action)) {	# if function is instantiated | 
| 99 | 2 |  |  |  |  | 8 | return $function .= '::'.$action; | 
| 100 |  |  |  |  |  |  | } else {				# instantiate it or NotImplemented | 
| 101 | 4 |  |  |  |  | 20 | return (instantiate("TYPE$type",$action))[0]; | 
| 102 |  |  |  |  |  |  | } | 
| 103 |  |  |  |  |  |  | } | 
| 104 |  |  |  |  |  |  | } | 
| 105 |  |  |  |  |  |  |  | 
| 106 |  |  |  |  |  |  | ######################################################### | 
| 107 |  |  |  |  |  |  | #	implements the common portion of... | 
| 108 |  |  |  |  |  |  | #  ($newoff,$name,$type,$class,$ttl,$rdlength,$rdata,...) | 
| 109 |  |  |  |  |  |  | #        = $get->next(\$buffer,$offset); | 
| 110 |  |  |  |  |  |  |  | 
| 111 |  |  |  |  |  |  | sub RRget { | 
| 112 | 12 |  |  | 12 | 0 | 30 | my($function,$self,$bp,$newoff) = @_; | 
| 113 | 12 |  |  |  |  | 87 | my ($off,$name) = dn_expand($bp,$newoff); | 
| 114 | 12 |  |  |  |  | 113 | (my $type, $off) = get16($bp,$off); | 
| 115 | 12 |  |  |  |  | 45 | (my $class, $off) = get16($bp,$off); | 
| 116 | 12 |  |  |  |  | 48 | (my $ttl, $off) = get32($bp,$off); | 
| 117 | 12 |  |  |  |  | 38 | my $rdlength = get16($bp,$off);	# scalar context, don't get offset | 
| 118 | 12 | 100 |  |  |  | 71 | $function = make_function($type) unless $function; | 
| 119 | 14 |  |  | 14 |  | 110 | no strict; | 
|  | 14 |  |  |  |  | 37 |  | 
|  | 14 |  |  |  |  | 3102 |  | 
| 120 | 12 |  |  |  |  | 78 | ($off, my @results) = &$function($self,$bp,$off); | 
| 121 | 12 |  |  |  |  | 201 | return($off,$name,$type,$class,$ttl,$rdlength,@results); | 
| 122 |  |  |  |  |  |  | } | 
| 123 |  |  |  |  |  |  |  | 
| 124 |  |  |  |  |  |  | ######################################################### | 
| 125 |  |  |  |  |  |  | #	implements the common portions of... | 
| 126 |  |  |  |  |  |  | #  ($newoff,@dnptrs)=$put->XYZ(\$buffer,$offset,\@dnptrs, | 
| 127 |  |  |  |  |  |  | #        $name,$type,$class,$ttl,$rdata,...); | 
| 128 |  |  |  |  |  |  |  | 
| 129 |  |  |  |  |  |  | sub RRput { | 
| 130 |  |  |  |  |  |  | # extract common elements from input, shrink input | 
| 131 |  |  |  |  |  |  | # input was: $function,$self,\$buffer,$offset,\@dnptrs,$name,$type,$class,$ttl,@rdata | 
| 132 | 10 |  |  | 10 | 0 | 42 | my ($func,$put,$bp,$off,$dnp,$name,$type,$class,$ttl) = @_; | 
| 133 | 10 | 100 |  |  |  | 80 | if (exists $_[1]->{class}) { | 
| 134 | 1 |  |  |  |  | 5 | ($func,$put,$bp,$off,$dnp,$name,$ttl) = splice(@_,0,7); | 
| 135 | 1 |  |  |  |  | 3 | $class = $put->{class}; | 
| 136 | 1 |  |  |  |  | 5 | $func =~ /.+::(.+)::put$/; | 
| 137 | 1 |  |  |  |  | 2 | $type = 'T_'.$1; | 
| 138 | 14 |  |  | 14 |  | 119 | no strict; | 
|  | 14 |  |  |  |  | 36 |  | 
|  | 14 |  |  |  |  | 3157 |  | 
| 139 | 1 |  |  |  |  | 7 | $type = &$type; | 
| 140 |  |  |  |  |  |  | } else { | 
| 141 | 9 |  |  |  |  | 60 | ($func,$put,$bp,$off,$dnp,$name,$type,$class,$ttl) = splice(@_,0,9); | 
| 142 |  |  |  |  |  |  | } | 
| 143 |  |  |  |  |  |  | # input is now: @rdata | 
| 144 | 10 | 50 |  |  |  | 70 | die "'names' ending in '.' are not allowed per RFC's\n" | 
| 145 |  |  |  |  |  |  | if $name =~ /\.$/; | 
| 146 | 10 |  |  |  |  | 296 | ($off, my @dnptrs) = dn_comp($bp,$off,\$name,$dnp); | 
| 147 | 10 | 50 |  |  |  | 52 | unless (@dnptrs) {		# if not valid return | 
| 148 | 0 |  |  |  |  | 0 | while(shift) {};		# empty the input array | 
| 149 | 0 |  |  |  |  | 0 | return ();			# error | 
| 150 |  |  |  |  |  |  | } | 
| 151 | 10 | 50 |  |  |  | 70 | return () unless ($off = put16($bp,$off,$type)); | 
| 152 |  |  |  |  |  |  | # the rest should work since offset has been checked | 
| 153 | 10 |  |  |  |  | 35 | $off = put16($bp,$off,$class);# class | 
| 154 | 10 |  |  |  |  | 35 | $off = put32($bp,$off,$ttl);# ttl | 
| 155 | 14 |  |  | 14 |  | 79 | no strict; | 
|  | 14 |  |  |  |  | 27 |  | 
|  | 14 |  |  |  |  | 2312 |  | 
| 156 | 10 |  |  |  |  | 63 | &$func($self,$bp,$off,\@dnptrs,@_); | 
| 157 |  |  |  |  |  |  | } | 
| 158 |  |  |  |  |  |  |  | 
| 159 |  |  |  |  |  |  | #################################################################### | 
| 160 |  |  |  |  |  |  | #	implements the common portion of... | 
| 161 |  |  |  |  |  |  | #  ($name,$typeTXT,$classTXT,$ttl,$rdlength,$RDATA,...) | 
| 162 |  |  |  |  |  |  | #        = $parse->XYZ($name,$type,$class,$ttl,$rdlength,$rdata,...) | 
| 163 |  |  |  |  |  |  |  | 
| 164 |  |  |  |  |  |  | sub RRparse { | 
| 165 |  |  |  |  |  |  | # extract common elements from input, shrink input | 
| 166 |  |  |  |  |  |  | # input was: $function,$self,$name,$type,$class,$ttl,$rdlength,@rdata | 
| 167 | 11 |  |  | 11 | 0 | 34 | my $function = shift; | 
| 168 |  |  |  |  |  |  | # input is now: $name,$type,$class,$ttl,$rdlength,@rdata | 
| 169 | 11 |  |  |  |  | 51 | my ($name,$type,$class,$ttl,$rdlength) = splice(@_,1,5);	# pass $self,@rdata to $function call | 
| 170 |  |  |  |  |  |  | # if length is ever needed, add it here | 
| 171 |  |  |  |  |  |  | #  $_[0]->{len} = $rdlength; | 
| 172 | 11 |  |  |  |  | 47 | $name .= '.';	# terminate domain name | 
| 173 | 11 | 100 |  |  |  | 62 | $function = make_function($type) unless $function; | 
| 174 | 14 |  |  | 14 |  | 82 | no strict; | 
|  | 14 |  |  |  |  | 32 |  | 
|  | 14 |  |  |  |  | 1953 |  | 
| 175 | 11 |  | 66 |  |  | 50 | my $typetxt = TypeTxt->{$type} || "TYPE$type"; | 
| 176 | 11 |  | 33 |  |  | 118 | my $classtxt = ClassTxt->{$class} || "CLASS$class"; | 
| 177 | 11 |  |  |  |  | 86 | return($name,$typetxt,$classtxt,$ttl,$rdlength,&{$function}(@_)); | 
|  | 11 |  |  |  |  | 79 |  | 
| 178 |  |  |  |  |  |  | } | 
| 179 |  |  |  |  |  |  |  | 
| 180 |  |  |  |  |  |  | ##################################################################### | 
| 181 |  |  |  |  |  |  | ######################### sub PACKAGES ############################## | 
| 182 |  |  |  |  |  |  | ##################################################################### | 
| 183 |  |  |  |  |  |  |  | 
| 184 |  |  |  |  |  |  | # this entire sub package is obsolete as of v0.07 | 
| 185 |  |  |  |  |  |  | #{ | 
| 186 |  |  |  |  |  |  | #  package Net::DNS::ToolKit::RR::NotImplemented; | 
| 187 |  |  |  |  |  |  | # | 
| 188 |  |  |  |  |  |  | #  sub get { | 
| 189 |  |  |  |  |  |  | #    my($self,$bp,$offset) = @_; | 
| 190 |  |  |  |  |  |  | #    (my $rdlength, $offset) = &Net::DNS::ToolKit::get16($bp,$offset); | 
| 191 |  |  |  |  |  |  | #    $offset += $rdlength; | 
| 192 |  |  |  |  |  |  | #    return($offset,"\0"); | 
| 193 |  |  |  |  |  |  | #  } | 
| 194 |  |  |  |  |  |  | # | 
| 195 |  |  |  |  |  |  | ## die in loader, unimplemented | 
| 196 |  |  |  |  |  |  | ##  sub put { | 
| 197 |  |  |  |  |  |  | ##    my($bp,$off,$dp) = @_; | 
| 198 |  |  |  |  |  |  | ##    return($off,@$dp); | 
| 199 |  |  |  |  |  |  | ##  } | 
| 200 |  |  |  |  |  |  | # | 
| 201 |  |  |  |  |  |  | #  sub parse { | 
| 202 |  |  |  |  |  |  | #    shift;	# $self | 
| 203 |  |  |  |  |  |  | #    return(@_);	# garbage in, garbage out | 
| 204 |  |  |  |  |  |  | #  } | 
| 205 |  |  |  |  |  |  | #} | 
| 206 |  |  |  |  |  |  |  | 
| 207 |  |  |  |  |  |  | { | 
| 208 |  |  |  |  |  |  | package Net::DNS::ToolKit::RR::get; | 
| 209 | 14 |  |  | 14 |  | 84 | use vars qw($AUTOLOAD); | 
|  | 14 |  |  |  |  | 29 |  | 
|  | 14 |  |  |  |  | 2541 |  | 
| 210 |  |  |  |  |  |  |  | 
| 211 |  |  |  |  |  |  | # preload Question | 
| 212 |  |  |  |  |  |  | *Question = \&Net::DNS::ToolKit::Question::get; | 
| 213 |  |  |  |  |  |  |  | 
| 214 |  |  |  |  |  |  | sub AUTOLOAD { | 
| 215 | 5 |  |  | 5 |  | 3074 | $Net::DNS::ToolKit::RR::autoload = $AUTOLOAD; | 
| 216 | 5 |  |  |  |  | 16 | goto &Net::DNS::ToolKit::RR::remoteload; | 
| 217 |  |  |  |  |  |  | } | 
| 218 |  |  |  |  |  |  | sub next { | 
| 219 | 7 |  |  | 7 |  | 5365 | unshift @_,undef;	# flag to RRget; | 
| 220 | 7 |  |  |  |  | 30 | goto &Net::DNS::ToolKit::RR::RRget; | 
| 221 |  |  |  |  |  |  | } | 
| 222 | 0 |  |  | 0 |  | 0 | sub EmptyList {()}; | 
| 223 | 0 |  |  | 0 |  | 0 | sub DESTROY {}; | 
| 224 |  |  |  |  |  |  | } | 
| 225 |  |  |  |  |  |  |  | 
| 226 |  |  |  |  |  |  | { | 
| 227 |  |  |  |  |  |  | package Net::DNS::ToolKit::RR::put; | 
| 228 | 14 |  |  | 14 |  | 88 | use vars qw($AUTOLOAD); | 
|  | 14 |  |  |  |  | 53 |  | 
|  | 14 |  |  |  |  | 1622 |  | 
| 229 |  |  |  |  |  |  |  | 
| 230 |  |  |  |  |  |  | # preload Question | 
| 231 |  |  |  |  |  |  | *Question = \&Net::DNS::ToolKit::Question::put; | 
| 232 |  |  |  |  |  |  |  | 
| 233 |  |  |  |  |  |  | sub AUTOLOAD { | 
| 234 | 10 |  |  | 10 |  | 3693 | $Net::DNS::ToolKit::RR::autoload = $AUTOLOAD; | 
| 235 | 10 |  |  |  |  | 43 | goto &Net::DNS::ToolKit::RR::remoteload; | 
| 236 |  |  |  |  |  |  | } | 
| 237 | 0 |  |  | 0 |  | 0 | sub DESTROY {}; | 
| 238 |  |  |  |  |  |  | } | 
| 239 |  |  |  |  |  |  |  | 
| 240 |  |  |  |  |  |  | { | 
| 241 |  |  |  |  |  |  | package Net::DNS::ToolKit::RR::parse; | 
| 242 | 14 |  |  | 14 |  | 68 | use vars qw($AUTOLOAD); | 
|  | 14 |  |  |  |  | 25 |  | 
|  | 14 |  |  |  |  | 6486 |  | 
| 243 |  |  |  |  |  |  |  | 
| 244 |  |  |  |  |  |  | # preload Question | 
| 245 |  |  |  |  |  |  | *Question = \&Net::DNS::ToolKit::Question::parse; | 
| 246 |  |  |  |  |  |  |  | 
| 247 |  |  |  |  |  |  | sub AUTOLOAD { | 
| 248 | 8 |  |  | 8 |  | 10702 | $Net::DNS::ToolKit::RR::autoload = $AUTOLOAD; | 
| 249 | 8 |  |  |  |  | 37 | goto &Net::DNS::ToolKit::RR::remoteload; | 
| 250 |  |  |  |  |  |  | } | 
| 251 |  |  |  |  |  |  | # this next sub has been in the distro a long time | 
| 252 |  |  |  |  |  |  | # $parse->RR | 
| 253 |  |  |  |  |  |  | # this was unintentional but does not hurt anything | 
| 254 |  |  |  |  |  |  | sub RR { | 
| 255 | 0 |  |  | 0 |  | 0 | unshift @_,undef; # flag to RRparse; | 
| 256 | 0 |  |  |  |  | 0 | goto &Net::DNS::ToolKit::RR::RRparse; | 
| 257 |  |  |  |  |  |  | } | 
| 258 |  |  |  |  |  |  | # this SHOULD of been here instead of the above | 
| 259 |  |  |  |  |  |  | sub next { | 
| 260 | 3 |  |  | 3 |  | 1344 | unshift @_,undef; # flag to RRparse; | 
| 261 | 3 |  |  |  |  | 14 | goto &Net::DNS::ToolKit::RR::RRparse; | 
| 262 |  |  |  |  |  |  | } | 
| 263 | 0 |  |  | 0 |  | 0 | sub DESTROY {}; | 
| 264 |  |  |  |  |  |  | } | 
| 265 |  |  |  |  |  |  |  | 
| 266 |  |  |  |  |  |  | =head1 NAME | 
| 267 |  |  |  |  |  |  |  | 
| 268 |  |  |  |  |  |  | Net::DNS::ToolKit::RR - Resource Record class loader | 
| 269 |  |  |  |  |  |  |  | 
| 270 |  |  |  |  |  |  | =head1 SYNOPSIS | 
| 271 |  |  |  |  |  |  |  | 
| 272 |  |  |  |  |  |  | use Net::DNS::ToolKit::RR; | 
| 273 |  |  |  |  |  |  |  | 
| 274 |  |  |  |  |  |  | ($get,$put,$parse) = new Net::DNS::ToolKit::RR; | 
| 275 |  |  |  |  |  |  | or | 
| 276 |  |  |  |  |  |  | ($get,$put,$parse) = Net::DNS::ToolKit::RR->new; | 
| 277 |  |  |  |  |  |  |  | 
| 278 |  |  |  |  |  |  | retrieve the next record (type unknown) | 
| 279 |  |  |  |  |  |  | ($newoff,$name,$type,$class,$ttl,$rdlength,$rdata,...) | 
| 280 |  |  |  |  |  |  | = $get->next(\$buffer,$offset); | 
| 281 |  |  |  |  |  |  |  | 
| 282 |  |  |  |  |  |  | parse the current record (type in input fields) | 
| 283 |  |  |  |  |  |  | ($name,$typeTXT,$classTXT,$ttlTXT,$rdlength,$RDATA,...) | 
| 284 |  |  |  |  |  |  | = $parse->RR($name,$type,$class,$ttl,$rdlength, | 
| 285 |  |  |  |  |  |  | $rdata,...); | 
| 286 |  |  |  |  |  |  |  | 
| 287 |  |  |  |  |  |  | ($newoff,@dnptrs)=$put->XYZ(\$buffer,$offset,\@dnptrs, | 
| 288 |  |  |  |  |  |  | $name,$type,$class,$ttl,$rdata,...); | 
| 289 |  |  |  |  |  |  |  | 
| 290 |  |  |  |  |  |  | The 'get' and 'parse' operations can also be done | 
| 291 |  |  |  |  |  |  | by specific record type... | 
| 292 |  |  |  |  |  |  | ...but why would you use them instead of 'next' & 'RR'? | 
| 293 |  |  |  |  |  |  |  | 
| 294 |  |  |  |  |  |  | ($newoff,$name,$type,$class,$ttl,$rdlength,$rdata,...) | 
| 295 |  |  |  |  |  |  | = $get->XYZ(\$buffer,$offset); | 
| 296 |  |  |  |  |  |  |  | 
| 297 |  |  |  |  |  |  | ($name,$typeTXT,$classTXT,$ttlTXT,$rdlength,$RDATA,...) | 
| 298 |  |  |  |  |  |  | = $parse->XYZ($name,$type,$class,$ttl,$rdlength, | 
| 299 |  |  |  |  |  |  | $rdata,...); | 
| 300 |  |  |  |  |  |  |  | 
| 301 |  |  |  |  |  |  | or you can use the individual methods | 
| 302 |  |  |  |  |  |  | directly without calling "new" | 
| 303 |  |  |  |  |  |  |  | 
| 304 |  |  |  |  |  |  | @output=Net::DNS::ToolKit::RR::get->next(@input); | 
| 305 |  |  |  |  |  |  | @output=Net::DNS::ToolKit::RR::get->XYZ(@input); | 
| 306 |  |  |  |  |  |  | @output=Net::DNS::ToolKit::RR::put->XYZ(@input); | 
| 307 |  |  |  |  |  |  | @output=Net::DNS::ToolKit::RR::parse->RR(@input); | 
| 308 |  |  |  |  |  |  | @output=Net::DNS::ToolKit::RR::parse->XYZ(@input); | 
| 309 |  |  |  |  |  |  |  | 
| 310 |  |  |  |  |  |  | The Question section is a special case: | 
| 311 |  |  |  |  |  |  |  | 
| 312 |  |  |  |  |  |  | ($newoff,$name,type,class) = | 
| 313 |  |  |  |  |  |  | $get->Question(\$buffer,$offset); | 
| 314 |  |  |  |  |  |  | ($newoff,@dnptrs) = | 
| 315 |  |  |  |  |  |  | $put->Question(\$buffer,$offset, | 
| 316 |  |  |  |  |  |  | $name,$type,$class,\@dnptrs); | 
| 317 |  |  |  |  |  |  | ($name,$typeTXT,$classTXT) = | 
| 318 |  |  |  |  |  |  | $parse->Question($name,$type,$class); | 
| 319 |  |  |  |  |  |  |  | 
| 320 |  |  |  |  |  |  | =head1 ALTERNATE PUT METHOD SYNOPSIS | 
| 321 |  |  |  |  |  |  |  | 
| 322 |  |  |  |  |  |  | An alternate method for B is available for class specific | 
| 323 |  |  |  |  |  |  | submissions. This eliminates the need to specify TYPE and CLASS when doing a | 
| 324 |  |  |  |  |  |  | put. The generic form of a put command using this method is shown below but | 
| 325 |  |  |  |  |  |  | NOT detailed in the method descriptions. | 
| 326 |  |  |  |  |  |  |  | 
| 327 |  |  |  |  |  |  | ($get,$put,$parse) = new Net::DNS::ToolKit::RR(class_type); | 
| 328 |  |  |  |  |  |  | or | 
| 329 |  |  |  |  |  |  | ($get,$put,$parse) = Net::DNS::ToolKit::RR->new(C_IN); | 
| 330 |  |  |  |  |  |  |  | 
| 331 |  |  |  |  |  |  | The generic form of a C operation then becomes: | 
| 332 |  |  |  |  |  |  |  | 
| 333 |  |  |  |  |  |  | ($newoff,@dnptrs)=$put->XYZ(\$buffer,$offset,\@dnptrs, | 
| 334 |  |  |  |  |  |  | $name,$ttl,$rdate,...) | 
| 335 |  |  |  |  |  |  |  | 
| 336 |  |  |  |  |  |  | The only class currently supported at this time is C_IN. | 
| 337 |  |  |  |  |  |  |  | 
| 338 |  |  |  |  |  |  | NOTE: the use of this alternate method changes the number of required | 
| 339 |  |  |  |  |  |  | arguments to ALL put RR operations. These changes are NOT noted below in the | 
| 340 |  |  |  |  |  |  | method descriptions. | 
| 341 |  |  |  |  |  |  |  | 
| 342 |  |  |  |  |  |  | =head1 DESCRIPTION | 
| 343 |  |  |  |  |  |  |  | 
| 344 |  |  |  |  |  |  | B is the class loader for Resource Record classes. | 
| 345 |  |  |  |  |  |  | It provides an extensible wrapper for existing | 
| 346 |  |  |  |  |  |  | classes as well as the framework to easily add new RR classes. See: | 
| 347 |  |  |  |  |  |  | B | 
| 348 |  |  |  |  |  |  |  | 
| 349 |  |  |  |  |  |  | From RFC 1035 | 
| 350 |  |  |  |  |  |  |  | 
| 351 |  |  |  |  |  |  | 3.2.1. Format | 
| 352 |  |  |  |  |  |  |  | 
| 353 |  |  |  |  |  |  | All RRs have the same top level format shown below: | 
| 354 |  |  |  |  |  |  |  | 
| 355 |  |  |  |  |  |  | 1  1  1  1  1  1 | 
| 356 |  |  |  |  |  |  | 0  1  2  3  4  5  6  7  8  9  0  1  2  3  4  5 | 
| 357 |  |  |  |  |  |  | +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ | 
| 358 |  |  |  |  |  |  | |                      NAME                     | | 
| 359 |  |  |  |  |  |  | +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ | 
| 360 |  |  |  |  |  |  | |                      TYPE                     | | 
| 361 |  |  |  |  |  |  | +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ | 
| 362 |  |  |  |  |  |  | |                     CLASS                     | | 
| 363 |  |  |  |  |  |  | +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ | 
| 364 |  |  |  |  |  |  | |                      TTL                      | | 
| 365 |  |  |  |  |  |  | +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ | 
| 366 |  |  |  |  |  |  | |                   RDLENGTH                    | | 
| 367 |  |  |  |  |  |  | +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--| | 
| 368 |  |  |  |  |  |  | |                     RDATA                     | | 
| 369 |  |  |  |  |  |  | +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ | 
| 370 |  |  |  |  |  |  |  | 
| 371 |  |  |  |  |  |  | NAME	an owner name, i.e., the name of the node to which this | 
| 372 |  |  |  |  |  |  | resource record pertains. | 
| 373 |  |  |  |  |  |  |  | 
| 374 |  |  |  |  |  |  | TYPE	two octets containing one of the RR TYPE codes. | 
| 375 |  |  |  |  |  |  |  | 
| 376 |  |  |  |  |  |  | CLASS	two octets containing one of the RR CLASS codes. | 
| 377 |  |  |  |  |  |  |  | 
| 378 |  |  |  |  |  |  | TTL	a 32 bit signed integer that specifies the time interval | 
| 379 |  |  |  |  |  |  | that the resource record may be cached before the source | 
| 380 |  |  |  |  |  |  | of the information should again be consulted.  Zero | 
| 381 |  |  |  |  |  |  | values are interpreted to mean that the RR can only be | 
| 382 |  |  |  |  |  |  | used for the transaction in progress, and should not be | 
| 383 |  |  |  |  |  |  | cached.  For example, SOA records are always distributed | 
| 384 |  |  |  |  |  |  | with a zero TTL to prohibit caching.  Zero values can | 
| 385 |  |  |  |  |  |  | also be used for extremely volatile data. | 
| 386 |  |  |  |  |  |  |  | 
| 387 |  |  |  |  |  |  | RDLENGTH an unsigned 16 bit integer that specifies the length | 
| 388 |  |  |  |  |  |  | in octets of the RDATA field. | 
| 389 |  |  |  |  |  |  |  | 
| 390 |  |  |  |  |  |  | RDATA	a variable length string of octets that describes the | 
| 391 |  |  |  |  |  |  | resource.  The format of this information varies | 
| 392 |  |  |  |  |  |  | according to the TYPE and CLASS of the resource record. | 
| 393 |  |  |  |  |  |  |  | 
| 394 |  |  |  |  |  |  | =over 4 | 
| 395 |  |  |  |  |  |  |  | 
| 396 |  |  |  |  |  |  | =item * ($get,$put,$parse) = new Net::DNS::ToolKit::RR; | 
| 397 |  |  |  |  |  |  |  | 
| 398 |  |  |  |  |  |  | Retrieves the method pointers to B, B, and B for Queston | 
| 399 |  |  |  |  |  |  | section and Resource Records of a particular type. | 
| 400 |  |  |  |  |  |  |  | 
| 401 |  |  |  |  |  |  | =cut | 
| 402 |  |  |  |  |  |  |  | 
| 403 |  |  |  |  |  |  | sub new { | 
| 404 | 13 |  |  | 13 | 1 | 1899 | my ($proto,$class) = @_; | 
| 405 | 13 |  | 33 |  |  | 103 | my $package = ref($proto) || $proto; | 
| 406 | 13 |  |  |  |  | 30 | my $get  = {}; | 
| 407 | 13 |  |  |  |  | 70 | bless ($get, "${package}::get"); | 
| 408 | 13 | 100 | 66 |  |  | 86 | my $put = ($class && ClassTxt->{$class}) | 
| 409 |  |  |  |  |  |  | ? { class => $class, } : {}; | 
| 410 | 13 |  |  |  |  | 76 | bless ($put, "${package}::put"); | 
| 411 | 13 |  |  |  |  | 28 | my $parse = {}; | 
| 412 | 13 |  |  |  |  | 55 | bless ($parse, "${package}::parse"); | 
| 413 | 13 |  |  |  |  | 48 | return ($get,$put,$parse); | 
| 414 |  |  |  |  |  |  | } | 
| 415 |  |  |  |  |  |  |  | 
| 416 |  |  |  |  |  |  | =item * ($newoff,@common,$rdata,...) = | 
| 417 |  |  |  |  |  |  | $get->next(\$buffer,$offset); | 
| 418 |  |  |  |  |  |  |  | 
| 419 |  |  |  |  |  |  | Get the next Resource Record. | 
| 420 |  |  |  |  |  |  |  | 
| 421 |  |  |  |  |  |  | input:	pointer to buffer, | 
| 422 |  |  |  |  |  |  | offset into buffer | 
| 423 |  |  |  |  |  |  |  | 
| 424 |  |  |  |  |  |  | returns:	offset to next RR or section, | 
| 425 |  |  |  |  |  |  | (items common to all RR's) | 
| 426 |  |  |  |  |  |  | i.e.	$name,$type,$class,$ttl,$rdlength, | 
| 427 |  |  |  |  |  |  | $rdata,.... for this RR | 
| 428 |  |  |  |  |  |  | or	undef if the RR is unsupported. | 
| 429 |  |  |  |  |  |  |  | 
| 430 |  |  |  |  |  |  | HERE IS THE OPPORTUNITY FOR YOU TO ADD TO THIS PACKAGE. | 
| 431 |  |  |  |  |  |  | If your RR of interest is not supported, see: | 
| 432 |  |  |  |  |  |  |  | 
| 433 |  |  |  |  |  |  | Net::DNS::ToolKit::RR::Template in: | 
| 434 |  |  |  |  |  |  | .../Net/DNS/ToolKit/Template/Template.pm | 
| 435 |  |  |  |  |  |  |  | 
| 436 |  |  |  |  |  |  | Build the support for your Resource Record and submit it to CPAN as an | 
| 437 |  |  |  |  |  |  | extension to this package. | 
| 438 |  |  |  |  |  |  |  | 
| 439 |  |  |  |  |  |  | UN-IMPLEMENTED methods: $get->[unimplemented] returns a correct offset to | 
| 440 |  |  |  |  |  |  | the following RR, correct @common data and a single $rdata element | 
| 441 |  |  |  |  |  |  | containing a null ... "\0" to be precise. This works as either a numeric 0 | 
| 442 |  |  |  |  |  |  | (zero) or an end of string. | 
| 443 |  |  |  |  |  |  |  | 
| 444 |  |  |  |  |  |  | =cut | 
| 445 |  |  |  |  |  |  |  | 
| 446 |  |  |  |  |  |  | =item * ($newoff,@dnptrs)=$put->XYZ(\$buffer,$offset,\@dnptrs, | 
| 447 |  |  |  |  |  |  | $name,$type,$class,$ttl,$rdata,...); | 
| 448 |  |  |  |  |  |  |  | 
| 449 |  |  |  |  |  |  |  | 
| 450 |  |  |  |  |  |  | Append a resource record of type XYZ to the current buffer. This is the | 
| 451 |  |  |  |  |  |  | generic form of a B. | 
| 452 |  |  |  |  |  |  |  | 
| 453 |  |  |  |  |  |  | input:	pointer to buffer, | 
| 454 |  |  |  |  |  |  | offset,	[should be end of buffer] | 
| 455 |  |  |  |  |  |  | pointer to compressed name array, | 
| 456 |  |  |  |  |  |  | (items common to all RR's) | 
| 457 |  |  |  |  |  |  | i.e.	$name,$type,$class,$ttl, | 
| 458 |  |  |  |  |  |  | $rdata,.... for this RR | 
| 459 |  |  |  |  |  |  | in binary form if appropriate | 
| 460 |  |  |  |  |  |  |  | 
| 461 |  |  |  |  |  |  | returns:	offset to end of RR, | 
| 462 |  |  |  |  |  |  | new pointer array, | 
| 463 |  |  |  |  |  |  | or	empty list if the RR type is | 
| 464 |  |  |  |  |  |  | unsupported | 
| 465 |  |  |  |  |  |  |  | 
| 466 |  |  |  |  |  |  | See: note above about writing new RR's | 
| 467 |  |  |  |  |  |  |  | 
| 468 |  |  |  |  |  |  | UN-IMPLEMENTED methods: $put->[unimplemented] fails miserably with a DIE | 
| 469 |  |  |  |  |  |  | statement identifying the offending method. | 
| 470 |  |  |  |  |  |  |  | 
| 471 |  |  |  |  |  |  | =cut | 
| 472 |  |  |  |  |  |  |  | 
| 473 |  |  |  |  |  |  | =item * (@COMMON,$RDATA) = $parse->XYZ(@common,$rdata,...); | 
| 474 |  |  |  |  |  |  |  | 
| 475 |  |  |  |  |  |  | Convert non-printable and numeric data common to all records and the RR | 
| 476 |  |  |  |  |  |  | specific B into ascii text. In many cases this is a null | 
| 477 |  |  |  |  |  |  | operation. i.e. for a TXT record. However, for a RR of type B, the | 
| 478 |  |  |  |  |  |  | operation would be as follows: | 
| 479 |  |  |  |  |  |  |  | 
| 480 |  |  |  |  |  |  | EXAMPLE | 
| 481 |  |  |  |  |  |  | Common: | 
| 482 |  |  |  |  |  |  |  | 
| 483 |  |  |  |  |  |  | name       is already text. | 
| 484 |  |  |  |  |  |  | type       numeric to text | 
| 485 |  |  |  |  |  |  | class      numeric to text | 
| 486 |  |  |  |  |  |  | ttl        numeric to text | 
| 487 |  |  |  |  |  |  | rdlength   is a number | 
| 488 |  |  |  |  |  |  | rdata      RR specific conversion | 
| 489 |  |  |  |  |  |  |  | 
| 490 |  |  |  |  |  |  | Resource Record B returns $rdata containing a packed IPv4 network | 
| 491 |  |  |  |  |  |  | address. The parse operation would be: | 
| 492 |  |  |  |  |  |  |  | 
| 493 |  |  |  |  |  |  | input: | 
| 494 |  |  |  |  |  |  |  | 
| 495 |  |  |  |  |  |  | name       foo.bar.com | 
| 496 |  |  |  |  |  |  | type       1 | 
| 497 |  |  |  |  |  |  | class      1 | 
| 498 |  |  |  |  |  |  | ttl        123 | 
| 499 |  |  |  |  |  |  | rdlength   4 | 
| 500 |  |  |  |  |  |  | rdata      a packed IPv4 address | 
| 501 |  |  |  |  |  |  |  | 
| 502 |  |  |  |  |  |  | output: | 
| 503 |  |  |  |  |  |  |  | 
| 504 |  |  |  |  |  |  | name       foo.bar.com | 
| 505 |  |  |  |  |  |  | type       T_A | 
| 506 |  |  |  |  |  |  | class      C_IN | 
| 507 |  |  |  |  |  |  | ttl        123 # 2m 3s | 
| 508 |  |  |  |  |  |  | rdlength   4 | 
| 509 |  |  |  |  |  |  | rdata      192.168.20.40 | 
| 510 |  |  |  |  |  |  |  | 
| 511 |  |  |  |  |  |  | The rdata conversion is implemented internally as: | 
| 512 |  |  |  |  |  |  |  | 
| 513 |  |  |  |  |  |  | $dotquad = inet_ntoa($networkaddress); | 
| 514 |  |  |  |  |  |  |  | 
| 515 |  |  |  |  |  |  | where $dotquad is a printable IP address like | 
| 516 |  |  |  |  |  |  | 192.168.20.55 | 
| 517 |  |  |  |  |  |  |  | 
| 518 |  |  |  |  |  |  | UN-IMPLEMENTED methods: $parse->[unimplemented] returns correct @common | 
| 519 |  |  |  |  |  |  | elements insofar as the type and class are present in Net::DNS::Codes. | 
| 520 |  |  |  |  |  |  | Other elements are passed through unchanged. i.e. garbage-in, garbage-out. | 
| 521 |  |  |  |  |  |  |  | 
| 522 |  |  |  |  |  |  | =item * ($newoff,$name,type,class) = | 
| 523 |  |  |  |  |  |  | $get->Question(\$buffer,$offset); | 
| 524 |  |  |  |  |  |  |  | 
| 525 |  |  |  |  |  |  | Get the Question. | 
| 526 |  |  |  |  |  |  |  | 
| 527 |  |  |  |  |  |  | input:	pointer to buffer, | 
| 528 |  |  |  |  |  |  | offset | 
| 529 |  |  |  |  |  |  | returns:	domain name, | 
| 530 |  |  |  |  |  |  | question type, | 
| 531 |  |  |  |  |  |  | question class | 
| 532 |  |  |  |  |  |  |  | 
| 533 |  |  |  |  |  |  | =item * ($newoff,@dnptrs) = | 
| 534 |  |  |  |  |  |  | $put->Question(\$buffer,$offset, | 
| 535 |  |  |  |  |  |  | $name,$type,$class,\@dnptrs); | 
| 536 |  |  |  |  |  |  |  | 
| 537 |  |  |  |  |  |  | Append a question to the $buffer. Returns a new pointer array for compressed | 
| 538 |  |  |  |  |  |  | names and the offset to the next RR. | 
| 539 |  |  |  |  |  |  |  | 
| 540 |  |  |  |  |  |  | NOTE: it is up to the user to update the question count. See: L | 
| 541 |  |  |  |  |  |  |  | 
| 542 |  |  |  |  |  |  | Since the B usually is the first record to be appended to the | 
| 543 |  |  |  |  |  |  | buffer, @dnptrs may be ommitted. See the details at L. | 
| 544 |  |  |  |  |  |  |  | 
| 545 |  |  |  |  |  |  | Usage: ($newoff,@dnptrs)=$put->Question(\$buffer,$offset, | 
| 546 |  |  |  |  |  |  | $name,$type,$class); | 
| 547 |  |  |  |  |  |  |  | 
| 548 |  |  |  |  |  |  | input:	pointer to buffer, | 
| 549 |  |  |  |  |  |  | offset into buffer, | 
| 550 |  |  |  |  |  |  | domain name, | 
| 551 |  |  |  |  |  |  | question type, | 
| 552 |  |  |  |  |  |  | question class, | 
| 553 |  |  |  |  |  |  | pointer to array of | 
| 554 |  |  |  |  |  |  | previously compressed names, | 
| 555 |  |  |  |  |  |  | returns:	offset to next record, | 
| 556 |  |  |  |  |  |  | updated array of offsets to | 
| 557 |  |  |  |  |  |  | previous compressed names | 
| 558 |  |  |  |  |  |  |  | 
| 559 |  |  |  |  |  |  | =item * ($name,$typeTXT,$classTXT) = | 
| 560 |  |  |  |  |  |  | $parse->Question($name,$type,$class); | 
| 561 |  |  |  |  |  |  |  | 
| 562 |  |  |  |  |  |  | Convert non-printable and numeric data | 
| 563 |  |  |  |  |  |  | into ascii text. | 
| 564 |  |  |  |  |  |  |  | 
| 565 |  |  |  |  |  |  | input:	domain name, | 
| 566 |  |  |  |  |  |  | question type (numeric) | 
| 567 |  |  |  |  |  |  | question class (numeric) | 
| 568 |  |  |  |  |  |  | returns:	domain name, | 
| 569 |  |  |  |  |  |  | type TEXT, | 
| 570 |  |  |  |  |  |  | class TEXT | 
| 571 |  |  |  |  |  |  |  | 
| 572 |  |  |  |  |  |  | =back | 
| 573 |  |  |  |  |  |  |  | 
| 574 |  |  |  |  |  |  | =cut | 
| 575 |  |  |  |  |  |  |  | 
| 576 |  |  |  |  |  |  | 1; | 
| 577 |  |  |  |  |  |  | __END__ |