File Coverage

blib/lib/NetPacket/IP.pm
Criterion Covered Total %
statement 286 290 98.6
branch 5 10 50.0
condition n/a
subroutine 82 83 98.8
pod 3 4 75.0
total 376 387 97.1


line stmt bran cond sub pod time code
1             package NetPacket::IP;
2             BEGIN {
3 8     8   18296 $NetPacket::IP::AUTHORITY = 'cpan:YANICK';
4             }
5             # ABSTRACT: Assemble and disassemble IP (Internet Protocol) packets.
6             $NetPacket::IP::VERSION = '1.6.0';
7 8     8   43 use strict;
  8         19  
  8         224  
8 8     8   32 use warnings;
  8         11  
  8         213  
9              
10 8     8   869 use parent 'NetPacket';
  8         960  
  8         53  
11              
12             our @EXPORT_OK = qw(ip_strip
13             IP_PROTO_IP IP_PROTO_ICMP IP_PROTO_IGMP
14             IP_PROTO_IPIP IP_PROTO_TCP IP_PROTO_EGP
15             IP_PROTO_EGP IP_PROTO_PUP IP_PROTO_UDP
16             IP_PROTO_IDP IP_PROTO_TP IP_PROTO_DCCP
17             IP_PROTO_IPV6 IP_PROTO_ROUTING IP_PROTO_FRAGMENT
18             IP_PROTO_RSVP IP_PROTO_GRE IP_PROTO_ESP
19             IP_PROTO_AH IP_PROTO_ICMPV6 IP_PROTO_NONE
20             IP_PROTO_DSTOPTS IP_PROTO_MTP IP_PROTO_ENCAP
21             IP_PROTO_PIM IP_PROTO_COMP IP_PROTO_SCTP
22             IP_PROTO_UDPLITE
23             IP_VERSION_IPv4
24             IP_FLAG_MOREFRAGS IP_FLAG_DONTFRAG IP_FLAG_CONGESTION
25             IPTOS_ECN_MASK IPTOS_ECN_NOT_ECT IPTOS_ECN_ECT1
26             IPTOS_ECN_ECT0 IPTOS_ECN_CE
27             IPTOS_DSCP_MASK IPTOS_DSCP_EF
28             IPTOS_DSCP_AF11 IPTOS_DSCP_AF12 IPTOS_DSCP_AF13
29             IPTOS_DSCP_AF21 IPTOS_DSCP_AF22 IPTOS_DSCP_AF23
30             IPTOS_DSCP_AF31 IPTOS_DSCP_AF32 IPTOS_DSCP_AF33
31             IPTOS_DSCP_AF41 IPTOS_DSCP_AF42 IPTOS_DSCP_AF43
32             IPTOS_CLASS_MASK IPTOS_CLASS_DEFAULT
33             IPTOS_CLASS_CS0 IPTOS_CLASS_CS1 IPTOS_CLASS_CS2
34             IPTOS_CLASS_CS3 IPTOS_CLASS_CS4 IPTOS_CLASS_CS5
35             IPTOS_CLASS_CS6 IPTOS_CLASS_CS7
36             IPTOS_PREC_MASK IPTOS_PREC_NETCONTROL
37             IPTOS_PREC_INTERNETCONTROL IPTOS_PREC_CRITIC_ECP
38             IPTOS_PREC_FLASHOVERRIDE IPTOS_PREC_FLASH
39             IPTOS_PREC_IMMEDIATE IPTOS_PREC_PRIORITY
40             IPTOS_PREC_ROUTINE
41             MAXTTL IPDEFTTL IPFRAGTTL IPTTLDEC IP_MSS IP_MAXPACKET
42             );
43              
44             our %EXPORT_TAGS = (
45             ALL => [@EXPORT_OK],
46             protos => [qw(IP_PROTO_IP IP_PROTO_ICMP IP_PROTO_IGMP IP_PROTO_IPIP
47             IP_PROTO_TCP IP_PROTO_EGP IP_PROTO_PUP
48             IP_PROTO_UDP IP_PROTO_IDP IP_PROTO_TP IP_PROTO_DCCP
49             IP_PROTO_IPV6 IP_PROTO_ROUTING IP_PROTO_FRAGMENT
50             IP_PROTO_RSVP IP_PROTO_GRE IP_PROTO_ESP IP_PROTO_AH
51             IP_PROTO_ICMPV6 IP_PROTO_NONE IP_PROTO_DSTOPTS
52             IP_PROTO_MTP IP_PROTO_ENCAP IP_PROTO_PIM IP_PROTO_COMP
53             IP_PROTO_SCTP IP_PROTO_UDPLITE)],
54             versions => [qw(IP_VERSION_IPv4)],
55             strip => [qw(ip_strip)],
56             flags => [qw(IP_FLAG_MOREFRAGS IP_FLAG_DONTFRAG IP_FLAG_CONGESTION)],
57             tos => [qw(IPTOS_ECN_MASK IPTOS_ECN_NOT_ECT IPTOS_ECN_ECT1
58             IPTOS_ECN_ECT0 IPTOS_ECN_CE
59             IPTOS_DSCP_MASK IPTOS_DSCP_EF
60             IPTOS_DSCP_AF11 IPTOS_DSCP_AF12 IPTOS_DSCP_AF13
61             IPTOS_DSCP_AF21 IPTOS_DSCP_AF22 IPTOS_DSCP_AF23
62             IPTOS_DSCP_AF31 IPTOS_DSCP_AF32 IPTOS_DSCP_AF33
63             IPTOS_DSCP_AF41 IPTOS_DSCP_AF42 IPTOS_DSCP_AF43
64             IPTOS_CLASS_MASK IPTOS_CLASS_DEFAULT
65             IPTOS_CLASS_CS0 IPTOS_CLASS_CS1 IPTOS_CLASS_CS2
66             IPTOS_CLASS_CS3 IPTOS_CLASS_CS4 IPTOS_CLASS_CS5
67             IPTOS_CLASS_CS6 IPTOS_CLASS_CS7
68             IPTOS_PREC_MASK IPTOS_PREC_NETCONTROL
69             IPTOS_PREC_INTERNETCONTROL IPTOS_PREC_CRITIC_ECP
70             IPTOS_PREC_FLASHOVERRIDE IPTOS_PREC_FLASH
71             IPTOS_PREC_IMMEDIATE IPTOS_PREC_PRIORITY
72             IPTOS_PREC_ROUTINE)],
73             misc => [qw(MAXTTL IPDEFTTL IPFRAGTTL IPTTLDEC IP_MSS
74             IP_MAXPACKET)],
75             );
76              
77             #
78             # Partial list of IP protocol values from RFC 1700
79             #
80              
81 8     8   1483 use constant IP_PROTO_IP => 0; # Dummy protocol for TCP
  8         13  
  8         510  
