File Coverage

blib/lib/Net/Frame/Layer/Syslog.pm
Criterion Covered Total %
statement 200 216 92.5
branch 25 46 54.3
condition 6 11 54.5
subroutine 49 50 98.0
pod 9 9 100.0
total 289 332 87.0


line stmt bran cond sub pod time code
1             #
2             # $Id: Syslog.pm 49 2012-11-19 13:15:34Z VinsWorldcom $
3             #
4             package Net::Frame::Layer::Syslog;
5 6     6   282117 use strict; use warnings;
  6     6   15  
  6         204  
  6         34  
  6         13  
  6         300  
6              
7             our $VERSION = '1.04';
8              
9 6     6   5306 use Net::Frame::Layer qw(:consts :subs);
  6         435965  
  6         1707  
10 6     6   62 use Exporter;
  6         11  
  6         974  
11             our @ISA = qw(Net::Frame::Layer Exporter);
12              
13             our %EXPORT_TAGS = (
14             consts => [qw(
15             NF_SYSLOG_FACILITY_KERNEL
16             NF_SYSLOG_FACILITY_USER
17             NF_SYSLOG_FACILITY_MAIL
18             NF_SYSLOG_FACILITY_SYSTEM
19             NF_SYSLOG_FACILITY_SECURITY
20             NF_SYSLOG_FACILITY_INTERNAL
21             NF_SYSLOG_FACILITY_PRINTER
22             NF_SYSLOG_FACILITY_NEWS
23             NF_SYSLOG_FACILITY_UUCP
24             NF_SYSLOG_FACILITY_CLOCK
25             NF_SYSLOG_FACILITY_SECURITY2
26             NF_SYSLOG_FACILITY_FTP
27             NF_SYSLOG_FACILITY_NTP
28             NF_SYSLOG_FACILITY_AUDIT
29             NF_SYSLOG_FACILITY_ALERT
30             NF_SYSLOG_FACILITY_CLOCK2
31             NF_SYSLOG_FACILITY_LOCAL0
32             NF_SYSLOG_FACILITY_LOCAL1
33             NF_SYSLOG_FACILITY_LOCAL2
34             NF_SYSLOG_FACILITY_LOCAL3
35             NF_SYSLOG_FACILITY_LOCAL4
36             NF_SYSLOG_FACILITY_LOCAL5
37             NF_SYSLOG_FACILITY_LOCAL6
38             NF_SYSLOG_FACILITY_LOCAL7
39             NF_SYSLOG_SEVERITY_EMERGENCY
40             NF_SYSLOG_SEVERITY_ALERT
41             NF_SYSLOG_SEVERITY_CRITICAL
42             NF_SYSLOG_SEVERITY_ERROR
43             NF_SYSLOG_SEVERITY_WARNING
44             NF_SYSLOG_SEVERITY_NOTICE
45             NF_SYSLOG_SEVERITY_INFORMATIONAL
46             NF_SYSLOG_SEVERITY_DEBUG
47             )],
48             subs => [qw(
49             priorityAton
50             priorityNtoa
51             )],
52             );
53             our @EXPORT_OK = (
54             @{$EXPORT_TAGS{consts}},
55             @{$EXPORT_TAGS{subs}},
56             );
57              
58 6     6   44 use constant NF_SYSLOG_FACILITY_KERNEL => 0;
  6         14  
  6         373  
59 6     6   32 use constant NF_SYSLOG_FACILITY_USER => 1;
  6         12  
  6         249  
60 6     6   31 use constant NF_SYSLOG_FACILITY_MAIL => 2;
  6         17  
  6         273  
61 6     6   30 use constant NF_SYSLOG_FACILITY_SYSTEM => 3;
  6         10  
  6         260  
62 6     6   30 use constant NF_SYSLOG_FACILITY_SECURITY => 4;
  6         13  
  6         296  
63 6     6   88 use constant NF_SYSLOG_FACILITY_INTERNAL => 5;
  6         12  
  6         282  
64 6     6   31 use constant NF_SYSLOG_FACILITY_PRINTER => 6;
  6         10  
  6         275  
65 6     6   29 use constant NF_SYSLOG_FACILITY_NEWS => 7;
  6         10  
  6         310  
66 6     6   34 use constant NF_SYSLOG_FACILITY_UUCP => 8;
  6         11  
  6         290  
67 6     6   40 use constant NF_SYSLOG_FACILITY_CLOCK => 9;
  6         10  
  6         234  
68 6     6   28 use constant NF_SYSLOG_FACILITY_SECURITY2 => 10;
  6         9  
  6         257  
69 6     6   27 use constant NF_SYSLOG_FACILITY_FTP => 11;
  6         10  
  6         336  
