| DNS-Oterica documentation | Contained in the DNS-Oterica distribution. |
DNS::Oterica::RecordMaker::TinyDNS - a tinydns recordmaker for DNSO.
version 0.100001
This role provides logic for generating lines for the tinydns-data program to consume.
Generate an = line, the bread and butter A and PTR record pair for a
hostname and IP.
Generate an ^ line, for the reverse DNS of an IP address.
Ricardo SIGNES <rjbs@cpan.org>
This software is copyright (c) 2011 by Ricardo SIGNES.
This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself.
| DNS-Oterica documentation | Contained in the DNS-Oterica distribution. |
use strict; use warnings; package DNS::Oterica::RecordMaker::TinyDNS; BEGIN { $DNS::Oterica::RecordMaker::TinyDNS::VERSION = '0.100001'; } # ABSTRACT: a tinydns recordmaker for DNSO. sub _default_ttl { 1800 } sub _serial_number { return($ENV{DNS_OTERICA_SN} || $^T) } sub comment { my ($self, $comment) = @_; return "# $comment\n"; } sub __ip_locode_pairs { my ($self, $rec) = @_; if ($rec->{node} and $rec->{ip} || $rec->{loc}) { Carp::confess('provide either a node or an ip/loc, not both'); } if (not $rec->{node} || $rec->{ip}) { Carp::confess('provide either a node or an ip/loc'); } # This is what we'd do to emit one record per interface to implement a split # horizon in the tinydns data file. This is probably not what we want to end # up doing. -- rjbs, 2008-12-12 # return map {; [ $_->[0] => $_->[1]->code ] } $rec->{node}->interfaces # if $rec->{node}; return map {; [ $_->[0] => $_->[1]->code ] } grep { $_->[1]->name eq 'world' } $rec->{node}->interfaces if $rec->{node}; return [ $rec->{ip}, $rec->{loc} || '' ]; } sub _generic { my ($self, $op, $rec) = @_; my @lines; for my $if ($self->__ip_locode_pairs($rec)) { push @lines, sprintf "%s%s:%s:%s:%s:%s\n", $op, $rec->{name}, $if->[0], $rec->{ttl} || $self->_default_ttl, $self->_serial_number, $if->[1], ; } return @lines; } # =fqdn:ip:ttl:timestamp:lo sub a_and_ptr { my ($self, $rec) = @_; return ( $self->_generic(q{+}, $rec), $self->ptr($rec), ); } # ^fqdn:ip:ttl:timestamp:lo # can't use __generic here because it wants to look at interfaces, and we want # the reverse of that sub ptr { my ($self, $rec) = @_; my @lines; for my $if ($self->__ip_locode_pairs($rec)) { my $ip = $if->[0]; my @bytes = reverse split /\./, $ip; splice @bytes, 1, 1, '0-24', $bytes[1]; my $extended_arpa = join '.', @bytes, 'in-addr', 'arpa'; push @lines, sprintf "^%s:%s:%s:%s:%s\n", $extended_arpa, $rec->{name}, $rec->{ttl} || $self->_default_ttl, $self->_serial_number, $if->[1]; } return @lines; } # TODO find out why we generate Z and & records for our IPs and refactor this # to not duplicate effort with &ptr and the like. problem is that &a calls &ptr # so having the code there means it gets called for every time we generate a + # record, totally not what we want. What we want is for this to be called once # for every IP address, not every hostname. sub soa_and_ns_for_ip { my ($self, $rec) = @_; my @lines; my $node = $rec->{node}; my $ns_f = $node->hub->ns_family; my %ns = $node->hub->node_family($ns_f)->ns_nodes; my $ns_1 = (keys %ns)[0]; my $addr = $node->hub->soa_rname; my $ip = $rec->{ip}; my @bytes = reverse split /\./, $ip; my $arpa = join '.', @bytes, 'in-addr', 'arpa'; push @lines, sprintf "Z%s:%s:%s::::::%s:%s:%s\n", $arpa, $ns_1, $addr, $self->_default_ttl, $self->_serial_number, '', ; for my $ns (keys %ns) { push @lines, $self->domain({ domain => $arpa, ip => $ip, ns => $ns, }); } return @lines; } # +fqdn:ip:ttl:timestamp:lo sub a { my ($self, $rec) = @_; my @lines = $self->_generic(q{+}, $rec); # if $rec->{node}->hub->location($rec->{node}->location)->delegated) { # push @lines, $self->ptr($rec); # } return @lines; } # @fqdn:ip:x:dist:ttl:timestamp:lo sub mx { my ($self, $rec) = @_; my @lines; my $mx_name = defined $rec->{mx} ? $rec->{mx} : $rec->{node} ? $rec->{node}->fqdn : Carp::confess('neither mx nor node given as mx for mx record'); for my $if ($self->__ip_locode_pairs($rec)) { push @lines, sprintf "@%s:%s:%s:%s:%s:%s:%s\n", $rec->{name}, $if->[0], $mx_name, $rec->{dist} || 10, $rec->{ttl} || $self->_default_ttl, $self->_serial_number, $if->[1], ; } return @lines; } # .fqdn:ip:x:ttl:timestamp:lo # This doesn't handle nodes, because I don't want to deal with ip-less records, # which would cause __generic to barf. This is just a hack for now. # -- rjbs, 2008-12-15 sub domain { my ($self, $rec) = @_; my @lines; push @lines, sprintf "&%s:%s:%s:%s:%s:%s\n", $rec->{domain}, $rec->{ip} || '', $rec->{ns}, $rec->{ttl} || $self->_default_ttl, $self->_serial_number, '', ; return @lines; } sub soa_and_ns { my ($self, $rec) = @_; my @lines; push @lines, sprintf "Z%s:%s:%s::::::%s:%s:%s\n", $rec->{domain}, $rec->{ns} || '', $rec->{node}->hub->soa_rname, $rec->{ttl} || $self->_default_ttl, $self->_serial_number, '', ; return @lines; } # Cfqdn:p:ttl:timestamp:lo sub cname { my ($self, $rec) = @_; my @lines; push @lines, sprintf "C%s:%s:%s:%s:%s\n", $rec->{cname}, $rec->{domain} || '', $rec->{ttl} || $self->_default_ttl, $self->_serial_number, '', ; return @lines; } sub txt { my ($self, $rec) = @_; my @lines; # 'fqdn:s:ttl:timestamp:lo push @lines, sprintf qq{'%s:%s:%s:%s:%s\n}, $rec->{node}->fqdn, $rec->{text}, $rec->{ttl} || $self->_default_ttl, $self->_serial_number, '', ; return @lines; } 1; __END__