82 8     8   43 use constant IP_PROTO_ICMP => 1; # Internet Control Message Protocol
  8         8  
  8         417  
83 8     8   33 use constant IP_PROTO_IGMP => 2; # Internet Group Management Protocol
  8         10  
  8         346  
84 8     8   31 use constant IP_PROTO_IPIP => 4; # IP in IP encapsulation
  8         25  
  8         310  
85 8     8   57 use constant IP_PROTO_TCP => 6; # Transmission Control Protocol
  8         8  
  8         355  
86 8     8   38 use constant IP_PROTO_EGP => 8; # Exterior Gateway Protocol
  8         11  
  8         386  
87 8     8   43 use constant IP_PROTO_PUP => 12; # PUP protocol
  8         8  
  8         367  
88 8     8   31 use constant IP_PROTO_UDP => 17; # User Datagram Protocol
  8         12  
  8         308  
89 8     8   32 use constant IP_PROTO_IDP => 22; # XNS IDP Protocol
  8         9  
  8         309  
90 8     8   33 use constant IP_PROTO_TP => 29; # SO Transport Protocol Class 4
  8         8  
  8         296  
91 8     8   35 use constant IP_PROTO_DCCP => 33; # Datagram Congestion Control Protocol
  8         10  
  8         361  
92 8     8   508 use constant IP_PROTO_IPV6 => 41; # IPv6 header
  8         23  
  8         348  
93 8     8   35 use constant IP_PROTO_ROUTING => 43; # IPv6 routing header
  8         8  
  8         383  
94 8     8   35 use constant IP_PROTO_FRAGMENT => 44; # IPv6 fragmentation header
  8         10  
  8         379  
95 8     8   37 use constant IP_PROTO_RSVP => 46; # Reservation Protocol
  8         10  
  8         339  
96 8     8   31 use constant IP_PROTO_GRE => 47; # General Routing Encapsulation
  8         7  
  8         315  
