File Coverage

blib/lib/BGPmon/Translator/XFB2PerlHash/Simple.pm
Criterion Covered Total %
statement 10 12 83.3
branch n/a
condition n/a
subroutine 4 4 100.0
pod n/a
total 14 16 87.5


line stmt bran cond sub pod time code
1             package BGPmon::Translator::XFB2PerlHash::Simple;
2              
3 1     1   3422 use 5.14.0;
  1         5  
  1         54  
4 1     1   5 use strict;
  1         2  
  1         2900  
5 1     1   13 use warnings;
  1         2  
  1         36  
6 1     1   2898 use BGPmon::Translator::XFB2PerlHash;
  0            
  0            
7             use Data::Dumper;
8             use List::MoreUtils qw(uniq);
9              
10             BEGIN{
11             require Exporter;
12             our $AUTOLOAD;
13             our @ISA = qw(Exporter);
14             our @EXPORT_OK = qw(init get_timestamp get_dateTime get_nlri get_mp_nlri
15             get_withdrawn get_mp_withdrawn get_peering get_origin get_as_path get_as4_path
16             get_next_hop get_mp_next_hop get_xml_string get_error_code get_error_message
17             get_error_msg get_xml_message_type get_status);
18             our $VERSION = '2.0';
19             }
20              
21             #Variables to hold error codes and messages
22             my %error_code;
23             my %error_msg;
24             my @function_names = ('init', 'get_timestamp', 'get_dateTime', 'get_nlri',
25             'get_mp_nlri','get_withdrawn','get_mp_withdrawn','get_peering','get_origin',
26             'get_as_path','get_as4_path','get_next_hop','get_mp_next_hop','get_xml_string'
27             ,'get_xml_message_type', 'get_status');
28              
29             use constant NO_ERROR_CODE => 0;
30             use constant NO_ERROR_MSG => 'No Error. Life is good.';
31             use constant INVALID_FUNCTION_SPECIFIED_CODE => 603;
32             use constant INVALID_FUNCTION_SPECIFIED_MSG =>
33             'Invalid Function Name Specified';
34              
35             =head1 NAME
36              
37             BGPmon::Translator::XFB2PerlHash::Simple - a clean interface to extract
38             commonly-used information from XFB messages.
39              
40             =head1 SYNOPSIS
41              
42             use BGPmon::Translator::XFB2PerlHash::Simple;
43              
44             print get_error_msg('init') if !init('/XML/MESSAGE/TO/PARSE');
45              
46             my $scalar_result = get_timestamp();
47              
48             print $scalar_result;
49              
50             my @array_result = get_nlri();
51              
52             do_something() foreach my $nlri (@array_result)...
53              
54             my $hash_ref_result = get_peering();
55              
56             print $hash_ref_result-{'element'}-{'subelement'}-{'attribute'};
57              
58             =cut
59              
60             =head1 EXPORT
61              
62              
63             init get_timestamp get_dateTime get_nlri get_mp_nlri get_withdrawn
64             get_mp_withdrawn get_peering get_origin get_as_path get_as4_path get_next_hop
65             get_mp_next_hop get_xml_string get_error_code get_error_message get_error_msg
66             get_xml_message_type get_status
67              
68             =head1 SUBROUTINES/METHODS
69              
70             =head2 init
71              
72             This function takes an XML message to be translated and internally converts it
73             to an appropriate data structure for querying.
74              
75             Input: The message to be translated
76              
77             Output: 1 on success, 0 on failure
78              
79             =cut
80              
81             sub init{
82             my $msg = shift;
83             my $fname = 'init';
84             my $hash = BGPmon::Translator::XFB2PerlHash::translate_msg($msg);
85             if( !keys %$hash ){
86             $error_code{$fname} =
87             BGPmon::Translator::XFB2PerlHash::get_error_code('translate_msg');
88             $error_msg{$fname} =
89             BGPmon::Translator::XFB2PerlHash::get_error_msg('translate_msg');
90             return 0;
91             }
92             $error_code{$fname} = NO_ERROR_CODE;
93             $error_msg{$fname} = NO_ERROR_MSG;
94             return 1;
95             }
96              
97              
98              
99             =head2 get_error_code
100              
101             Get the error code
102              
103             Input : the name of the function whose error code we should report
104              
105             Output: the function's error code
106             or NO_FUNCTION_SPECIFIED if the user did not supply a function
107             or INVALID_FUNCTION_SPECIFIED if the user provided an invalid function
108             =cut
109             sub get_error_code {
110             my $function = shift;
111              
112             # check we got a function name
113             if (!defined($function)) {
114             return INVALID_FUNCTION_SPECIFIED_CODE;
115             }
116              
117             # check this is one of our exported function names
118             if (!defined($error_code{$function}) ) {
119             return INVALID_FUNCTION_SPECIFIED_CODE;
120             }
121              
122             my $code = $error_code{$function};
123             return $code;
124             }
125              
126             =head2 get_error_message
127              
128             Get the error message
129              
130             Input : the name of the function whose error message we should report
131              
132             Output: the function's error message
133             or NO_FUNCTION_SPECIFIED if the user did not supply a function
134             or INVALID_FUNCTION_SPECIFIED if the user provided an invalid function
135             =cut
136             sub get_error_message {
137             my $function = shift;
138              
139             # check we got a function name
140             if (!defined($function)) {
141             return INVALID_FUNCTION_SPECIFIED_MSG;
142             }
143              
144             # check this is one of our exported function names
145             if (!defined($error_msg{$function}) ) {
146             return INVALID_FUNCTION_SPECIFIED_MSG;
147             }
148              
149             my $msg = $error_msg{$function};
150             return $msg;
151             }
152              
153             =head2 get_error_msg
154              
155             Get the error message
156              
157             This function is identical to get_error_message
158              
159             =cut
160             sub get_error_msg {
161             my $msg = shift;
162             return get_error_message($msg);
163             }
164              
165             ############################## BEGIN UNEXPORTED FUNCTIONS #####################
166              
167             #The autoloader handles all the functions that we want to define in this module
168             # Input: a function name of the format 'get_*' where * is some element
169             # of an XFB message
170             # Output: the appropriate value(s) from the message, or undef if either
171             # the lookup fails or the element is not a defined lookup
172             sub AUTOLOAD{
173             our $AUTOLOAD;
174             my $msg = shift;
175              
176             # get the function name
177             my $sub = $AUTOLOAD;
178             (my $function_name = $sub) =~ s/.*:://;
179              
180             # check we got a valid function name
181             if( !defined $function_name ) {
182             # no function name so no error code/msg to set
183             return undef;
184             }
185              
186             #Begin by setting the error code to none; if the function is bad
187             #the error code will be set further down
188             $error_code{$function_name} = NO_ERROR_CODE;
189             $error_msg{$function_name} = NO_ERROR_MSG;
190              
191             ################################# SCALAR ELEMENTS #############################
192             =head2 get_timestamp
193              
194             Returns the UNIX timestamp from an XFB message as a scalar.
195              
196             =cut
197             return BGPmon::Translator::XFB2PerlHash::get_content
198             ('/BGP_MONITOR_MESSAGE/OBSERVED_TIME/TIMESTAMP/content')
199             if $function_name eq 'get_timestamp';
200              
201             =head2 get_dateTime
202              
203             Returns the human-readable timestamp from an XFB message as a scalar.
204              
205             =cut
206             return BGPmon::Translator::XFB2PerlHash::get_content
207             ('/BGP_MONITOR_MESSAGE/OBSERVED_TIME/DATETIME/content')
208             if $function_name eq 'get_dateTime';
209              
210             =head2 get_xml_message_type
211              
212             Returns the type of message we're seeing - if it's from a live stream or if
213             it's from a RIB dump from a BGPmon source.
214              
215             =cut
216             return BGPmon::Translator::XFB2PerlHash::get_content
217             ('/BGP_MONITOR_MESSAGE/COLLECTION/content')
218             if $function_name eq 'get_xml_message_type';
219              
220             =head2 get_origin
221              
222             Returns the stringified origin of the BGP message. Defined values are given in
223             the XFB specification.
224              
225             =cut
226             return BGPmon::Translator::XFB2PerlHash::get_content
227             ('/BGP_MONITOR_MESSAGE/bgp:UPDATE/bgp:ORIGIN/content')
228             if $function_name eq 'get_origin';
229              
230             =head2 get_next_hop
231              
232             Returns a scalar IPv4 address in dotted-decimal notation as given in the next
233             hop attribute.
234              
235             =cut
236             #Get the string representation of the content of the NEXT_HOP element
237             return BGPmon::Translator::XFB2PerlHash::get_content
238             ('/BGP_MONITOR_MESSAGE/bgp:UPDATE/bgp:NEXT_HOP/content')
239             if $function_name eq 'get_next_hop';
240              
241             =head2 get_xml_string
242              
243             Returns the raw XML string passed into init
244              
245             =cut
246             return BGPmon::Translator::XFB2PerlHash::get_content('/raw')
247             if $function_name eq 'get_xml_string';
248            
249             =head2 get_status
250              
251             Returns the status message in the XML if it exists
252              
253             =cut
254             #Return the status message
255             return BGPmon::Translator::XFB2PerlHash::get_content
256             ('/BGP_MONITOR_MESSAGE/STATUS/TYPE/content')
257             if $function_name eq 'get_status';
258              
259             ################################ ARRAY ELEMENTS ###############################
260              
261             =head2 get_mp_next_hop
262              
263             Returns an array of hashes with the next hop(s) from the MP_REACH attribute.
264              
265             Ex: my @ret = get_mp_next_hop();
266             print my $addr-{'ADDRESS'}-{'content'} foreach $addr (@ret);
267              
268             =cut
269             if($function_name eq 'get_mp_next_hop'){
270             my @prefs = ();
271             my $hashRes = BGPmon::Translator::XFB2PerlHash::get_content
272             ('/BGP_MONITOR_MESSAGE/bgp:UPDATE/bgp:MP_REACH_NLRI/bgp:MP_NEXT_HOP/');
273             if(ref($hashRes) eq "ARRAY"){
274             @prefs = (@prefs, @$hashRes);
275             }
276             elsif(ref($hashRes) eq "HASH"){
277             push(@prefs, $hashRes);
278             }
279             return @prefs;
280             }
281              
282             =head2 get_nlri
283              
284             Returns an array of hashes. Each of these hashes are structured like so:
285              
286             {
287             'SAFI' = {
288             'value' = '1',
289             'content' = 'UNICAST'
290             },
291             'AFI' = {
292             'value' = '1',
293             'content' = 'IPV4'
294             },
295             'ADDRESS' = {
296             'content' = '192.168.0.0/16'
297             }
298              
299             }
300             =cut
301             if ($function_name eq 'get_nlri'){
302             my @nlri_prefs = ();
303             my $hashRes = BGPmon::Translator::XFB2PerlHash::get_content
304             ('/BGP_MONITOR_MESSAGE/bgp:UPDATE/bgp:NLRI/');
305             if(ref($hashRes) eq "ARRAY"){
306             @nlri_prefs = (@nlri_prefs, @$hashRes);
307             }
308             elsif(ref($hashRes) eq "HASH"){
309             push(@nlri_prefs, $hashRes);
310             }
311             return @nlri_prefs;
312             }
313              
314             =head2 get_withdrawn
315              
316             Returns an array of hashes which contain an AFI,SAFI,and withdrawn IPv4 prefix.
317             These hashes are structured just like the ones described in the documentation
318             for get_nlri().
319              
320             =cut
321             if ($function_name eq 'get_withdrawn') {
322             my @with_prefs = ();
323             my $hashRes = BGPmon::Translator::XFB2PerlHash::get_content
324             ('/BGP_MONITOR_MESSAGE/bgp:UPDATE/bgp:WITHDRAW/');
325              
326             if(ref($hashRes) eq "ARRAY"){
327             @with_prefs = (@with_prefs, @$hashRes);
328             }
329             elsif(ref($hashRes) eq "HASH"){
330             push(@with_prefs, $hashRes);
331             }
332             return @with_prefs;
333             }
334              
335             ################################### HASHREF ELEMENTS ##########################
336             =head2 get_as_path
337              
338             Returns an array of hashes that contains the AS path attribute of the message.
339             Each hash represents a single AS Segment, which can be either an AS_SEQUENCE
340             or AS_SET. Each AS_SEG has an AS subarray that contains the ASNs for that
341             segment.
342              
343             =cut
344             return BGPmon::Translator::XFB2PerlHash::get_content
345             ('/BGP_MONITOR_MESSAGE/bgp:UPDATE/bgp:AS_PATH/')
346             if $function_name eq 'get_as_path';
347              
348             =head2 get_as4_path
349              
350             Returns an array of hashes that contains the AS4_PATH attribute of the message.
351             Each hash represents a single AS Segment, which can be either an AS_SEQUENCE
352             or AS_SET. Each AS_SEG has an AS subarray that contains the ASNs for that
353             segment.
354              
355             =cut
356             return BGPmon::Translator::XFB2PerlHash::get_content
357             ('/BGP_MONITOR_MESSAGE/bgp:UPDATE/bgp:AS4_PATH/')
358             if $function_name eq 'get_as4_path';
359              
360             =head2 get_mp_nlri
361              
362             Returns an array of hashes which contain an AFI,SAFI,and announced prefix.
363             These hashes are structured just like the ones described in the documentation
364             for get_nlri().
365              
366             =cut
367             return BGPmon::Translator::XFB2PerlHash::get_content
368             ('/BGP_MONITOR_MESSAGE/bgp:UPDATE/bgp:MP_REACH_/NLRI/')
369             if $function_name eq 'get_mp_nlri';
370              
371             =head2 get_mp_withdrawn
372              
373             Returns an array of hashes which contain an AFI,SAFI,and withdrawn prefix.
374             These hashes are structured just like the ones described in the documentation
375             for get_nlri().
376              
377             =cut
378             return BGPmon::Translator::XFB2PerlHash::get_content
379             ('/BGP_MONITOR_MESSAGE/bgp:UPDATE/bgp:MP_UNREACH_NLRI/')
380             if $function_name eq 'get_mp_withdrawn';
381              
382             =head2 get_peering
383              
384             Returns a hash reference that contains information about the BGP peering
385             session that the message was received from. To see its contents, check the
386             XFB specification or use Data::Dumper.
387              
388             =cut
389             return BGPmon::Translator::XFB2PerlHash::get_content
390             ('/BGP_MONITOR_MESSAGE/SOURCE/') if $function_name eq 'get_peering';
391              
392             ################################ ERROR HANDLING ###############################
393             #If there's no error code on get_content and none of the above
394             #functions were called, then an unknown function was called
395             if( !BGPmon::Translator::XFB2PerlHash::get_error_code('get_content') ){
396             $error_code{$function_name} = INVALID_FUNCTION_SPECIFIED_CODE;
397             $error_msg{$function_name} = INVALID_FUNCTION_SPECIFIED_MSG.": $function_name";
398             return undef;
399             }
400             else{
401             $error_code{$function_name} =
402             BGPmon::Translator::XFB2PerlHash::get_error_code('get_content');
403             $error_msg{$function_name} =
404             BGPmon::Translator::XFB2PerlHash::get_error_msg('get_content');
405             return undef;
406             }
407              
408             }
409              
410             #Function to return an array of values from a call to get_content
411             # Input: a reference variable that is supposed to point to an array
412             # Output: returns the array pointed at by the reference
413              
414             sub return_array{
415             my $arg = shift;
416             return @$arg if defined $arg;
417             return ();
418             }
419              
420              
421             =head1 BUGS
422              
423             Please report any bugs or feature requests to
424             C, or through
425             the web interface at L.
426              
427              
428             =head1 SUPPORT
429              
430             You can find documentation for this module with the perldoc command.
431              
432             perldoc BGPmon::Translator::XFB2PerlHash::Simple
433              
434             =cut
435              
436             =head1 LICENSE AND COPYRIGHT
437              
438             Copyright (c) 2012 Colorado State University
439              
440             Permission is hereby granted, free of charge, to any person
441             obtaining a copy of this software and associated documentation
442             files (the "Software"), to deal in the Software without
443             restriction, including without limitation the rights to use,
444             copy, modify, merge, publish, distribute, sublicense, and/or
445             sell copies of the Software, and to permit persons to whom
446             the Software is furnished to do so, subject to the following
447             conditions:
448              
449             The above copyright notice and this permission notice shall be
450             included in all copies or substantial portions of the Software.
451              
452             THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
453             EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
454             OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
455             NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
456             HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
457             WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
458             FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
459             OTHER DEALINGS IN THE SOFTWARE.\
460              
461             File: Simple.pm
462              
463             Authors: M. Lawrence Weikum, Jason Bartlett
464             Date: 13 October 2013
465              
466             =cut
467             1; #End of module BGPmon::Translator::XFB2PerlHash::Simple