1NAME
2 Net::DNS::ToolKit - tools for working with DNS packets
3
4SYNOPSIS
5 use Net::DNS::ToolKit qw(
6
7 get1char
8 get16
9 get32
10 put1char
11 put16
12 put32
13 getIPv4
14 putIPv4
15 putIPv6
16 getIPv6
17 getstring
18 putstring
19 dn_comp
20 dn_expand
21 parse_char
22 gethead
23 newhead
24 getflags
25 putflags
26 get_qdcount
27 get_ancount
28 get_nscount
29 get_arcount
30 put_qdcount
31 put_ancount
32 put_nscount
33 put_arcount
34 inet_aton
35 inet_ntoa
36 ipv6_aton
37 ipv6_n2x
38 ipv6_n2d
39 sec2time
40 ttlAlpha2Num
41 collapse
42 strip
43 get_ns
44 gettimeofday
45 );
46
47 $char = get1char(\$buffer,$offset);
48 ($int, $newoff) = get16(\$buffer,$offset);
49 ($long, $newoff) = get32(\$buffer,$offset);
50 $newoff = put1char(\$buffer,$offset,$u_char);
51 $newoff = put16(\$buffer,$offset,$int);
52 $newoff = put32(\$buffer,$offset,$long);
53 $flags = getflags(\$buffer);
54 true = putflags(\$buffer,$flags);
55 $int = get_qdcount(\$buffer);
56 $int = get_ancount(\$buffer);
57 $int = get_nscount(\$buffer);
58 $int = get_arcount(\$buffer);
59 $newoff = put_qdcount(\$buffer,$int);
60 $newoff = put_ancount(\$buffer,$int);
61 $newoff = put_nscount(\$buffer,$int);
62 $newoff = put_arcount(\$buffer,$int);
63 ($netaddr,$newoff)=getIPv4(\$buffer,$offset);
64 $newoff = putIPv4(\$buffer,$offset,$netaddr);
65 ($ipv6addr,$newoff)=getIPv6(\$buffer,$offset);
66 $newoff = putIPv6(\$buffer,$offset,$ipv6addr);
67 ($offset,
68 $id,$qr,$opcode,$aa,$tc,$rd,$ra,$mbz,$ad,$cd,$rcode,
69 $qdcount,$ancount,$nscount,$arcount)
70 = gethead(\$buffer);
71 $newoff = newhead(\$buffer,$id,$flags,
72 $qdcount,$ancount,$nscount,$arcount);
73 ($b,$h,$d,$a)=parse_char($char);
74 ($newoff,$name) = dn_expand(\$buffer,$offset);
75 ($newoff,@dnptrs)=dn_comp(\$buffer,$offset,\$name,\@dnptrs);
76 $dotquad = inet_ntoa($netaddr);
77 $netaddr = inet_aton($dotquad);
78 $ipv6addr = ipv6_aton($ipv6_text);
79 $hex_text = ipv6_n2x($ipv6addr);
80 $dec_text = ipv6_n2d($ipv6addr);
81 $timetxt = sec2time($seconds);
82 $seconds = ttlAlpha2Num($timetext);
83 $shorthost = collapse($zonename,$longhost);
84 $tag = strip($P_tag);
85 @nameservers = get_ns();
86 ($secs,$usecs) = gettimeofday();
87
88DESCRIPTION
89 Routines to pick apart, examine and put together DNS packets. They can
90 be used for diagnostic purposes or as building blocks for DNS
91 applications such as DNS servers and clients or to allow user
92 applications to interact directly with remote DNS servers.
93
94 See: Net::DNS::ToolKit:RR and the subdirectory
95 lib/Net/DNS/ToolKit/RR/
96 for individual Resource Record methods.
97
98 Net::DNS::ToolKit does not handle every type of RR with context
99 help for the record format. HOWEVER, it does handle all unknown
100 record types per RFC-3597 so if your program can manipulate the
101 binary and/or hex representation of the data as proscribed in RFC-3597 this
102 module will always work for you.
103
104 A good example of full utilization of this module is the Net::DNS::Dig
105 manpage/module.
106
107 See: the Net::DNS::ToolKit::RR manpage (included in this distribution)
108 for a complete description of how to use this module and the
109 accompanying Resource Records tools.
110
111FUNCTIONS
112 These functions return a value and offset in list context and first
113 value only in scalar context.
114
115 ($int,$newoff) = get16(...
116 ($long,$newoff) = get32(...
117 ($netaddr,$newoff) = getIPv4(...
118 ($ipv6addr,$newoff) = getIPv6(...
119 ($string,$newoff) = getstring(...
120 ($newoff,$name) = dn_expand(...
121 ($secs,$usecs) = gettimeofday(...
122
123 These functions return only a value or an offset.
124
125 $newoff = put1char(...
126 $newoff = put16(...
127 $newoff = put32(...
128 $newoff = put_qdcount(...
129 $newoff = put_ancount(...
130 $newoff = put_nscount(...
131 $newoff = put_arcount(...
132 $newoff = putIPv4(...
133 $newoff = putIPv4(...
134 $newoff = putstring(...
135 $newoff = newhead(...
136 $flags = getflags(...
137 true = putflags(...
138 $int = get_qdcount(...
139 $int = get_ancount(...
140 $int = get_nscount(...
141 $int = get_arcount(...
142 $char = get1char(...
143 $dotquad = inet_ntoa(...
144 $netaddr = inet_aton(...
145 $timetxt = sec2time(...
146 $seconds = ttlAlpha2Num(...
147 $tag = strip(...
148 $shorthost = collapse(...
149
150 This function always return list context prefixed by a new offset.
151
152 ($newoff,@dnptrs) = dn_comp(...
153 ($offset,@list) = gethead(...
154
155 These functions always return list context.
156
157 @list = parse_char(...
158 @nameservers = get_ns(...
159
160 * $char = get1char(\$buffer,$offset);
161 Get a single character from the buffer at $offset
162
163 input: pointer to buffer,
164 offset into buffer
165 output: the "character"
166 or undef if the pointer
167 is outside the buffer
168
169 * ($int, $newoff) = get16(\$buffer,$offset);
170 Get a 16 bit integer from the buffer at $offset. Return the value
171 and a new offset pointing at the next character.
172
173 Returns and empty array on error.
174
175 input: pointer to buffer,
176 offset into buffer
177 returns: 16 bit integer,
178 offset + size of int
179
180 In SCALAR context, returns just the value.
181
182 * $newoff = put1char(\$buffer,$offset,$u_char);
183 Put an unsigned 8 bit value into the buffer at $offset. Return the
184 value of the new offset pointer to the next char (usually end of
185 buffer).
186
187 * $newoff = put16(\$buffer,$offset,$int);
188 Put a 16 bit integer into the buffer at $offset. Return the value of
189 the new offset pointer to the the next char (usually end of buffer).
190
191 input: pointer to buffer,
192 offset into buffer,
193 16 bit integer
194 returns: offset + size of int
195
196 * ($long, $newoff) = get32(\$buffer,$offset);
197 Get a 32 bit long from the buffer at $offset. Return the long and a
198 new offset pointing at the next character.
199
200 Returns and empty array on error.
201
202 input: pointer to buffer,
203 offset into buffer
204 returns: 32 bit long,
205 offset + size long
206
207 In SCALAR context, returns just the value.
208
209 * $newoff = put32(\$buffer,$offset,$long);
210 Put a 32 bit long into the buffer at $offset. Return the value of
211 the new offset pointer to the the next char (usually end of buffer).
212
213 input: pointer to buffer,
214 offset into buffer,
215 32 bit long
216 returns: offset + size of int
217
218 * $flags = getflags(\$buffer);
219 Get the flag bits from the header
220
221 input: pointer to buffer,
222 returns: flag bits
223
224 * putflags(\$buffer,$flags);
225 Put flags bits back in header
226
227 input: pointer to buffer,
228 flags bits
229 returns: n/a
230
231 * $int = get_qdcount(\$buffer);
232 Get the contents of the qdcount.
233
234 input: pointer to buffer,
235 returns: 16 bit integer,
236
237 * $int = get_ancount(\$buffer);
238 Get the contents of the ancount.
239
240 input: pointer to buffer,
241 returns: 16 bit integer,
242
243 * $int = get_nscount(\$buffer);
244 Get the contents of the nscount.
245
246 input: pointer to buffer,
247 returns: 16 bit integer,
248
249 * $int = get_arcount(\$buffer);
250 Get the contents of the arcount.
251
252 input: pointer to buffer,
253 returns: 16 bit integer,
254
255 * $newoff = put_qdcount(\$buffer,$int);
256 Put a 16 bit integer into qdcount. Return an offset to ancount.
257
258 input: pointer to buffer,
259 16 bit integer,
260 returns: offset to ancount
261
262 * $newoff = put_ancount(\$buffer,$int);
263 Put a 16 bit integer into ancount. Return an offset to nscount.
264
265 input: pointer to buffer,
266 16 bit integer,
267 returns: offset to nscount
268
269 * $newoff = put_nscount(\$buffer,$int);
270 Put a 16 bit chunk into nscount. Return an offset to arcount.
271
272 input: pointer to buffer,
273 16 bit integer,
274 returns: offset to arcount
275
276 * $newoff = put_arcount(\$buffer,$int);
277 Put a 16 bit integer into arcount. Return an offset to answer
278 section.
279
280 input: pointer to buffer,
281 16 bit integer,
282 returns: offset to question section
283
284 * ($netaddr,$newoff)=getIPv4(\$buffer,$offset);
285 Get an IPv4 network address from the buffer at $offset. Return the
286 netaddr and a new offset pointing at the next character beyond.
287
288 Returns and empty array on error.
289
290 input: pointer to buffer,
291 offset into buffer
292 returns: netaddr,
293 offset + size of ipaddr
294
295 In SCALAR context, returns just netaddr.
296
297 * $newoff = putIPv4(\$buffer,$offset,$netaddr);
298 Put a netaddr into the buffer. Return the value of the new offset
299 pointer to the next char (usually end of buffer).
300
301 input: pointer to buffer,
302 offset into buffer,
303 packed IPv4 net address
304 returns: pointer to end of buffer
305
306 * ($ipv6addr,$newoff)=getIPv6(\$buffer,$offset);
307 Get an IPv6 network address from the buffer at $offset. Return the
308 ipv6addr and a new offset pointing at the next character beyond.
309
310 Returns and empty array on error.
311
312 input: pointer to buffer,
313 offset into buffer
314 returns: ipv6addr,
315 offset + size of ipv6addr
316
317 IN SCALAR context, returns just ipv6addr.
318
319 * $newoff = putIPv6(\$buffer,$offset,$ipv6addr);
320 Put an ipv6addr into the buffer. Return the value of the new offset
321 pointer to the next char (usually end of buffer).
322
323 input: pointer to buffer,
324 offset into buffer,
325 128 bit IPv6 net address
326 returns: pointer to end of buffer
327
328 * ($string,$newoff) = getstring(\$buffer,$offset,$length);
329 Return a string of $length from the buffer.
330
331 input: pointer to buffer,
332 offset,
333 length of string
334 returns: string,
335 new offset to end
336 off string in buffer
337
338 * $newoff = putstring(\$buffer,$offset,\$string);
339 Append a string to $buffer at $offset.
340
341 input: pointer to buffer,
342 offset into buffer,
343 pointer to string
344 returns: new offset to end of buffer
345
346 * ($offset,@headitems) = gethead(\$buffer);
347 ($offset,
348 $id,$qr,$opcode,$aa,$tc,$rd,$ra,$mbz,$ad,$cd,$rcode,
349 $qdcount,$ancount,$nscount,$arcount)
350 = gethead(\$buffer);
351
352 Get the numeric codes for header variables
353
354 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
355 -------------------------------------------------
356 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
357 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
358 | ID |
359 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
360 |QR| Opcode |AA|TC|RD|RA| Z|AD|CD| RCODE |
361 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
362 | QDCOUNT |
363 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
364 | ANCOUNT |
365 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
366 | NSCOUNT |
367 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
368 | ARCOUNT |
369 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
370
371 The length of this header is NS_HFIXEDSZ
372
373 input: pointer to message buffer
374 returns: offset to question section,
375 array of variables
376
377 * $newoff=newhead(\$buffer,
378 $id,$flags,$qdcount,$ancount,$nscount,$arcount);
379 Creat a new header and return the offset to question
380
381 input: \$buffer
382 $id,
383 $flags,
384 $qdcount,
385 $ancount,
386 $nscount,
387 $arcount
388 returns: offset to question = NS_HFIXEDSZ
389 or undefined on error
390
391 If qdcount, ancount, nscount, arcount are
392 not present, then they will be set to zero.
393
394 example dump script:
395
396 use lib qw(blib/lib blib/arch);
397 use Net::DNS::Codes qw(:all);
398 use Net::DNS::ToolKit::Debug qw(
399 print_head
400 print_buf
401 );
402 use Net::DNS::ToolKit qw(
403 get1char
404 parse_char
405 newhead
406 );
407 my $buffer = '';
408 newhead(\$buffer,
409 1234, # ID
410 QR | BITS_QUERY | RD,
411 1, # questions
412 5, # answers
413 2, # ns authority
414 3, # glue records
415 );
416
417 print_head(\$buffer);
418 print_buf(\$buffer);
419
420 Will produce the following output:
421
422 ID => 1234
423 QR => 1
424 OPCODE => QUERY
425 AA => 0
426 TC => 0
427 RD => 1
428 RA => 0
429 Z => 0
430 AD => 0
431 CD => 0
432 RCODE => NOERROR
433 QDCOUNT => 1
434 ANCOUNT => 5
435 NSCOUNT => 2
436 ARCOUNT => 3
437 0 : 0000_0100 0x04 4
438 1 : 1101_0010 0xD2 210
439 2 : 1000_0001 0x81 129
440 3 : 0000_0000 0x00 0
441 4 : 0000_0000 0x00 0
442 5 : 0000_0001 0x01 1
443 6 : 0000_0000 0x00 0
444 7 : 0000_0101 0x05 5
445 8 : 0000_0000 0x00 0
446 9 : 0000_0010 0x02 2
447 10 : 0000_0000 0x00 0
448 11 : 0000_0011 0x03 3
449
450 * ($b,$h,$d,$a) = parse_char($char);
451 return strings for the character in:
452
453 binary hex decimal ascii
454 0011_1001 0x39 57 9
455
456 as appropriate. Ascii is only
457 returned if printable.
458
459 A simple script using this routine can provide a view into a DNS
460 packet to examine the bits and byte. Very useful while writing DNS
461 client and server routines. See the example below.
462
463 * ($name,$newoff) = dn_expand(\$buffer,$offset);
464 Expands a compressed domain name into a full domain name.
465
466 input: pointer to buffer,
467 offset into buffer
468 returns: expanded name,
469 pointer to next RR
470
471 * ($newoff,@dnptrs)=dn_comp(\$buffer,$offset,\$name,\@dnptrs);
472 Compress a domain name and append it to the buffer.
473
474 input: pointer to buffer,
475 offset to insertion point,
476 (usually end of buffer)
477 pointer to name,
478 pointer to array of offsets of
479 previously compressed names,
480 returns: new offset to end of buffer,
481 updated array of offsets to
482 previous compressed names,
483
484 NOTES: 1) When the first domain name
485 is compressed, the \@dnptrs
486 array is ommited. dn_comp
487 will return an initialized
488 array that can then be used
489 for subsequent calls.
490
491 i.e. initial call
492
493 ($newoff,@dnptrs)=dn_comp(\$buffer,$offset,\$name);
494
495 2) if \@dnptrs is null, no compression takes place
496
497 * $dotquad = inet_ntoa($netaddr);
498 Convert a packed IPv4 network address to a dot-quad IP address.
499
500 input: packed network address
501 returns: IP address i.e. 10.4.12.123
502
503 Imported/Exported from NetAdder::IP::Util
504
505 * $netaddr = inet_aton($dotquad);
506 Convert a dot-quad IP address into an IPv4 packed network address.
507
508 input: IP address i.e. 192.5.16.32
509 returns: packed network address
510
511 Imported/Exported from NetAdder::IP::Util
512
513 * $ipv6addr = ipv6_aton($ipv6_text);
514 Takes an IPv6 address of the form described in rfc1884 and returns a
515 128 bit binary RDATA string.
516
517 input: ipv6 text
518 returns: 128 bit RDATA string
519
520 Imported/Exported from NetAdder::IP::Util
521
522 * $hex_text = ipv6_n2x($ipv6addr);
523 Takes an IPv6 RDATA string and returns an 8 segment IPv6 hex address
524
525 input: 128 bit RDATA string
526 returns: x:x:x:x:x:x:x:x
527
528 Imported/Exported from NetAdder::IP::Util
529
530 * $dec_text = ipv6_n2d($ipv6addr);
531 Takes an IPv6 RDATA string and returns a mixed hex - decimal IPv6
532 address with the 6 uppermost chunks in hex and the lower 32 bits in
533 dot-quad representation.
534
535 input: 128 bit RDATA string
536 returns: x:x:x:x:x:x:d.d.d.d
537
538 Imported/Exported from NetAdder::IP::Util
539
540 * $timetxt = sec2time($seconds);
541 Convert numeric seconds into a string of the form
542
543 NNw NNd NNh NNm NNs
544
545 for weeks, days, hours, minutes, seconds respectively.
546
547 input: seconds
548 returns: elapsed time text
549
550 * $seconds = ttlAlpha2Num($timetext);
551 Convert a string of time text of the form
552
553 NNw NNd NNh NNm NNs
554
555 into seconds. Upper case is OK.
556
557 input: ttl in form numeric
558 or alpha numeric
559 returns: seconds
560
561 * $shorthost = collapse($zonename,$longhost);
562 Remove the zone portion of a fully qualified domain name and return
563 the host portion.
564
565 input: zone name,
566 fqdn
567 returns: short host name
568
569 i.e. zone = bar.com
570 fqdn = foo.bar.com
571
572 foo = collapse(zone,fqdn);
573
574 Testing is not case sensitive. If the fqdn does not end in the zone
575 name then the fqdn is returned.
576
577 * $tag = strip($P_tag);
578 Remove the leading character(s) from a type/class label.
579
580 input: label # like T_MX or C_IN
581 returns: tag # MX, IN
582
583 * @nameservers = get_ns();
584 Return a list of name server addresses in packed network form for
585 use by this host.
586
587 * ($secs,$usecs) = gettimeofday();
588 Returns a time value that is accurate to the nearest microsecond but
589 also has a range of years.
590
591 input: none
592 returns: seconds since epoch,
593 microseconds (of current sec)
594
595INSTALLATION
596 To install this module, type:
597
598 perl Makefile.PL
599 make
600 make test
601 make install
602
603DEPENDENCIES
604 perl 5.00503
605 Net::DNS::Codes 0.06
606
607EXAMPLES
608 See the scripts directory in this distribution
609
610 * dig.pl
611 A script that functions like dig in the BIND distribution. It
612 provides additional functionality in that it will dump the packet
613 buffer contents for inspection in debug mode. It is easily modified
614 to add features.
615
616 Syntax:
617 dig.pl [@server] [+tcp] [-d] [-p port#] [-t type] name
618
619 server is the name or IP address of the name server to query. An IPv4
620 address can be provided in dotted-decimal notation. When the
621 supplied server argument is a hostname, dig resolves that name
622 before querying that name server.
623
624 +tcp only use TCP protocol
625
626 -d print the query to the console
627
628 -p port# is the port number that dig.pl will send its queries
629 instead of the standard DNS port number 53.
630
631 -t indicates what type of query is required. This script supports
632 only A, MX, NS, CNAME, SOA, TXT, and ANY queries as well as
633 AXFR record transfers. If no type argument is supplied, dig.pl
634 will perform a lookup for an A record
635
636 name is the name of the resource record that is to be looked up.
637
638 * rdns_blk.pl
639 A script to lookup an entire class "C" set of PTR records
640 recursively. This is useful hunting spam domains where many DNS's do
641 not allow AXFR record transfers to inspect what is in a range of IP
642 addresses.
643
644 Syntax:
645 ./rdns_blk.pl nn.nn.nn[.nn]
646
647 at least the first three groups of
648 dot.quad.addr numbers
649
650 returns PTR results for 1..255 of address range
651 skips non-existent records, notes timeouts
652
653EXPORT
654 None
655
656EXPORT_OK
657 get1char get16 get32 put1char put16 put32 getIPv4 putIPv4 getIPv6
658 putIPv6 getstring putstring dn_comp dn_expand parse_char gethead newhead
659 getflags putflags get_qdcount get_ancount get_nscount get_arcount
660 put_qdcount put_ancount put_nscount put_arcount inet_aton inet_ntoa
661 ipv6_aton ipv6_n2x ipv6_n2d sec2time ttlAlpha2Num collapse strip get_ns
662 gettimeofday
663
664BUGS
665 There have been some reports of the "C" library function for
666
667 "int res_init(void);
668
669 not properly returning the local resolver nameserver configuration
670 information for certain Perl 5.6 -> 5.8 hosts. This is for the ToolKit
671 function "get_ns()".
672
673 I have been unable to duplicate this on any of the ix86 Linux or
674 Sun-Sparc systems that I have. If you have a system that exhibits this
675 problem and can provide a user account, I'd appreciate it if you would
676 contact me so I can fix it.
677
678 Update v0.38 Thu Oct 2 14:49:26 PDT 2008 This may be an issue with
679 sharing of the __res_state structure. The update uses a private
680 __res_state structure rather than the shared one and calling
681 res_ninit(*private_res). Hopefully this will fix the problem.
682
683AUTHOR
684 Michael Robinton <michael@bizsystems.com>
685
686ACKNOWLEDGEMENTS
687 The following functions are used in whole or in part as include files to
688 ToolKit.xs. The copyrights are include in the respective files.
689
690 file: functions:
691
692 dn_expand.inc dn_expand
693
694 dn_expand is from Michael Fuhr's Net::DNS package (DNS.pm), copyright
695 (c) 1997-2002. Thank you Michael.
696
697COPYRIGHT
698 Copyright 2003 - 2014, Michael Robinton <michael@bizsystems.com>
699
700 Michael Robinton <michael@bizsystems.com>
701
702 All rights reserved.
703
704 This program is free software; you can redistribute it and/or modify it
705 under the terms of either:
706
707 a) the GNU General Public License as published by the Free
708 Software Foundation; either version 2, or (at your option) any
709 later version, or
710
711 b) the "Artistic License" which comes with this distribution.
712
713 This program is distributed in the hope that it will be useful, but
714 WITHOUT ANY WARRANTY; without even the implied warranty of
715 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See either the GNU
716 General Public License or the Artistic License for more details.
717
718 You should have received a copy of the Artistic License with this
719 distribution, in the file named "Artistic". If not, I'll be glad to
720 provide one.
721
722 You should also have received a copy of the GNU General Public License
723 along with this program in the file named "Copying". If not, write to
724 the
725
726 Free Software Foundation, Inc.
727 59 Temple Place, Suite 330
728 Boston, MA 02111-1307, USA
729
730 or visit their web page on the internet at:
731
732 http://www.gnu.org/copyleft/gpl.html.
733
734See also:
735 Net::DNS::Codes(3), Net::DNS::ToolKit::RR(3),
736 Net::DNS::ToolKit::Debug(3), Net::DNS::ToolKit::Utilities,
737 NetAdder::IP::Util
738
739