70 6     6   28 use constant NF_SYSLOG_FACILITY_NTP => 12;
  6         10  
  6         231  
71 6     6   26 use constant NF_SYSLOG_FACILITY_AUDIT => 13;
  6         9  
  6         269  
72 6     6   35 use constant NF_SYSLOG_FACILITY_ALERT => 14;
  6         24  
  6         240  
73 6     6   26 use constant NF_SYSLOG_FACILITY_CLOCK2 => 15;
  6         10  
  6         290  
74 6     6   31 use constant NF_SYSLOG_FACILITY_LOCAL0 => 16;
  6         12  
  6         299  
75 6     6   27 use constant NF_SYSLOG_FACILITY_LOCAL1 => 17;
  6         12  
  6         323  
76 6     6   32 use constant NF_SYSLOG_FACILITY_LOCAL2 => 18;
  6         10  
  6         291  
77 6     6   29 use constant NF_SYSLOG_FACILITY_LOCAL3 => 19;
  6         191  
  6         369  
78 6     6   29 use constant NF_SYSLOG_FACILITY_LOCAL4 => 20;
  6         11  
  6         233  
79 6     6   27 use constant NF_SYSLOG_FACILITY_LOCAL5 => 21;
  6         8  
  6         251  
80 6     6   26 use constant NF_SYSLOG_FACILITY_LOCAL6 => 22;
  6         9  
  6         260  
81 6     6   35 use constant NF_SYSLOG_FACILITY_LOCAL7 => 23;
  6         9  
  6         252  
82 6     6   27 use constant NF_SYSLOG_SEVERITY_EMERGENCY => 0;
  6         10  
  6         262  
83 6     6   27 use constant NF_SYSLOG_SEVERITY_ALERT => 1;
  6         10  
  6         224  
84 6     6   26 use constant NF_SYSLOG_SEVERITY_CRITICAL => 2;
  6         99  
  6         286  
85 6     6   28 use constant NF_SYSLOG_SEVERITY_ERROR => 3;
  6         10  
  6         218  
86 6     6   56 use constant NF_SYSLOG_SEVERITY_WARNING => 4;
  6         11  
  6         257  
87 6     6   26 use constant NF_SYSLOG_SEVERITY_NOTICE => 5;
  6         10  
  6         230  
88 6     6   27 use constant NF_SYSLOG_SEVERITY_INFORMATIONAL => 6;
  6         27  
  6         4616  
89 6     6   41 use constant NF_SYSLOG_SEVERITY_DEBUG => 7;
  6         8  
  6         830  
90              
91             our @FACILITY = qw(kernel user mail system security internal printer news uucp clock security2 FTP NTP audit alert clock2 local0 local1 local2 local3 local4 local5 local6 local7);
92             our @SEVERITY = qw(Emergency Alert Critical Error Warning Notice Informational Debug);
93              
94             our @AS = qw(
95             facility
96             severity
97             timestamp
98             host
99             tag
100             content
101             msg
102             );
103             __PACKAGE__->cgBuildIndices;
104             __PACKAGE__->cgBuildAccessorsScalar(\@AS);
105              
106             #no strict 'vars';
107 6     6   38 use Socket qw(inet_ntoa AF_INET IPPROTO_TCP);
  6         10  
  6         653  
108              
109             #my $AF_INET6 = eval { Socket::AF_INET6() };
110             my $AF_UNSPEC = eval { Socket::AF_UNSPEC() };
111             #my $AI_NUMERICHOST = eval { Socket::AI_NUMERICHOST() };
112             my $NI_NUMERICHOST = eval { Socket::NI_NUMERICHOST() };
113              
114 6     6   6909 use Sys::Hostname;
  6         9678  
  6         12272  
