line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package Net::DNSServer; |
2
|
|
|
|
|
|
|
|
3
|
2
|
|
|
2
|
|
146878
|
use strict; |
|
2
|
|
|
|
|
5
|
|
|
2
|
|
|
|
|
71
|
|
4
|
2
|
|
|
2
|
|
10
|
use Exporter; |
|
2
|
|
|
|
|
4
|
|
|
2
|
|
|
|
|
66
|
|
5
|
2
|
|
|
2
|
|
37129
|
use Net::DNS; |
|
2
|
|
|
|
|
1079269
|
|
|
2
|
|
|
|
|
335
|
|
6
|
2
|
|
|
2
|
|
2244
|
use Net::Server::MultiType; |
|
2
|
|
|
|
|
192114
|
|
|
2
|
|
|
|
|
73
|
|
7
|
2
|
|
|
2
|
|
7119
|
use Getopt::Long qw(GetOptions); |
|
2
|
|
|
|
|
44776
|
|
|
2
|
|
|
|
|
15
|
|
8
|
2
|
|
|
2
|
|
2726
|
use Carp qw(croak); |
|
2
|
|
|
|
|
5
|
|
|
2
|
|
|
|
|
159
|
|
9
|
2
|
|
|
2
|
|
11
|
use vars qw(@ISA $VERSION); |
|
2
|
|
|
|
|
4
|
|
|
2
|
|
|
|
|
3727
|
|
10
|
|
|
|
|
|
|
@ISA = qw(Exporter Net::Server::MultiType); |
11
|
|
|
|
|
|
|
|
12
|
|
|
|
|
|
|
$VERSION = '0.11'; |
13
|
|
|
|
|
|
|
|
14
|
|
|
|
|
|
|
sub run { |
15
|
0
|
|
|
0
|
1
|
|
my $class = shift; |
16
|
0
|
|
0
|
|
|
|
$class = ref $class || $class; |
17
|
0
|
|
|
|
|
|
my $prop = shift; |
18
|
0
|
0
|
0
|
|
|
|
unless ($prop && |
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
19
|
|
|
|
|
|
|
(ref $prop) && |
20
|
|
|
|
|
|
|
(ref $prop eq "HASH") && |
21
|
|
|
|
|
|
|
($prop->{priority}) && |
22
|
|
|
|
|
|
|
(ref $prop->{priority} eq "ARRAY")) { |
23
|
0
|
|
|
|
|
|
croak "Usage> $class->run({priority => \\\@resolvers})"; |
24
|
|
|
|
|
|
|
} |
25
|
0
|
|
|
|
|
|
foreach (@{ $prop->{priority} }) { |
|
0
|
|
|
|
|
|
|
26
|
0
|
|
|
|
|
|
my $type = ref $_; |
27
|
0
|
0
|
|
|
|
|
if (!$type) { |
|
|
0
|
|
|
|
|
|
28
|
0
|
|
|
|
|
|
croak "Not a Net::DNSServer::Base object [$_]"; |
29
|
|
|
|
|
|
|
} elsif (!$_->isa('Net::DNSServer::Base')) { |
30
|
0
|
|
|
|
|
|
croak "Resolver object must isa Net::DNSServer::Base (Type [$type] is not?)"; |
31
|
|
|
|
|
|
|
} |
32
|
|
|
|
|
|
|
} |
33
|
0
|
|
|
|
|
|
my $self = bless $prop, $class; |
34
|
|
|
|
|
|
|
|
35
|
0
|
|
0
|
|
|
|
$self->{server}->{commandline} ||= [ $0, @ARGV ]; |
36
|
|
|
|
|
|
|
# Fix up process title on a "ps" |
37
|
0
|
|
|
|
|
|
$0 = join(" ",$0,@ARGV); |
38
|
|
|
|
|
|
|
|
39
|
0
|
|
|
|
|
|
my ($help,$conf_file,$nodaemon,$user,$group,$server_port,$pidfile); |
40
|
0
|
0
|
|
|
|
|
GetOptions # arguments compatible with bind8 |
41
|
|
|
|
|
|
|
("help" => \$help, |
42
|
|
|
|
|
|
|
"config-file|boot-file=s" => \$conf_file, |
43
|
|
|
|
|
|
|
"foreground" => \$nodaemon, |
44
|
|
|
|
|
|
|
"user=s" => \$user, |
45
|
|
|
|
|
|
|
"group=s" => \$group, |
46
|
|
|
|
|
|
|
"port=s" => \$server_port, |
47
|
|
|
|
|
|
|
"Pidfile=s" => \$pidfile, |
48
|
|
|
|
|
|
|
) or $self -> help(); |
49
|
0
|
0
|
|
|
|
|
$self -> help() if $help; |
50
|
|
|
|
|
|
|
|
51
|
|
|
|
|
|
|
# Load general configuration settings |
52
|
0
|
|
0
|
|
|
|
$conf_file ||= "/etc/named.conf"; |
53
|
|
|
|
|
|
|
### XXX - FIXME: not working yet... |
54
|
|
|
|
|
|
|
# $self -> load_configuration($conf_file); |
55
|
|
|
|
|
|
|
|
56
|
|
|
|
|
|
|
# Daemonize into the background |
57
|
0
|
0
|
|
|
|
|
$self -> {server} -> {setsid} = 1 unless $nodaemon; |
58
|
|
|
|
|
|
|
|
59
|
|
|
|
|
|
|
# Effective uid |
60
|
0
|
0
|
|
|
|
|
$self -> {server} -> {user} = $user if defined $user; |
61
|
|
|
|
|
|
|
|
62
|
|
|
|
|
|
|
# Effective gid |
63
|
0
|
0
|
|
|
|
|
$self -> {server} -> {group} = $group if defined $group; |
64
|
|
|
|
|
|
|
|
65
|
|
|
|
|
|
|
# Which port to bind |
66
|
0
|
|
0
|
|
|
|
$server_port ||= getservbyname("domain", "udp") || 53; |
|
|
|
0
|
|
|
|
|
67
|
0
|
|
|
|
|
|
$self -> {server} -> {port} = ["$server_port/tcp", "$server_port/udp"]; |
68
|
|
|
|
|
|
|
|
69
|
|
|
|
|
|
|
# Where to store process ID for parent process |
70
|
0
|
|
0
|
|
|
|
$self -> {server} -> {pid_file} ||= $pidfile || "/tmp/named.pid"; |
|
|
|
0
|
|
|
|
|
71
|
|
|
|
|
|
|
|
72
|
|
|
|
|
|
|
# Listen queue length |
73
|
0
|
|
0
|
|
|
|
$self -> {server} -> {listen} ||= 12; |
74
|
|
|
|
|
|
|
|
75
|
|
|
|
|
|
|
# Default IP to bind to |
76
|
0
|
|
0
|
|
|
|
$self -> {server} -> {host} ||= "0.0.0.0"; |
77
|
|
|
|
|
|
|
|
78
|
|
|
|
|
|
|
# Show warnings until configuration has been initialized |
79
|
0
|
|
0
|
|
|
|
$self -> {server} -> {log_level} ||= 1; |
80
|
|
|
|
|
|
|
|
81
|
|
|
|
|
|
|
# Where to send errors |
82
|
0
|
|
0
|
|
|
|
$self -> {server} -> {log_file} ||= "/tmp/rob-named.error_log"; |
83
|
|
|
|
|
|
|
|
84
|
0
|
|
|
|
|
|
return $self->SUPER::run(@_); |
85
|
|
|
|
|
|
|
} |
86
|
|
|
|
|
|
|
|
87
|
|
|
|
|
|
|
sub help { |
88
|
0
|
|
|
0
|
0
|
|
my ($p)=$0=~m%([^/]+)$%; |
89
|
0
|
|
|
|
|
|
print "Usage> $p [ -u ] [ -f ] [ -(b|c) config_file ] [ -p port# ] [ -P pidfile ]\n"; |
90
|
0
|
|
|
|
|
|
exit 1; |
91
|
|
|
|
|
|
|
} |
92
|
|
|
|
|
|
|
|
93
|
|
|
|
|
|
|
sub post_configure_hook { |
94
|
0
|
|
|
0
|
1
|
|
my $self = shift; |
95
|
0
|
|
|
|
|
|
open (STDERR, ">>$self->{server}->{log_file}"); |
96
|
0
|
|
|
|
|
|
local $_; |
97
|
0
|
|
|
|
|
|
foreach (@{$self -> {priority}}) { |
|
0
|
|
|
|
|
|
|
98
|
0
|
|
|
|
|
|
$_->init($self); |
99
|
|
|
|
|
|
|
} |
100
|
|
|
|
|
|
|
} |
101
|
|
|
|
|
|
|
|
102
|
|
|
|
|
|
|
sub pre_server_close_hook { |
103
|
0
|
|
|
0
|
1
|
|
my $self = shift; |
104
|
0
|
|
|
|
|
|
local $_; |
105
|
|
|
|
|
|
|
# Call cleanup() routines |
106
|
0
|
|
|
|
|
|
foreach (@{$self -> {priority}}) { |
|
0
|
|
|
|
|
|
|
107
|
0
|
|
|
|
|
|
$_->cleanup($self); |
108
|
|
|
|
|
|
|
} |
109
|
|
|
|
|
|
|
} |
110
|
|
|
|
|
|
|
|
111
|
|
|
|
|
|
|
sub restart_close_hook { |
112
|
0
|
|
|
0
|
1
|
|
my $self = shift; |
113
|
0
|
|
|
|
|
|
local $_; |
114
|
|
|
|
|
|
|
# Call cleanup() routines |
115
|
0
|
|
|
|
|
|
foreach (@{$self -> {priority}}) { |
|
0
|
|
|
|
|
|
|
116
|
0
|
|
|
|
|
|
$_->cleanup($self); |
117
|
|
|
|
|
|
|
} |
118
|
|
|
|
|
|
|
# Make sure everything is taint clean ready before exec |
119
|
0
|
|
|
|
|
|
foreach (@{ $self->{server}->{commandline} }) { |
|
0
|
|
|
|
|
|
|
120
|
|
|
|
|
|
|
# Taintify commandline |
121
|
0
|
0
|
|
|
|
|
$_ = $1 if /^(.*)$/; |
122
|
|
|
|
|
|
|
} |
123
|
0
|
|
|
|
|
|
foreach (keys %ENV) { |
124
|
|
|
|
|
|
|
# Taintify %ENV |
125
|
0
|
0
|
|
|
|
|
$ENV{$_} = $1 if $ENV{$_} =~ /^(.*)$/; |
126
|
|
|
|
|
|
|
} |
127
|
|
|
|
|
|
|
} |
128
|
|
|
|
|
|
|
|
129
|
|
|
|
|
|
|
sub process_request { |
130
|
0
|
|
|
0
|
1
|
|
my $self = shift; |
131
|
0
|
|
|
|
|
|
my $peeraddr = $self -> {server} -> {peeraddr}; |
132
|
0
|
|
|
|
|
|
my $peerport = $self -> {server} -> {peerport}; |
133
|
0
|
|
|
|
|
|
my $sockaddr = $self -> {server} -> {sockaddr}; |
134
|
0
|
|
|
|
|
|
my $sockport = $self -> {server} -> {sockport}; |
135
|
0
|
0
|
|
|
|
|
my $proto = $self -> {server} -> {udp_true} ? "udp" : "tcp"; |
136
|
0
|
|
|
|
|
|
print STDERR "DEBUG: process_request from [$peeraddr:$peerport] for [$sockaddr:$sockport] on [$proto] ...\n"; |
137
|
0
|
|
|
|
|
|
local $0 = "named: $peeraddr:$peerport"; |
138
|
0
|
0
|
|
|
|
|
if( $self -> {server} -> {udp_true} ){ |
139
|
0
|
|
|
|
|
|
print STDERR "DEBUG: udp packet received!\n"; |
140
|
0
|
|
|
|
|
|
my $dns_packet = new Net::DNS::Packet (\$self -> {server} -> {udp_data}); |
141
|
0
|
|
|
|
|
|
print STDERR "DEBUG: Question Packet:\n",$dns_packet->string; |
142
|
|
|
|
|
|
|
# Call pre() routine for each module |
143
|
0
|
|
|
|
|
|
foreach (@{$self -> {priority}}) { |
|
0
|
|
|
|
|
|
|
144
|
0
|
|
|
|
|
|
$_->pre($dns_packet); |
145
|
|
|
|
|
|
|
} |
146
|
|
|
|
|
|
|
|
147
|
|
|
|
|
|
|
# Keep calling resolve() routine until one module resolves it |
148
|
0
|
|
|
|
|
|
my $answer_packet = undef; |
149
|
0
|
|
|
|
|
|
print STDERR "DEBUG: Preparing for resolvers...\n"; |
150
|
0
|
|
|
|
|
|
foreach (@{$self -> {priority}}) { |
|
0
|
|
|
|
|
|
|
151
|
0
|
|
|
|
|
|
print STDERR "DEBUG: Executing ",(ref $_),"->resolve() ...\n"; |
152
|
0
|
|
|
|
|
|
$answer_packet = $_->resolve(); |
153
|
0
|
0
|
|
|
|
|
last if $answer_packet; |
154
|
|
|
|
|
|
|
} |
155
|
|
|
|
|
|
|
# For DEBUGGING purposes, use the question as the answer |
156
|
|
|
|
|
|
|
# if no module could figure out the real answer (echo) |
157
|
0
|
|
0
|
|
|
|
$self -> {answer_packet} = $answer_packet || $dns_packet; |
158
|
|
|
|
|
|
|
|
159
|
0
|
|
|
|
|
|
print STDERR "DEBUG: Answer Packet After Resolve:\n",$self->{answer_packet}->string; |
160
|
|
|
|
|
|
|
|
161
|
|
|
|
|
|
|
# Before the answer is sent to the client |
162
|
|
|
|
|
|
|
# Run it through the post() routine for each module |
163
|
0
|
|
|
|
|
|
foreach (@{$self -> {priority}}) { |
|
0
|
|
|
|
|
|
|
164
|
0
|
|
|
|
|
|
$_->post( $self -> {answer_packet} ); |
165
|
|
|
|
|
|
|
} |
166
|
|
|
|
|
|
|
|
167
|
|
|
|
|
|
|
# Send the answer back to the client |
168
|
0
|
|
|
|
|
|
print STDERR "DEBUG: Answer Packet After Post:\n",$self->{answer_packet}->string; |
169
|
0
|
|
|
|
|
|
$self -> {server} -> {client} -> send($self->{answer_packet}->data); |
170
|
|
|
|
|
|
|
} else { |
171
|
0
|
|
|
|
|
|
print STDERR "DEBUG: Incoming TCP packet? Not implemented\n"; |
172
|
|
|
|
|
|
|
} |
173
|
|
|
|
|
|
|
} |
174
|
|
|
|
|
|
|
|
175
|
|
|
|
|
|
|
|
176
|
|
|
|
|
|
|
1; |
177
|
|
|
|
|
|
|
__END__ |