| 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__ |