115              
116             $Net::Frame::Layer::UDP::Next->{514} = "Syslog";
117              
118             sub new {
119 3     3 1 2708 my $time = _getTime();
120 3         12 my $host = _getHost();
121 3         15 my $tag = _getTag();
122              
123             shift->SUPER::new(
124 3         53 facility => NF_SYSLOG_FACILITY_LOCAL7,
125             severity => NF_SYSLOG_SEVERITY_INFORMATIONAL,
126             timestamp => $time,
127             host => $host,
128             tag => $tag,
129             content => 'syslog message',
130             @_,
131             );
132             }
133              
134             sub message {
135 1     1 1 29 my $time = _getTime();
136 1         4 my $host = _getHost();
137 1         4 my $tag = _getTag();
138              
139             shift->SUPER::new(
140 1         10 msg => "<190>$time $host $tag syslog message",
141             @_,
142             );
143             }
144              
145             sub getLength {
146 0     0 1 0 my $self = shift;
147              
148 0 0       0 if (defined($self->msg)) {
149 0         0 return length($self->msg)
150             } else {
151              
152 0         0 my $priority = priorityAton($self->facility, $self->severity);
153 0         0 my $len =
154             length($priority) +
155             length($self->timestamp) +
156             length($self->host) +
157             length($self->tag) +
158             length($self->content) +
159             5;
160              
161 0         0 return $len
162             }
163             }
164              
165             sub pack {
166 3     3 1 775 my $self = shift;
167              
168 3         6 my $raw;
169 3 100       12 if (defined($self->msg)) {
170 1 50       15 $raw = $self->SUPER::pack('a*',
171             $self->msg
172             ) or return;
173             } else {
174 2         52 my $priority = priorityAton($self->facility, $self->severity);
175              
176 2 50       13 $raw = $self->SUPER::pack('a*',
177             "<" .
178             $priority .
179             ">" .
180             $self->timestamp .
181             " " .
182             $self->host .
183             " " .
184             $self->tag .
185             " " .
186             $self->content
187             ) or return;
188             }
189              
190 3         172 return $self->raw($raw);
191             }
192              
193             sub unpack {
194 1     1 1 16 my $self = shift;
195              
196 1 50       8 my ($payload) =
197             $self->SUPER::unpack('a*', $self->raw)
198             or return;
199              
200 1         25 my $regex = '<(\d{1,3})>[\d{1,}: \*]*((?:[JFMASONDjfmasond]\w\w) {1,2}(?:\d+)(?: \d{4})* (?:\d{2}:\d{2}:\d{2}[\.\d{1,3}]*)(?: [A-Z]{1,3})*)?:*\s*(?:((?:[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3})|(?:[a-zA-Z\-]+)|(?:(?:(?:[0-9A-Fa-f]{1,4}:){7}(?:[0-9A-Fa-f]{1,4}|:))|(?:(?:[0-9A-Fa-f]{1,4}:){6}(?::[0-9A-Fa-f]{1,4}|(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(?:\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(?:(?:[0-9A-Fa-f]{1,4}:){5}(?:(?:(?::[0-9A-Fa-f]{1,4}){1,2})|:(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(?:\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(?:(?:[0-9A-Fa-f]{1,4}:){4}(?:(?:(?::[0-9A-Fa-f]{1,4}){1,3})|(?:(?::[0-9A-Fa-f]{1,4})?:(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(?:\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(?:(?:[0-9A-Fa-f]{1,4}:){3}(?:(?:(?::[0-9A-Fa-f]{1,4}){1,4})|(?:(?::[0-9A-Fa-f]{1,4}){0,2}:(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(?:\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(?:(?:[0-9A-Fa-f]{1,4}:){2}(?:(?:(?::[0-9A-Fa-f]{1,4}){1,5})|(?:(?::[0-9A-Fa-f]{1,4}){0,3}:(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(?:\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(?:(?:[0-9A-Fa-f]{1,4}:){1}(?:(?:(?::[0-9A-Fa-f]{1,4}){1,6})|(?:(?::[0-9A-Fa-f]{1,4}){0,4}:(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(?:\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(?::(?:(?:(?::[0-9A-Fa-f]{1,4}){1,7})|(?:(?::[0-9A-Fa-f]{1,4}){0,5}:(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(?:\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:)))(?:%.+)?) )?(.*)';
201 1         346 my $Cregex = qr/$regex/;
202              
203 1 50       21 if ($payload =~ /$Cregex/) {
204              
205 1         4 my $priority = $1;
206 1   50     5 my $timestamp = $2 || '0';
207 1   50     4 my $hostname = $3 || '0';
208 1         3 my $message = $4;
209 1         3 my ($facility, $severity) = priorityNtoa($priority);
210              
211 1         5 $self->facility($facility);
212 1         12 $self->severity($severity);
213 1         10 $self->timestamp($timestamp);
214              
215 1         9 $hostname =~ s/\s+//;
216 1         3 $self->host($hostname);
217              
218 1         9 my %chars;
219 1         4 $chars{bracket} = index($message,"]");
220 1         2 $chars{colon} = index($message,":");
221 1         3 $chars{space} = index($message," ");
222 1         2 my $win = 0;
223 1         48 foreach my $ch (sort {$chars{$b} cmp $chars{$a}} keys %chars) {
  3         9  
224 3 100       8 if ($chars{$ch} > 0) {
225 2         3 $win = $ch
226             }
227             }
228 1 50       4 if ($chars{$win} > 0) {
229 1   50     5 my $tag = substr($message, 0, $chars{$win}+1) || '0';
230 1   50     4 my $content = substr($message, $chars{$win}+1) || '0';
231 1         4 $self->tag($tag);
232 1         11 $self->content($content)
233             } else {
234 0         0 $self->tag('0');
235 0         0 $self->content($message)
236             }
237              
238 1         10 my $msg = substr $payload, index($payload,">")+1;
239 1         3 $self->msg($msg)
240              
241             } else {
242 0         0 $self->facility(undef);
243 0         0 $self->severity(undef);
244 0         0 $self->msg($payload)
245             }
246              
247 1         13 return $self;
248             }
249              
250             sub encapsulate {
251 1     1 1 6 my $self = shift;
252              
253 1 50       8 return $self->nextLayer if $self->nextLayer;
254              
255             # Needed?
256 1 50       17 if ($self->payload) {
257 0         0 return 'Syslog';
258             }
259              
260 1         10 NF_LAYER_NONE;
261             }
262              
263             sub print {
264 3     3 1 577 my $self = shift;
265              
266 3         19 my $l = $self->layer;
267 3         27 my $buf;
268 3 100       12 if (defined($self->msg)) {
269 2 100 66     25 if (defined($self->facility) && defined($self->severity)) {
270 1         33 $buf = sprintf
271             "$l: facility:$FACILITY[$self->facility] severity:$SEVERITY[$self->severity]\n"
272             }
273 2         45 $buf .= sprintf
274             "$l: message:%s",
275             $self->msg;
276             } else {
277 1         36 $buf = sprintf
278             "$l: facility:$FACILITY[$self->facility] severity:$SEVERITY[$self->severity]\n".
279             "$l: timestamp:%s host:%s\n".
280             "$l: tag:%s\n".
281             "$l: content:%s",
282             $self->timestamp, $self->host,
283             $self->tag,
284             $self->content;
285             }
286              
287 3         1166 return $buf;
288             }
289              
290             ####
291              
292             sub priorityAton {
293 3     3 1 46 my ($fac, $sev) = @_;
294              
295 3         9 return (($fac << 3) | $sev)
296             }
297              
298             sub priorityNtoa {
299 3     3 1 759 my ($pri, $flag) = @_;
300              
301 3         8 my $sev = $pri % 8;
302 3         13 my $fac = ($pri - $sev) / 8;
303              
304 3 100       10 if (defined($flag)) {
305 1         8 return ($FACILITY[$fac], $SEVERITY[$sev])
306             } else {
307 2         7 return ($fac, $sev)
308             }
309             }
310              
311             sub _getTime {
312 4     4   23 my @month = qw(Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec);
313 4         171 my @time = localtime();
314 4 50       57 my $ts =
    50          
    50          
    50          
315             $month[ $time[4] ] . " "
316             . ( ( $time[3] < 10 ) ? ( " " . $time[3] ) : $time[3] ) . " "
317             . ( ( $time[2] < 10 ) ? ( "0" . $time[2] ) : $time[2] ) . ":"
318             . ( ( $time[1] < 10 ) ? ( "0" . $time[1] ) : $time[1] ) . ":"
319             . ( ( $time[0] < 10 ) ? ( "0" . $time[0] ) : $time[0] );
320              
321 4         20 return $ts
322             }
323              
324             sub _getHost {
325 4     4   7 my $hostname = 'localhost';
326              
327 4 50       31 if ($Socket::VERSION >= 1.94) {
328 4         21 my %hints = (
329             family => $AF_UNSPEC,
330             protocol => IPPROTO_TCP
331             );
332 4         23 my ($err, @getaddr) = Socket::getaddrinfo(Sys::Hostname::hostname, undef, \%hints);
333 4 50       2273 if (defined($getaddr[0])) {
334 4         2878 my ($err, $address) = Socket::getnameinfo($getaddr[0]->{addr}, $NI_NUMERICHOST);
335 4 50       29 if (defined($address)) {
336 4         8 $hostname = $address;
337 4         35 $hostname =~ s/\%(.)*$// # remove %ifID if IPv6
338             }
339             }
340             } else {
341 0         0 my @gethost = gethostbyname(Sys::Hostname::hostname);
342 0 0       0 if (defined($gethost[4])) {
343 0         0 $hostname = inet_ntoa($gethost[4])
344             }
345             }
346 4         14 return $hostname
347             }
348              
349             sub _getTag {
350 4     4   13 my $name = $0;
351 4 50       46 if ($name =~ /.+\/(.+)/) {
    0          
352 4         18 $name = $1;
353             } elsif ($name =~ /.+\\(.+)/) {
354 0         0 $name = $1;
355             }
356              
357 4         33 return $name . "[" . $$ . "]"
358             }
359              
360             1;
361              
362             __END__