97 8     8   31 use constant IP_PROTO_ESP => 50; # encapsulating security payload
  8         9  
  8         386  
98 8     8   31 use constant IP_PROTO_AH => 51; # authentication header
  8         9  
  8         314  
99 8     8   31 use constant IP_PROTO_ICMPV6 => 58; # ICMPv6
  8         10  
  8         317  
100 8     8   35 use constant IP_PROTO_NONE => 59; # IPv6 no next header
  8         9  
  8         325  
101 8     8   34 use constant IP_PROTO_DSTOPTS => 60; # IPv6 destination options
  8         11  
  8         329  
102 8     8   36 use constant IP_PROTO_MTP => 92; # Multicast Transport Protocol
  8         15  
  8         314  
103 8     8   38 use constant IP_PROTO_ENCAP => 98; # Encapsulation Header
  8         26  
  8         346  
104 8     8   45 use constant IP_PROTO_PIM => 103; # Protocol Independent Multicast
  8         9  
  8         336  
105 8     8   37 use constant IP_PROTO_COMP => 108; # Compression Header Protocol
  8         10  
  8         398  
106 8     8   36 use constant IP_PROTO_SCTP => 132; # Stream Control Transmission Protocol
  8         10  
  8         366  
107 8     8   37 use constant IP_PROTO_UDPLITE => 136; # UDP-Lite protocol
  8         10  
  8         339  
108              
109              
110             #
111             # Partial list of IP version numbers from RFC 1700
112             #
113              
114 8     8   30 use constant IP_VERSION_IPv4 => 4; # IP version 4
  8         10  
  8         364  
115              
116             #
117             # Flag values
118             #
119              
120 8     8   31 use constant IP_FLAG_MOREFRAGS => 1; # More fragments coming
  8         9  
  8         502  
121 8     8   42 use constant IP_FLAG_DONTFRAG => 2; # Don't fragment me
  8         8  
  8         338  
122 8     8   33 use constant IP_FLAG_CONGESTION => 4; # Congestion present
  8         11  
  8         310  
123              
124             #
125             # ToS/DSCP values
126             #
127              
128 8     8   31 use constant IPTOS_ECN_MASK => 0x03;
  8         9  
  8         330  
129 8     8   35 use constant IPTOS_ECN_NOT_ECT => 0x00;
  8         10  
  8         401  
130 8     8   34 use constant IPTOS_ECN_ECT1 => 0x01;
  8         12  
  8         325  
131 8     8   31 use constant IPTOS_ECN_ECT0 => 0x02;
  8         8  
  8         316  
132 8     8   37 use constant IPTOS_ECN_CE => 0x03;
  8         10  
  8         350  
133              
134 8     8   39 use constant IPTOS_DSCP_MASK => 0xfc;
  8         11  
  8         371  
135 8     8   38 use constant IPTOS_DSCP_AF11 => 0x28;
  8         8  
  8         331  
136 8     8   32 use constant IPTOS_DSCP_AF12 => 0x30;
  8         9  
  8         479  
137 8     8   35 use constant IPTOS_DSCP_AF13 => 0x38;
  8         9  
  8         326  
138 8     8   38 use constant IPTOS_DSCP_AF21 => 0x48;
  8         7  
  8         356  
139 8     8   46 use constant IPTOS_DSCP_AF22 => 0x50;
  8         13  
  8         320  
140 8     8   30 use constant IPTOS_DSCP_AF23 => 0x58;
  8         10  
  8         298  
141 8     8   35 use constant IPTOS_DSCP_AF31 => 0x68;
  8         12  
  8         316  
142 8     8   33 use constant IPTOS_DSCP_AF32 => 0x70;
  8         124  
  8         314  
143 8     8   35 use constant IPTOS_DSCP_AF33 => 0x78;
  8         10  
  8         295  
144 8     8   81 use constant IPTOS_DSCP_AF41 => 0x88;
  8         8  
  8         343  
145 8     8   36 use constant IPTOS_DSCP_AF42 => 0x90;
  8         8  
  8         305  
146 8     8   32 use constant IPTOS_DSCP_AF43 => 0x98;
  8         9  
  8         295  
147 8     8   30 use constant IPTOS_DSCP_EF => 0xb8;
  8         10  
  8         291  
148              
149 8     8   32 use constant IPTOS_CLASS_MASK => 0xe0;
  8         13  
  8         436  
150 8     8   32 use constant IPTOS_CLASS_CS0 => 0x00;
  8         9  
  8         332  
