File Coverage

blib/lib/Net/DNS/ToolKit/RR/Template.pm
Criterion Covered Total %
statement 22 22 100.0
branch 2 4 50.0
condition n/a
subroutine 7 7 100.0
pod 0 3 0.0
total 31 36 86.1


line stmt bran cond sub pod time code
1             package Net::DNS::ToolKit::RR::Template;
2              
3 7     7   37 use strict;
  7         14  
  7         313  
4             #use warnings;
5              
6             # This file contains the working code for
7             # the RR_A record methods.
8             # They are not really in the A.pm file, they
9             # are imported into that namespace from here
10             # so that this example can show a functional
11             # module containing real code.
12              
13             # The functions needed for 'A' records
14             # are 'put16', 'getIPv4', putIPv4, inet_aton,
15             # and inet_ntoa. Other RR types will need
16             # different and/or additional functions.
17              
18 7         577 use Net::DNS::ToolKit qw(
19             put16
20             getIPv4
21             putIPv4
22             inet_aton
23             inet_ntoa
24 7     7   36 );
  7         63  
25 7     7   50 use Net::DNS::Codes qw(:constants);
  7         13  
  7         2254  
26 7     7   43 use vars qw($VERSION);
  7         12  
  7         2418  
27              
28             $VERSION = do { my @r = (q$Revision: 0.02 $ =~ /\d+/g); sprintf "%d."."%02d" x $#r, @r };
29              
30             =head1 NAME
31              
32             Net::DNS::ToolKit::RR::Template - template for resource records
33              
34             =head1 SYNOPSIS
35              
36             This file is a template from which to create new resource record
37             manipulation methods. While these modules may be loaded directly for
38             testing, they are intended to be loaded by the class loader
39             B. The SYNOPSIS section of specific RR documentation
40             should begin with the caveat:
41              
42             I
43              
44             DO NOT use Net::DNS::ToolKit::RR::XYZ
45             DO NOT require Net::DNS::ToolKit::RR::XYZ
46              
47             Net::DNS::ToolKit::RR::XYZ is autoloaded by
48             class Net::DNS::ToolKit::RR and its methods
49             are instantiated in a 'special' manner.
50              
51             use Net::DNS::ToolKit::RR;
52             ($get,$put,$parse) = new Net::DNS::ToolKit::RR;
53              
54             ($newoff,$name,$type,$class,$ttl,$rdlength,
55             $rdata,...) = $get->XYZ(\$buffer,$offset);
56              
57             Note: the $get->XYZ method is normally called
58             via: @stuff = $get->next(\$buffer,$offset);
59              
60             ($newoff,@dnptrs)=$put->XYZ(\$buffer,$offset,\@dnptrs,
61             $name,$type,$class,$ttl,$rdata,...);
62              
63             $NAME,$TYPE,$CLASS,$TTL,$rdlength,$RDATA)
64             = $parse->XYZ($name,$type,$class,$ttl,$rdlength,
65             $rdata,...);
66              
67             =head1 DESCRIPTION
68              
69             B appends an XYZ resource record to a DNS packet under
70             construction, recovers an XYZ resource record from a packet being decoded, and
71             converts the numeric/binary portions of the resource record to human
72             readable form.
73              
74             Description from RFC1035.txt or other specification document.
75              
76             I
77              
78             See: I and I for
79             examples.
80              
81             Each RR module contains three methods which provide the RR specific
82             content manipulation. The data common to all resource modules is handled
83             from within the class loader prior to handing the request over the the
84             specific resource record method. Because of this, the DESCRIPTION of the
85             method action is somewhat misleading. As an example, lets dissect the 'parse' method:
86              
87             $NAME,$TYPE,$CLASS,$TTL,$rdlength,$RDATA,...)
88             = $parse->XYZ($name,$type,$class,$ttl,$rdlength,
89             $rdata,...);
90              
91             The common elements for all resource records are:
92              
93             $name,$type,$class,$ttl,$rdlength
94              
95             These are handled by the class loader and the local method actually only
96             receives a request to provide the '$rdata' portion. While the description of
97             the method as called from the user program is as above, the implementation
98             looks like this for and 'A' resource record. The $rdata is handled as
99             follows:
100              
101             $IPaddr = $classloader->A($netaddr);
102              
103             sub parse {
104             shift; # $self
105             inet_ntoa($netaddr);
106             }
107              
108             As you can see, all that is passed to the 'parse' method is the $rdata
109             portion of the request. 'parse' returns the ascii 'dotquad' IP address.
110              
111             The actual DESCRIPTION from B follows with
112             annotation about the CODE and what is passed to all resource methods from
113             the class loader.
114              
115             The rest of this Template example is taken DIRECTLY from
116             B, with comments added for clarity and to show the
117             CODE.
118              
119             =over 4
120              
121             =item * @stuff = $get->A(\$buffer,$offset);
122              
123             Get the contents of the resource record.
124              
125             USE: @stuff = $get->next(\$buffer,$offset);
126              
127             where: @stuff = (
128             $newoff $name,$type,$class,$ttl,$rdlength,
129             $netaddr );
130              
131             All except the last item, B<$netaddr>, is provided by
132             the class loader, B. The code in this method knows
133             how to retrieve B<$netaddr>.
134              
135             input: pointer to buffer,
136             offset into buffer
137             returns: offset to next resource,
138             @common RR elements,
139             packed IPv4 address
140             in network order
141              
142             NOTE: convert IPv4 address to dot quad text
143             using Net::DNS::ToolKit::inet_ntoa
144              
145             ------------------------------------------
146              
147             The get function is passed a pointer to the buffer
148             and an offset within the buffer to RDATA. It is
149             expected to return the RDATA in the appropriate
150             format as provided in the relevant RFC.
151              
152             The call to 'get' from the class loader looks like this:
153              
154             $netaddr = $classloader->get(\$buffer,$offset);
155              
156             Implementation for A RR's:
157              
158             sub get {
159             my($self,$bp,$offset) = @_;
160             $offset += INT16SZ; # don't need rdlength
161             my($netaddr,$newoff) = getIPv4($bp,$offset);
162             return ($newoff,$netaddr);
163             }
164              
165             =cut
166              
167             sub get {
168 7     7 0 73 my($self,$bp,$offset) = @_;
169 7         38 $offset += INT16SZ; # don't need rdlength
170 7         144 my($netaddr,$newoff) = getIPv4($bp,$offset);
171 7         35 return ($newoff,$netaddr);
172             }
173              
174             =item * ($newoff,@dnptrs)=$put->A(\$buffer,$offset,\@dnptrs,
175             $name,$type,$class,$ttl,$netaddr);
176              
177             Append an A record to $buffer.
178              
179             where @common = (
180             $name,$type,$class,$ttl);
181              
182             The method will insert the $rdlength and $netaddr, then
183             pass through the updated pointer to the array of compressed names
184              
185             The class loader, B, inserts the @common elements and
186             returns updated @dnptrs. This module knows how to insert its RDATA and
187             calculate the $rdlength.
188              
189             input: pointer to buffer,
190             offset (normally end of buffer),
191             pointer to compressed name array,
192             @common RR elements,
193             packed IPv4 address
194             in network order
195             output: offset to next RR,
196             new compressed name pointer array,
197             or empty list () on error.
198              
199             ------------------------------------------
200              
201             The put function is passed a pointer to the buffer an offset into the buffer
202             (normally the end of buffer) and a pointer to an array of previously
203             compressed names. It is expected to append the correct RDLENGTH and
204             RDATA to the buffer and return an offset to the next RR (usually the end of
205             buffer) as well as a new array of compressed names
206             or the one to which it has a pointer if there are no names added to the
207             buffer by this RR record method.
208              
209             The call passed to 'put' by the class loader looks like this:
210              
211             $newoff = $classloader->put(\$buffer,$offset,\@dnptrs,@rdata);
212              
213             Implementation for A RR's:
214              
215             sub put {
216             return () unless @_; # always return on error
217             my($self,$bp,$off,$dnp,$netaddr) = @_;
218             return () unless
219             ($off = put16($bp,$off,NS_INADDRSZ));
220             return(putIPv4($bp,$off,$netaddr), @$dnp);
221             }
222              
223             Implementation for NS RR's: This method calculates $rdlength
224              
225             sub put {
226             return () unless @_; # always return on error
227             my($self,$bp,$off,$dnp,$nsdname) = @_;
228             my $rdlp = $off; # save pointer to rdlength
229             return () unless # check for valid offset and get
230             ($off = put16($bp,$off,0)) && # offset to name space
231             (@_ = dn_comp($bp,$off,\$nsdname,$dnp));
232             # new offset is first item in @_
233             # rdlength = new offset - previous offset
234             put16($bp,$rdlp, $_[0] - $off);
235             return @_;
236             }
237              
238             =cut
239              
240             sub put {
241 6 50   6 0 305 return () unless @_; # always return on error
242 6         14 my($self,$bp,$off,$dnp,$netaddr) = @_;
243 6 50       31 return () unless
244             ($off = put16($bp,$off,NS_INADDRSZ));
245 6         212 return(putIPv4($bp,$off,$netaddr), @$dnp);
246             }
247              
248             =item * (@COMMON,$IPaddr) = $parse->A(@common,$netaddr);
249              
250             Converts binary/numeric field data into human readable form. The common RR
251             elements are supplied by the class loader, B. This
252             module knows how to parse its RDATA.
253              
254             EXAMPLE
255             Common is: name,$type,$class,$ttl,$rdlength
256              
257             name '.' is appended
258             type numeric to text
259             class numeric to text
260             ttl numeric to text
261             rdlength is a number
262             rdata RR specific conversion
263              
264             Resource Record B returns $rdata containing a packed IPv4 network
265             address. The parse operation would be:
266              
267             input:
268              
269             name foo.bar.com
270             type 1
271             class 1
272             ttl 123
273             rdlength 4
274             rdata a packed IPv4 address
275              
276             output:
277              
278             name foo.bar.com
279             type T_A
280             class C_IN
281             ttl 2m 3s
282             rdlength 4
283             rdata 192.168.20.40
284              
285             ------------------------------------------
286              
287             The parse function is passed the RDATA for its type.
288             It expected to convert the RDATA into human readable
289             form and return it.
290              
291             $IPaddress = $classloader->parse($netaddr);
292              
293             Implementation for A RR's:
294              
295             sub parse {
296             shift; # $self
297             inet_ntoa(shift);
298             }
299              
300             NOTE: while the B record does not return domain records, it is important
301             that developers remember to append a '.' to domain names which are text
302             formatted. i.e. foo.bar.com becomes foo.bar.com. when text formatted to
303             conform the record format for DNS files.
304              
305             =back
306              
307             =cut
308              
309             sub parse {
310 6     6 0 714 shift; # $self
311 6         195 inet_ntoa(shift);
312             }
313              
314             =head1 CODE for THIS MODULE
315              
316             The code in this module (for an 'A' resource record) without the comments is
317             pretty compact and looks like this:
318              
319             package Net::DNS::ToolKit::RR::A;
320              
321             use strict;
322             use Carp;
323             # The functions needed for 'A' records
324             # are 'put16', 'getIPv4', putIPv4, inet_aton,
325             # and inet_ntoa. Other RR types will need
326             # different and/or additional functions.
327              
328             use Net::DNS::ToolKit qw(
329             put16
330             getIPv4
331             putIPv4
332             inet_aton
333             inet_ntoa
334             );
335             use Net::DNS::Codes qw(:constants);
336             use vars qw($VERSION);
337             require Socket;
338              
339             $VERSION = do { my @r = (q$Revision: 0.01 $ =~ /\d+/g); sprintf "%d."."%02d" x $#r, @r };
340              
341             =head1 NAME
342             B
343              
344             =head1 SYNOPSIS
345             (removed for brevity)
346              
347             =head1 DESCRIPTION
348             (removed for brevity)
349              
350             =over 4
351              
352             =item * @stuff = $get->A(\$buffer,$offset);
353             (removed for brevity)
354              
355             =cut
356              
357             sub get {
358             my($self,$bp,$offset) = @_;
359             $offset += INT16SZ; # don't need rdlength
360             my($netaddr,$newoff) = getIPv4($bp,$offset);
361             return ($newoff,$netaddr);
362             }
363              
364             =item * ($newoff,@dnptrs)=$put->A(\$buffer,$offset,\@dnptrs,
365             @common, $rdlength,$netaddr);
366             (removed for brevity)
367              
368             sub put {
369             return () unless @_; # always return on error
370             my($self,$bp,$off,$dnp,$netaddr) = @_;
371             return () unless
372             ($off = put16($bp,$off,NS_INADDRSZ));
373             return(putIPv4($bp,$off,$netaddr), @$dnp);
374             }
375              
376             =cut
377              
378              
379             =item * (@COMMON,$IPaddr)=$parse->A(@common,$netaddr);
380             (removed for brevity)
381              
382             =cut
383              
384             sub parse {
385             shift; # $self
386             inet_ntoa(shift);
387             }
388              
389             =head1 TEST ROUTINES
390              
391             See: t/Template.t in this distribution.
392              
393              
394             See: t/NS.t in the Net::DNS::Toolkit distribution for an example of a test
395             routine that is more complex as well as embedded debugging routines which
396             are commented out.
397              
398             And.... what follows...
399              
400             =head1 DEPENDENCIES
401              
402             Net::DNS::ToolKit
403             Net::DNS::Codes
404             any others you require
405             for your new RR extension
406              
407             =head1 EXPORT
408              
409             none
410              
411             =head1 AUTHOR
412              
413             Your Name
414              
415             =head1 COPYRIGHT
416              
417             Portions copyright 2003, Michael Robinton
418              
419             Copyright 20xx, Your Name
420            
421             This program is free software; you can redistribute it and/or modify
422             it under the terms of the GNU General Public License as published by
423             the Free Software Foundation; either version 2 of the License, or
424             (at your option) any later version.
425            
426             This program is distributed in the hope that it will be useful,
427             but WITHOUT ANY WARRANTY; without even the implied warranty of
428             MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
429             GNU General Public License for more details.
430            
431             You should have received a copy of the GNU General Public License
432             along with this program; if not, write to the Free Software
433             Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
434              
435             =head1 See also:
436              
437             Net::DNS::Codes(3), Net::DNS::ToolKit(3), Net::DNS::ToolKit::RR::A(3)
438              
439             =cut
440              
441             1;