line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
1
|
|
|
1
|
|
6681
|
use strict;
|
|
1
|
|
|
|
|
3
|
|
|
1
|
|
|
|
|
57
|
|
2
|
1
|
|
|
1
|
|
6
|
use warnings;
|
|
1
|
|
|
|
|
3
|
|
|
1
|
|
|
|
|
53
|
|
3
|
|
|
|
|
|
|
|
4
|
|
|
|
|
|
|
package Net::NBName;
|
5
|
|
|
|
|
|
|
|
6
|
1
|
|
|
1
|
|
1996
|
use Net::NBName::NodeStatus;
|
|
1
|
|
|
|
|
3
|
|
|
1
|
|
|
|
|
38
|
|
7
|
1
|
|
|
1
|
|
887
|
use Net::NBName::NameQuery;
|
|
1
|
|
|
|
|
4
|
|
|
1
|
|
|
|
|
39
|
|
8
|
|
|
|
|
|
|
|
9
|
1
|
|
|
1
|
|
7
|
use vars '$VERSION';
|
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
549
|
|
10
|
|
|
|
|
|
|
$VERSION = "0.26";
|
11
|
|
|
|
|
|
|
|
12
|
|
|
|
|
|
|
sub new
|
13
|
|
|
|
|
|
|
{
|
14
|
0
|
|
|
0
|
1
|
|
my $class = shift;
|
15
|
|
|
|
|
|
|
|
16
|
0
|
|
|
|
|
|
my $self = {};
|
17
|
0
|
|
|
|
|
|
bless $self, $class;
|
18
|
0
|
|
|
|
|
|
return $self;
|
19
|
|
|
|
|
|
|
}
|
20
|
|
|
|
|
|
|
|
21
|
|
|
|
|
|
|
sub node_status
|
22
|
|
|
|
|
|
|
{
|
23
|
0
|
|
|
0
|
1
|
|
my $self = shift;
|
24
|
0
|
|
|
|
|
|
my $host = shift;
|
25
|
0
|
|
|
|
|
|
my $timeout = shift;
|
26
|
|
|
|
|
|
|
|
27
|
0
|
|
|
|
|
|
my $req = Net::NBName::Request->new;
|
28
|
0
|
|
|
|
|
|
$req->data(0, "*", "\x00", 0, 0x21);
|
29
|
0
|
|
|
|
|
|
my $resp = $req->unicast($host, $timeout);
|
30
|
0
|
0
|
|
|
|
|
if ($resp) {
|
31
|
0
|
|
|
|
|
|
my $ns = Net::NBName::NodeStatus->new($resp);
|
32
|
0
|
|
|
|
|
|
return $ns;
|
33
|
|
|
|
|
|
|
} else {
|
34
|
0
|
|
|
|
|
|
return undef;
|
35
|
|
|
|
|
|
|
}
|
36
|
|
|
|
|
|
|
}
|
37
|
|
|
|
|
|
|
|
38
|
|
|
|
|
|
|
sub name_query
|
39
|
|
|
|
|
|
|
{
|
40
|
0
|
|
|
0
|
1
|
|
my $self = shift;
|
41
|
0
|
|
|
|
|
|
my $host = shift;
|
42
|
0
|
|
|
|
|
|
my $name = shift;
|
43
|
0
|
|
|
|
|
|
my $suffix = shift;
|
44
|
0
|
|
0
|
|
|
|
my $flags = shift || 0x0100;
|
45
|
0
|
|
|
|
|
|
my $timeout = shift;
|
46
|
|
|
|
|
|
|
|
47
|
0
|
|
|
|
|
|
my $req = Net::NBName::Request->new;
|
48
|
0
|
|
|
|
|
|
$req->data($flags, $name, ' ', $suffix, 0x20);
|
49
|
0
|
|
|
|
|
|
my ($resp, $from_ip);
|
50
|
0
|
0
|
|
|
|
|
if (defined($host)) {
|
51
|
0
|
|
|
|
|
|
$resp = $req->unicast($host, $timeout);
|
52
|
|
|
|
|
|
|
} else {
|
53
|
0
|
|
|
|
|
|
($resp, $from_ip) = $req->broadcast($timeout);
|
54
|
|
|
|
|
|
|
}
|
55
|
|
|
|
|
|
|
|
56
|
0
|
0
|
|
|
|
|
if ($resp) {
|
57
|
0
|
|
|
|
|
|
my $nq = Net::NBName::NameQuery->new($resp);
|
58
|
0
|
|
|
|
|
|
return $nq;
|
59
|
|
|
|
|
|
|
} else {
|
60
|
0
|
|
|
|
|
|
return undef;
|
61
|
|
|
|
|
|
|
}
|
62
|
|
|
|
|
|
|
}
|
63
|
|
|
|
|
|
|
|
64
|
|
|
|
|
|
|
package Net::NBName::Request;
|
65
|
|
|
|
|
|
|
|
66
|
1
|
|
|
1
|
|
1303
|
use Socket;
|
|
1
|
|
|
|
|
5136
|
|
|
1
|
|
|
|
|
1444
|
|
67
|
|
|
|
|
|
|
|
68
|
|
|
|
|
|
|
sub new
|
69
|
|
|
|
|
|
|
{
|
70
|
0
|
|
|
0
|
|
|
my $class = shift;
|
71
|
|
|
|
|
|
|
|
72
|
0
|
|
|
|
|
|
my $self = {};
|
73
|
0
|
|
|
|
|
|
bless $self, $class;
|
74
|
0
|
|
|
|
|
|
return $self;
|
75
|
|
|
|
|
|
|
}
|
76
|
|
|
|
|
|
|
|
77
|
|
|
|
|
|
|
sub data
|
78
|
|
|
|
|
|
|
{
|
79
|
0
|
|
|
0
|
|
|
my $self = shift;
|
80
|
0
|
|
|
|
|
|
my ($flags, $name, $pad, $suffix, $qtype) = @_;
|
81
|
|
|
|
|
|
|
|
82
|
0
|
|
|
|
|
|
my $data = "";
|
83
|
0
|
|
|
|
|
|
$data .= pack("n*", $$, $flags, 1, 0, 0, 0);
|
84
|
0
|
|
|
|
|
|
$data .= _encode_name($name, $pad, $suffix);
|
85
|
0
|
|
|
|
|
|
$data .= pack("n*", $qtype, 0x0001);
|
86
|
|
|
|
|
|
|
|
87
|
0
|
|
|
|
|
|
$self->{data} = $data;
|
88
|
|
|
|
|
|
|
}
|
89
|
|
|
|
|
|
|
|
90
|
|
|
|
|
|
|
sub _encode_name
|
91
|
|
|
|
|
|
|
{
|
92
|
0
|
|
|
0
|
|
|
my $name = uc(shift);
|
93
|
0
|
|
0
|
|
|
|
my $pad = shift || "\x20";
|
94
|
0
|
|
0
|
|
|
|
my $suffix = shift || 0x00;
|
95
|
|
|
|
|
|
|
|
96
|
0
|
|
|
|
|
|
$name .= $pad x (16-length($name));
|
97
|
0
|
|
|
|
|
|
substr($name, 15, 1) = chr($suffix & 0xFF);
|
98
|
|
|
|
|
|
|
|
99
|
0
|
|
|
|
|
|
my $encoded_name = "";
|
100
|
0
|
|
|
|
|
|
for my $c (unpack("C16", $name)) {
|
101
|
0
|
|
|
|
|
|
$encoded_name .= chr(ord('A') + (($c & 0xF0) >> 4));
|
102
|
0
|
|
|
|
|
|
$encoded_name .= chr(ord('A') + ($c & 0xF));
|
103
|
|
|
|
|
|
|
}
|
104
|
|
|
|
|
|
|
|
105
|
|
|
|
|
|
|
# Note that the _encode_name function doesn't add any scope,
|
106
|
|
|
|
|
|
|
# nor does it calculate the length (32), it just prefixes it
|
107
|
0
|
|
|
|
|
|
return "\x20" . $encoded_name . "\x00";
|
108
|
|
|
|
|
|
|
}
|
109
|
|
|
|
|
|
|
|
110
|
|
|
|
|
|
|
sub unicast
|
111
|
|
|
|
|
|
|
{
|
112
|
0
|
|
|
0
|
|
|
my $self = shift;
|
113
|
0
|
|
|
|
|
|
my $host = shift;
|
114
|
|
|
|
|
|
|
# Timeout should be 250ms according to RFC1002
|
115
|
0
|
|
0
|
|
|
|
my $timeout = shift || 0.25;
|
116
|
|
|
|
|
|
|
|
117
|
0
|
|
|
|
|
|
my $data = $self->{data};
|
118
|
|
|
|
|
|
|
|
119
|
0
|
|
|
|
|
|
my $protocol = getprotobyname('udp');
|
120
|
0
|
|
|
|
|
|
my $port = 137;
|
121
|
0
|
0
|
|
|
|
|
socket(SOCK, AF_INET, SOCK_DGRAM, $protocol) or return undef;
|
122
|
0
|
|
|
|
|
|
my $to_saddr = sockaddr_in($port, inet_aton($host));
|
123
|
|
|
|
|
|
|
|
124
|
0
|
0
|
|
|
|
|
send(SOCK, $data, 0, $to_saddr) or return undef;
|
125
|
|
|
|
|
|
|
|
126
|
0
|
|
|
|
|
|
my $rin = "";
|
127
|
0
|
|
|
|
|
|
my $rout;
|
128
|
0
|
|
|
|
|
|
vec($rin, fileno(SOCK), 1) = 1;
|
129
|
|
|
|
|
|
|
|
130
|
0
|
|
|
|
|
|
my ($nfound, $timeleft) = select($rout = $rin, undef, undef, $timeout);
|
131
|
0
|
0
|
|
|
|
|
if ($nfound) {
|
132
|
0
|
|
|
|
|
|
my $resp;
|
133
|
0
|
0
|
|
|
|
|
if (my $from_saddr = recv(SOCK, $resp, 2000, 0)) {
|
134
|
0
|
|
|
|
|
|
my ($from_port, $from_ip) = sockaddr_in($from_saddr);
|
135
|
0
|
|
|
|
|
|
close(SOCKET);
|
136
|
0
|
|
|
|
|
|
return $resp;
|
137
|
|
|
|
|
|
|
} else { # socket error
|
138
|
|
|
|
|
|
|
#printf "Errno %d %s\n", $!, $^E;
|
139
|
0
|
|
|
|
|
|
close(SOCKET);
|
140
|
0
|
|
|
|
|
|
return undef;
|
141
|
|
|
|
|
|
|
}
|
142
|
|
|
|
|
|
|
} else { # timed out
|
143
|
0
|
|
|
|
|
|
close(SOCKET);
|
144
|
0
|
|
|
|
|
|
return undef;
|
145
|
|
|
|
|
|
|
}
|
146
|
|
|
|
|
|
|
}
|
147
|
|
|
|
|
|
|
|
148
|
|
|
|
|
|
|
sub broadcast
|
149
|
|
|
|
|
|
|
{
|
150
|
0
|
|
|
0
|
|
|
my $self = shift;
|
151
|
|
|
|
|
|
|
# Timeout should be 5s according to rfc1002 (but I've used 1s)
|
152
|
0
|
|
0
|
|
|
|
my $timeout = shift || 1;
|
153
|
|
|
|
|
|
|
|
154
|
0
|
|
|
|
|
|
my $host = "255.255.255.255";
|
155
|
0
|
|
|
|
|
|
my $data = $self->{data};
|
156
|
|
|
|
|
|
|
|
157
|
0
|
|
|
|
|
|
my $protocol = getprotobyname('udp');
|
158
|
0
|
|
|
|
|
|
my $port = 137;
|
159
|
0
|
0
|
|
|
|
|
socket(SOCK, AF_INET, SOCK_DGRAM, $protocol) or return undef;
|
160
|
0
|
|
|
|
|
|
setsockopt(SOCK, SOL_SOCKET, SO_BROADCAST, 1);
|
161
|
|
|
|
|
|
|
|
162
|
0
|
|
|
|
|
|
my $to_saddr = sockaddr_in($port, inet_aton($host));
|
163
|
|
|
|
|
|
|
|
164
|
0
|
0
|
|
|
|
|
send(SOCK, $data, 0, $to_saddr) or return undef;
|
165
|
0
|
|
|
|
|
|
my $rin = "";
|
166
|
0
|
|
|
|
|
|
my $rout;
|
167
|
0
|
|
|
|
|
|
vec($rin, fileno(SOCK), 1) = 1;
|
168
|
|
|
|
|
|
|
|
169
|
0
|
|
|
|
|
|
my ($nfound, $timeleft) = select($rout = $rin, undef, undef, $timeout);
|
170
|
0
|
0
|
|
|
|
|
if ($nfound) {
|
171
|
0
|
|
|
|
|
|
my $resp;
|
172
|
0
|
0
|
|
|
|
|
if (my $from_saddr = recv(SOCK, $resp, 2000, 0)) {
|
173
|
0
|
|
|
|
|
|
my ($from_port, $from_ip) = sockaddr_in($from_saddr);
|
174
|
0
|
|
|
|
|
|
close(SOCKET);
|
175
|
0
|
|
|
|
|
|
return $resp, inet_ntoa($from_ip);
|
176
|
|
|
|
|
|
|
} else { # socket error
|
177
|
|
|
|
|
|
|
#printf "Errno %d %s\n", $!, $^E;
|
178
|
0
|
|
|
|
|
|
close(SOCKET);
|
179
|
0
|
|
|
|
|
|
return undef;
|
180
|
|
|
|
|
|
|
}
|
181
|
|
|
|
|
|
|
} else { # timed out
|
182
|
0
|
|
|
|
|
|
close(SOCKET);
|
183
|
0
|
|
|
|
|
|
return undef;
|
184
|
|
|
|
|
|
|
}
|
185
|
|
|
|
|
|
|
}
|
186
|
|
|
|
|
|
|
|
187
|
|
|
|
|
|
|
1;
|
188
|
|
|
|
|
|
|
|
189
|
|
|
|
|
|
|
__END__
|