151 8     8   30 use constant IPTOS_CLASS_CS1 => 0x20;
  8         13  
  8         297  
152 8     8   33 use constant IPTOS_CLASS_CS2 => 0x40;
  8         9  
  8         307  
153 8     8   83 use constant IPTOS_CLASS_CS3 => 0x60;
  8         11  
  8         299  
154 8     8   32 use constant IPTOS_CLASS_CS4 => 0x80;
  8         27  
  8         331  
155 8     8   35 use constant IPTOS_CLASS_CS5 => 0xa0;
  8         14  
  8         316  
156 8     8   33 use constant IPTOS_CLASS_CS6 => 0xc0;
  8         9  
  8         357  
157 8     8   33 use constant IPTOS_CLASS_CS7 => 0xe0;
  8         12  
  8         341  
158 8     8   37 use constant IPTOS_CLASS_DEFAULT => 0x00;
  8         8  
  8         352  
159              
160 8     8   37 use constant IPTOS_PREC_MASK => 0xe0;
  8         19  
  8         302  
161 8     8   30 use constant IPTOS_PREC_NETCONTROL => 0xe0;
  8         30  
  8         279  
162 8     8   27 use constant IPTOS_PREC_INTERNETCONTROL => 0xc0;
  8         13  
  8         309  
163 8     8   35 use constant IPTOS_PREC_CRITIC_ECP => 0x0a;
  8         11  
  8         468  
164 8     8   34 use constant IPTOS_PREC_FLASHOVERRIDE => 0x80;
  8         11  
  8         376  
165 8     8   59 use constant IPTOS_PREC_FLASH => 0x60;
  8         9  
  8         352  
166 8     8   32 use constant IPTOS_PREC_IMMEDIATE => 0x40;
  8         8  
  8         317  
167 8     8   32 use constant IPTOS_PREC_PRIORITY => 0x20;
  8         12  
  8         400  
168 8     8   34 use constant IPTOS_PREC_ROUTINE => 0x00;
  8         9  
  8         293  
169              
170             # TTL values
171 8     8   37 use constant MAXTTL => 255;
  8         8  
  8         381  
172 8     8   31 use constant IPDEFTTL => 64;
  8         10  
  8         269  
173 8     8   31 use constant IPFRAGTTL => 60;
  8         9  
  8         285  
174 8     8   28 use constant IPTTLDEC => 1;
  8         10  
  8         278  
175              
176 8     8   31 use constant IP_MSS => 576;
  8         14  
  8         309  
177              
178             # Maximum IP Packet size
179 8     8   32 use constant IP_MAXPACKET => 65535;
  8         8  
  8         5497  
180              
181             # Convert 32-bit IP address to dotted quad notation
182              
183             sub to_dotquad {
184 16     16 0 21 my($net) = @_ ;
185 16         35 my($na, $nb, $nc, $nd);
186              
187 16         18 $na = $net >> 24 & 255;
188 16         23 $nb = $net >> 16 & 255;
189 16         17 $nc = $net >> 8 & 255;
190 16         17 $nd = $net & 255;
191              
192 16         61 return ("$na.$nb.$nc.$nd");
193             }
194              
195             #
196             # Decode the packet
197             #
198              
199             sub decode {
200 8     8 1 539 my $class = shift;
201 8         11 my($pkt, $parent) = @_;
202 8         17 my $self = {};
203              
204             # Class fields
205              
206 8         21 $self->{_parent} = $parent;
207 8         10 $self->{_frame} = $pkt;
208              
209             # Decode IP packet
210              
211 8 50       33 if (defined($pkt)) {
212 8         11 my $tmp;
213              
214 8         77 ($tmp, $self->{tos},$self->{len}, $self->{id}, $self->{foffset},
215             $self->{ttl}, $self->{proto}, $self->{cksum}, $self->{src_ip},
216             $self->{dest_ip}, $self->{options}) = unpack('CCnnnCCnNNa*' , $pkt);
217              
218             # Extract bit fields
219            
220 8         21 $self->{ver} = ($tmp & 0xf0) >> 4;
221 8         14 $self->{hlen} = $tmp & 0x0f;
222            
223 8         16 $self->{flags} = $self->{foffset} >> 13;
224 8         18 $self->{foffset} = ($self->{foffset} & 0x1fff) << 3;
225              
226             # Decode variable length header options and remaining data in field
227              
228 8         14 my $olen = $self->{hlen} - 5;
229 8 50       55 $olen = 0 if $olen < 0; # Check for bad hlen
230              
231             # Option length is number of 32 bit words
232              
233 8         17 $olen = $olen * 4;
234              
235 8         43 ($self->{options}, $self->{data}) = unpack("a" . $olen .
236             "a*", $self->{options});
237              
238 8         13 my $length = $self->{hlen};
239 8 50       26 $length = 5 if $length < 5; # precaution against bad header
240              
241             # truncate data to the length given by the header
242 8         25 $self->{data} = substr $self->{data}, 0, $self->{len} - 4 * $length;
243              
244             # Convert 32 bit ip addresses to dotted quad notation
245              
246 8         34 $self->{src_ip} = to_dotquad($self->{src_ip});
247 8         17 $self->{dest_ip} = to_dotquad($self->{dest_ip});
248             }
249              
250 8         30 return bless $self, $class;
251             }
252              
253             #
254             # Strip header from packet and return the data contained in it
255             #
256              
257             undef &ip_strip; # Create ip_strip alias
258             *ip_strip = \&strip;
259              
260             sub strip {
261 0     0 1 0 my ($pkt) = @_;
262              
263 0         0 my $ip_obj = NetPacket::IP->decode($pkt);
264 0         0 return $ip_obj->{data};
265             }
266              
267             #
268             # Encode a packet
269             #
270              
271             sub encode {
272              
273 1     1 1 845 my $self = shift;
274 1         2 my ($hdr,$packet,$zero,$tmp,$offset);
275 0         0 my ($src_ip, $dest_ip);
276              
277             # create a zero variable
278 1         2 $zero = 0;
279              
280             # adjust the length of the packet
281 1         4 $self->{len} = ($self->{hlen} * 4) + length($self->{data});
282              
283 1         2 $tmp = $self->{hlen} & 0x0f;
284 1         3 $tmp = $tmp | (($self->{ver} << 4) & 0xf0);
285              
286 1         2 $offset = $self->{flags} << 13;
287 1         2 $offset = $offset | (($self->{foffset} >> 3) & 0x1fff);
288              
289             # convert the src and dst ip
290 1         132 $src_ip = gethostbyname($self->{src_ip});
291 1         41 $dest_ip = gethostbyname($self->{dest_ip});
292              
293 1         3 my $fmt = 'CCnnnCCna4a4a*';
294 1         6 my @pkt = ($tmp, $self->{tos},$self->{len},
295             $self->{id}, $offset, $self->{ttl}, $self->{proto},
296             $zero, $src_ip, $dest_ip);
297             # change format and package in case of IP options
298 1 50       4 if(defined $self->{options}){
299 1         2 $fmt = 'CCnnnCCna4a4a*a*';
300 1         3 push(@pkt, $self->{options});
301             }
302              
303             # construct header to calculate the checksum
304 1         7 $hdr = pack($fmt, @pkt);
305 1         5 $self->{cksum} = NetPacket::htons(NetPacket::in_cksum($hdr));
306 1         3 $pkt[7] = $self->{cksum};
307              
308             # make the entire packet
309 1 50       3 if(defined $self->{data}){
310 1         1 push(@pkt, $self->{data});
311             }
312 1         4 $packet = pack($fmt, @pkt);
313              
314 1         5 return($packet);
315             }
316              
317             #
318             # Module initialisation
319             #
320              
321             1;
322              
323             # autoloaded methods go after the END token (&& pod) below
324              
325             =pod
326              
327             =head1 NAME
328              
329             NetPacket::IP - Assemble and disassemble IP (Internet Protocol) packets.
330              
331             =head1 VERSION
332              
333             version 1.6.0
334              
335             =head1 SYNOPSIS
336              
337             use NetPacket::IP;
338              
339             $ip_obj = NetPacket::IP->decode($raw_pkt);
340             $ip_pkt = NetPacket::IP->encode($ip_obj);
341             $ip_data = NetPacket::IP::strip($raw_pkt);
342              
343             =head1 DESCRIPTION
344              
345             C provides a set of routines for assembling and
346             disassembling packets using IP (Internet Protocol).
347              
348             =head2 Methods
349              
350             =over
351              
352             =item Cdecode([RAW PACKET])>
353              
354             Decode the raw packet data given and return an object containing
355             instance data. This method will quite happily decode garbage input.
356             It is the responsibility of the programmer to ensure valid packet data
357             is passed to this method.
358              
359             =item Cencode()>
360              
361             Return an IP packet encoded with the instance data specified. This
362             will infer the total length of the packet automatically from the
363             payload length and also adjust the checksum.
364              
365             =back
366              
367             =head2 Functions
368              
369             =over
370              
371             =item C
372              
373             Return the encapsulated data (or payload) contained in the IP
374             packet. This data is suitable to be used as input for other
375             C modules.
376              
377             This function is equivalent to creating an object using the
378             C constructor and returning the C field of that
379             object.
380              
381             =back
382              
383             =head2 Instance data
384              
385             The instance data for the C object consists of
386             the following fields.
387              
388             =over
389              
390             =item ver
391              
392             The IP version number of this packet.
393              
394             =item hlen
395              
396             The IP header length of this packet.
397              
398             =item flags
399              
400             The IP header flags for this packet.
401              
402             =item foffset
403              
404             The IP fragment offset for this packet.
405              
406             =item tos
407              
408             The type-of-service for this IP packet.
409              
410             =item len
411              
412             The length (including length of header) in bytes for this packet.
413              
414             =item id
415              
416             The identification (sequence) number for this IP packet.
417              
418             =item ttl
419              
420             The time-to-live value for this packet.
421              
422             =item proto
423              
424             The IP protocol number for this packet.
425              
426             =item cksum
427              
428             The IP checksum value for this packet.
429              
430             =item src_ip
431              
432             The source IP address for this packet in dotted-quad notation.
433              
434             =item dest_ip
435              
436             The destination IP address for this packet in dotted-quad notation.
437              
438             =item options
439              
440             Any IP options for this packet.
441              
442             =item data
443              
444             The encapsulated data (payload) for this IP packet.
445              
446             =back
447              
448             =head2 Exports
449              
450             =over
451              
452             =item default
453              
454             none
455              
456             =item exportable
457              
458             IP_PROTO_IP IP_PROTO_ICMP IP_PROTO_IGMP IP_PROTO_IPIP IP_PROTO_TCP
459             IP_PROTO_UDP IP_VERSION_IPv4
460              
461             =item tags
462              
463             The following tags group together related exportable items.
464              
465             =over
466              
467             =item C<:protos>
468              
469             IP_PROTO_IP IP_PROTO_ICMP IP_PROTO_IGMP IP_PROTO_IPIP
470             IP_PROTO_TCP IP_PROTO_UDP
471              
472             =item C<:versions>
473              
474             IP_VERSION_IPv4
475              
476             =item C<:strip>
477              
478             Import the strip function C.
479              
480             =item C<:ALL>
481              
482             All the above exportable items.
483              
484             =back
485              
486             =back
487              
488             =head1 EXAMPLE
489              
490             The following script dumps IP frames by IP address and protocol
491             to standard output.
492              
493             #!/usr/bin/perl -w
494              
495             use strict;
496             use Net::PcapUtils;
497             use NetPacket::Ethernet qw(:strip);
498             use NetPacket::IP;
499              
500             sub process_pkt {
501             my ($user, $hdr, $pkt) = @_;
502              
503             my $ip_obj = NetPacket::IP->decode(eth_strip($pkt));
504             print("$ip_obj->{src_ip}:$ip_obj->{dest_ip} $ip_obj->{proto}\n");
505             }
506              
507             Net::PcapUtils::loop(\&process_pkt, FILTER => 'ip');
508              
509             =head1 TODO
510              
511             =over
512              
513             =item IP option decoding - currently stored in binary form.
514              
515             =item Assembly of received fragments
516              
517             =back
518              
519             =head1 COPYRIGHT
520              
521             Copyright (c) 2001 Tim Potter and Stephanie Wehner.
522              
523             Copyright (c) 1995,1996,1997,1998,1999 ANU and CSIRO on behalf of
524             the participants in the CRC for Advanced Computational Systems
525             ('ACSys').
526              
527             This module is free software. You can redistribute it and/or
528             modify it under the terms of the Artistic License 2.0.
529              
530             This program is distributed in the hope that it will be useful,
531             but without any warranty; without even the implied warranty of
532             merchantability or fitness for a particular purpose.
533              
534             =head1 AUTHOR
535              
536             Tim Potter Etpot@samba.orgE
537              
538             Stephanie Wehner Eatrak@itsx.comE
539              
540             =cut
541              
542             __END__