Printing for debugging

Printing for debugging

am 14.01.2008 14:40:11 von Raful Mr Mitchell H

This is a multi-part message in MIME format.

------_=_NextPart_001_01C856B2.FC34841D
Content-Type: text/plain;
charset="iso-8859-1"
Content-Transfer-Encoding: quoted-printable

I have my code pasted below. My module, loaded with =
directive in Apache2, works well. However, sometimes switches don't =
respond correctly to bulk queries of fdbPorts object. What I want to do =
is to be able print the value of my variables either to the browser or a =
log file. A regular print statement does not work for this. The =
relevant variables are in a subroutine called from my sub handler.
=20
Thanks in advance.
=20

#!/usr/bin/perl -w

package Handlers::PortMapper;

use warnings;

use strict;

use HTML::Template;

use DBI;

use Socket qw(:DEFAULT :crlf);

use dec_hex;

use snmpSession;

use SNMP;

use Net::NBName;

use Net::Ping;

use Apache2::Request ();

use Apache2::Const -compile=3D>'OK';

=20

# %seen_vlans --tracks those vlans which are seen as each ports vlan =
membership is looked at=20

# %device --all results for each device found on a switch are placed =
here for dispatching to a web page

# @answer;

my @switch_row; #--hold results of db query for switch

my @router_row; #--hold results of db query for router whose arp cache =
you want

my %devices_ref;

my %hash;

my $time; # --gets time query began

my $chosen_switch; #--switch passed via http form data

my $chosen_router; #--switch passed via http form data

my $switch_ip; #--result one for initial query

my $switch_model; #--result two for initial query

my $devices_ref;

my $router_ip; # --result for query of router address

my $dbh; #--database handle

my $sql; #--database query

my @loop_data; #--hold hashes for my template

# $i =3D 0 --counters

# $j =3D 0 --counters

sub handler {

my $r =3D shift;

my $req =3D Apache2::Request->new( $r );

$r->content_type('text/html');=20

my %mac_data;

my @mac_array; #hold individual hex digits returned by =
ipNetToMediaPhysAddress

my @loop_data =3D (); #array of anonymous hashes which is dispatched to =
web page for display

my $template =3D HTML::Template->new( filename =3D> =
'/home/mitch/www-dev/mod_perl/templates/portmapper.tmpl',

debug =3D> 1,

die_on_bad_params =3D> 0 );

my $time =3D localtime();

$chosen_switch =3D $req->param('chosen_switch');

$chosen_switch =3D~ s/(\s.*)//g;

$chosen_router =3D $req->param( 'chosen_router' );

$dbh =3D DBI->connect( 'dbi:ODBC:MRIServer2k', 'mriinventory', =
'Wysiwyg@3044',

{ PrintError =3D> 1, RaiseError =3D> 0, AutoCommit =3D> 1 } );

$sql =3D "SELECT address, chassis_description FROM tblLiveCisco WHERE =
name=3D'$chosen_switch'";

@switch_row =3D $dbh->selectrow_array( $sql );

$switch_ip =3D $switch_row[0];

$switch_model =3D $switch_row[1];

@router_row =3D $dbh->selectrow_array("SELECT address FROM tblLiveCisco =
WHERE name=3D'$chosen_router'" );

$router_ip =3D $router_row[0];

$devices_ref =3D getDevices( $router_ip, $switch_ip, 'public');

foreach $_ (@{$devices_ref}) {

%hash =3D %$_;

push @loop_data, \%hash ;

}

$template->param(CHOSEN_SWITCH =3D> $chosen_switch );

$template->param(MODEL =3D> $switch_model );

$template->param(TIME =3D> $time );

$template->param(LOOP_DATA =3D> \@loop_data );

print "Content-Type: text/html\n\n";

print $template->output;

return Apache2::Const::OK;

}

sub getDevices {

my $router =3D shift;

my $switch =3D shift;

my $community =3D shift;

my @mac_array =3D ();

my %seen_vlans =3D ();

my %ifnames; #holds the ifIndex number and names of ports

my %trunk; #holds all ports on a switch that are trunking

my %arpCache;

my @data;

my @vlans; #all vlans found using vmVlan object

my $arp_mib =3D 'ipNetToMediaPhysAddress';

my ( $mac_address,$ip, $dns_name, $device_type );

my $arp_session =3D snmpSession::openSession( $router , $community, 1 );

my $vb_arp =3D new SNMP::Varbind( [$arp_mib] );

for(my $var =3D $arp_session->getnext( $vb_arp );

( $vb_arp->tag eq $arp_mib ) and not ( $arp_session->{ErrorNum} );

$var =3D $arp_session->getnext( $vb_arp )

) {

my $ip_addr =3D ( $vb_arp->tag . $vb_arp->iid );

$ip_addr =3D~ s/$arp_mib\d+\.//g;

my @vars =3D split(/:/, $var );

for( my $x =3D 0; $x < scalar( @vars ); $x++ ) {

if( length( $vars[$x] ) < 2 )

{

$vars[$x] =3D "0"."$vars[$x]";

}

push( @mac_array, $vars[$x] );

}

my $arp_mac_address =3D join( "", @mac_array );

push( @{$arpCache{$arp_mac_address}}, $ip_addr );

@mac_array =3D ();

}

if( $arp_session->{ErrorNum} ){ print "Got $arp_session->{ErrorStr} for =
$router\n"; }

my $vlan_session =3D snmpSession::openSession ( $switch, $community, 1 =
);

my $vb_vlan =3D new SNMP::VarList( ['vmVlan'], ['ifName'], =
['vlanTrunkPortDynamicStatus'] );

my @answers1 =3D $vlan_session->bulkwalk(0, 100, $vb_vlan );

if( $vlan_session->{ErrorNum} ) {

print "Got ", $vlan_session->{ErrorStr}, "on", =
$vlan_session->{DestHost}, " during Bulkwalk\n";

}

my $vlan_answer =3D $answers1[0];

my $ifName_answer =3D $answers1[1];

my $trunk_ports =3D $answers1[2];

for( my $i =3D 0; $i < scalar(@$vlan_answer); $i++ )

{

my $vlan =3D $vlan_answer->[$i]->[ 2];

if ( !exists ($seen_vlans{$vlan} ) ) {

push( @vlans, $vlan );

$seen_vlans{$vlan} =3D 1;

}

}

for( my $j =3D 0; $j < scalar(@$ifName_answer); $j++ )

{

my $index =3D $ifName_answer->[$j]->[1];

my $interface_name =3D $ifName_answer->[$j]->[2];

push @{$ifnames{$index}}, $interface_name;

}

for ( my $p =3D 0; $p < scalar( @$trunk_ports ); $p++ ) {

my $port_index =3D $trunk_ports->[$p]->[1];

if( $trunk_ports->[$p]->[2] eq 'trunking' )

{

$trunk{$port_index} =3D 1;

}

}

my $vb_cam =3D new SNMP::VarList( ['dot1dTpFdbPort'], =
['dot1dBasePortIfIndex'] );

foreach $_ ( @vlans ) {

$community =3D "public@"."$_";

my $cam_session =3D snmpSession::openSession ( $switch, $community, 1 );

my @answers2 =3D $cam_session->bulkwalk(0, 1000, $vb_cam );

my $fdbPorts =3D $answers2[0];

my $portIndexes =3D $answers2[1];

for ( my $q =3D 0; $q < scalar( @$fdbPorts ); $q++ ) {

for( my $r =3D 0; $r < scalar( @$portIndexes ); $r++ ) {

if( $fdbPorts->[$q]->[2] == $portIndexes->[$r]->[1] && !exists( =
$trunk{ $portIndexes->[$r]->[2] } ) )

{

$mac_address =3D lc(dec_hex::dec_to_hex( $fdbPorts->[$q]->[1] ) );

if( exists($arpCache{$mac_address} ) ) {

$ip =3D $arpCache{$mac_address}->[0];

$dns_name =3D getName( $ip );

$device_type =3D getDeviceType( $ip );

}

else { $ip =3D undef; }

if( !defined( $ip ) )

{

if( $mac_address =3D~ /000255/o )

{

$device_type =3D 'Register';

}

elsif( $mac_address =3D~ /000ff8/o )

{

$device_type =3D 'PSC handheld';

}

elsif( $mac_address =3D~ /00a0f8/g )

{

$device_type =3D 'Symbol RF device';

}

elsif( $mac_address =3D~ /001795/g )

{

$device_type =3D 'Cisco Systems AP';

}

}

my %device =3D ();=20

$device{PORT} =3D "@{$ifnames{ $portIndexes->[$r]->[2]} }";

$device{MAC} =3D $mac_address;

$device{IP} =3D $ip;

$device{DEVICE} =3D $dns_name;

$device{TYPE} =3D $device_type;

push( @data, \%device );

}

}

}

}

return \@data;

}

sub getName {

my $ip_address =3D shift(@_);

my( $nbQuery, $nbStatus, $DNS, $packed_binary_address );

$packed_binary_address =3D inet_aton( $ip_address);

$DNS =3D gethostbyaddr( $packed_binary_address, AF_INET );

if( !$DNS ) {

$nbQuery =3D Net::NBName->new;

$nbStatus =3D $nbQuery->node_status( $ip_address );

if( defined $nbStatus )

{

$DNS =3D $nbStatus->{names}->[0]->{name};

}

if( !$DNS ) { $DNS =3D 'unknown' }

}

return $DNS;

}

sub getDeviceType {

my $address =3D shift( @_ );

my ( $type, $rtt, $tcp_print, $addr, $host);

$tcp_print =3D Net::Ping->new("syn");

$tcp_print->{port_num} =3D "9100";

$tcp_print->service_check( 1 );

$tcp_print->ping( $address );

if( ( $host, $rtt, $addr ) =3D $tcp_print->ack )

{

$type =3D "Printer";

}

else{

$tcp_print =3D Net::Ping->new("syn");

$tcp_print->{port_num} =3D "4500";

$tcp_print->service_check( 1 );

$tcp_print->ping( $address );

if( ( $host, $rtt, $addr ) =3D $tcp_print->ack )

{

$type =3D "Controller"

}

}

return $type;

}

1;

Mitchell Raful MCSE CCNP=20
MCB Quantico=20
Personal and Family Readiness (MRI)=20
3044 Catlin Avenue=20
Quantico, VA 22134=20
Com: 703-784-5991=20
DSN: 278-5991=20
Cell: 804-363-0731=20

=20

------_=_NextPart_001_01C856B2.FC34841D
Content-Type: text/html;
charset="iso-8859-1"
Content-Transfer-Encoding: quoted-printable



charset=3Diso-8859-1">




I have =
my code=20
pasted below.  My module, loaded with <Location> directive in =

Apache2, works well.  However, sometimes switches don't respond =
correctly=20
to bulk queries of fdbPorts object.  What I want to do is to be =
able print=20
the value of my variables either to the browser or a log file.  A =
regular=20
print statement does not work for this.  The relevant variables are =
in a=20
subroutine called from my sub handler.

size=3D2> 

Thanks =
in=20
advance.

size=3D2> 

size=3D2>#!/usr/bin/perl -w

package =
Handlers::PortMapper;

use =
warnings;

use strict;

size=3D2>use HTML::Template;

use =
DBI;

use Socket qw(:DEFAULT =
:crlf);

use dec_hex;

size=3D2>use snmpSession;

use =
SNMP;

use Net::NBName;

size=3D2>use Net::Ping;

use Apache2::Request =
();

use Apache2::Const =
-compile=3D>'OK';

size=3D2> 

# %seen_vlans --tracks those =
vlans which are seen as each ports vlan membership is looked at =

# %device --all results for each device =
found on a switch are placed here for dispatching to a web =
page

# @answer;

size=3D2>my @switch_row; #--hold results of db query for =
switch

my @router_row; #--hold results of db =
query for router whose arp cache you want

my =
%devices_ref;

my %hash;

size=3D2>my $time; # --gets time query began

size=3D2>my $chosen_switch; #--switch passed via http form =
data

my $chosen_router; #--switch passed via =
http form data

my $switch_ip; #--result one =
for initial query

my $switch_model; =
#--result two for initial query

my =
$devices_ref;

my $router_ip; # --result for =
query of router address

my $dbh; #--database =
handle

my $sql; #--database =
query

my @loop_data; #--hold hashes for my =
template

# $i =3D 0 =
--counters

# $j =3D 0 =
--counters

sub handler {

size=3D2>my $r =3D shift;

my $req =3D =
Apache2::Request->new( $r );

size=3D2>$r->content_type('text/ class=3D894423513-14012008>html');

size=3D2>my %mac_data;

my @mac_array; #hold =
individual hex digits returned by =
ipNetToMediaPhysAddress

my @loop_data =3D =
(); #array of anonymous hashes which is dispatched to web page for =
display

my $template =3D =
HTML::Template->new( filename =3D> =
'/home/mitch/www-dev/mod_perl/templates/portmapper.tmpl',

ONT size=3D2>debug =3D> 1,

size=3D2>die_on_bad_params =3D> 0 );

size=3D2>

my $time =3D =
localtime();

$chosen_switch =3D =
$req->param('chosen_switch');

size=3D2>$chosen_switch =3D~ s/(\s.*)//g;

size=3D2>$chosen_router =3D $req->param( 'chosen_router' =
);

$dbh =3D DBI->connect( =
'dbi:ODBC:MRIServer2k', 'mriinventory', =
'Wysiwyg@3044',

{ PrintError =3D> 1, =
RaiseError =3D> 0, AutoCommit =3D> 1 } );

size=3D2>$sql =3D "SELECT address, chassis_description FROM tblLiveCisco =
WHERE name=3D'$chosen_switch'";

@switch_row =
=3D $dbh->selectrow_array( $sql );

size=3D2>$switch_ip =3D $switch_row[0];

size=3D2>$switch_model =3D $switch_row[1];

size=3D2>@router_row =3D $dbh->selectrow_array("SELECT address FROM =
tblLiveCisco WHERE name=3D'$chosen_router'" );

size=3D2>$router_ip =3D $router_row[0];

size=3D2>$devices_ref =3D getDevices( $router_ip, $switch_ip, =
'public');

foreach $_ (@{$devices_ref}) =
{

%hash =3D %$_;

size=3D2>push @loop_data, \%hash ;

size=3D2>}

$template->param(CHOSEN_SWITCH =
=3D> $chosen_switch );

size=3D2>$template->param(MODEL =3D> $switch_model =
);

$template->param(TIME =3D> $time =
);

$template->param(LOOP_DATA =3D> =
\@loop_data );

print "Content-Type: =
text/html\n\n";

print =
$template->output;

return =
Apache2::Const::OK;

}

size=3D2>sub getDevices {

my $router =3D =
shift;

my $switch =3D =
shift;

my $community =3D =
shift;

my @mac_array =3D =
();

my %seen_vlans =3D =
();

my %ifnames; #holds the ifIndex number =
and names of ports

my %trunk; #holds all =
ports on a switch that are trunking

my =
%arpCache;

my @data;

size=3D2>my @vlans; #all vlans found using vmVlan =
object

my $arp_mib =3D =
'ipNetToMediaPhysAddress';

my ( =
$mac_address,$ip, $dns_name, $device_type );

size=3D2>

my $arp_session =3D =
snmpSession::openSession( $router , $community, 1 );

size=3D2>my $vb_arp =3D new SNMP::Varbind( [$arp_mib] =
);

for(my $var =
=3D $arp_session->getnext( $vb_arp );

( =
$vb_arp->tag eq $arp_mib ) and not ( $arp_session->{ErrorNum} =
);

$var =3D $arp_session->getnext( =
$vb_arp )

) {

my =
$ip_addr =3D ( $vb_arp->tag . $vb_arp->iid );

size=3D2>$ip_addr =3D~ s/$arp_mib\d+\.//g;

size=3D2>my @vars =3D split(/:/, $var );

size=3D2>

for( my $x =3D 0; $x < scalar( =
@vars ); $x++ ) {

if( length( $vars[$x] ) =
< 2 )

{

size=3D2>$vars[$x] =3D "0"."$vars[$x]";

size=3D2>}

push( @mac_array, $vars[$x] =
);

}

my =
$arp_mac_address =3D join( "", @mac_array );

size=3D2>push( @{$arpCache{$arp_mac_address}}, $ip_addr =
);

@mac_array =3D ();

size=3D2>}

if( $arp_session->{ErrorNum} =
){ print "Got $arp_session->{ErrorStr} for $router\n"; =
}

my $vlan_session =3D =
snmpSession::openSession ( $switch, $community, 1 );

size=3D2>my $vb_vlan =3D new SNMP::VarList( ['vmVlan'], ['ifName'], =
['vlanTrunkPortDynamicStatus'] );

my =
@answers1 =3D $vlan_session->bulkwalk(0, 100, $vb_vlan =
);

if( $vlan_session->{ErrorNum} ) =
{

print "Got ", =
$vlan_session->{ErrorStr}, "on", $vlan_session->{DestHost}, " =
during Bulkwalk\n";

}

size=3D2>my $vlan_answer =3D $answers1[0];

size=3D2>my $ifName_answer =3D $answers1[1];

size=3D2>my $trunk_ports =3D $answers1[2];

size=3D2>for( my $i =3D 0; $i < scalar(@$vlan_answer); $i++ =
)

{

my $vlan =3D =
$vlan_answer->[$i]->[ 2];

if ( !exists =
($seen_vlans{$vlan} ) ) {

push( @vlans, =
$vlan );

$seen_vlans{$vlan} =3D =
1;

}

size=3D2>}

for( my $j =3D 0; $j < =
scalar(@$ifName_answer); $j++ )

size=3D2>{

my $index =3D =
$ifName_answer->[$j]->[1];

my =
$interface_name =3D $ifName_answer->[$j]->[2];

size=3D2>push @{$ifnames{$index}}, $interface_name;

size=3D2>}

for =
( my $p =3D 0; $p < scalar( @$trunk_ports ); $p++ ) =
{

my $port_index =3D =
$trunk_ports->[$p]->[1];

if( =
$trunk_ports->[$p]->[2] eq 'trunking' )

size=3D2>{

$trunk{$port_index} =3D =
1;

}

size=3D2>}

my $vb_cam =3D new SNMP::VarList( =
['dot1dTpFdbPort'], ['dot1dBasePortIfIndex'] );

size=3D2>foreach $_ ( @vlans ) {

$community =
=3D "public@"."$_";

my $cam_session =3D =
snmpSession::openSession ( $switch, $community, 1 );

size=3D2>my @answers2 =3D $cam_session->bulkwalk(0, 1000, $vb_cam =
);

my $fdbPorts =3D =
$answers2[0];

my $portIndexes =3D =
$answers2[1];

for ( my $q =3D 0; $q < =
scalar( @$fdbPorts ); $q++ ) {

for( my $r =
=3D 0; $r < scalar( @$portIndexes ); $r++ ) {

size=3D2>if( $fdbPorts->[$q]->[2] == =
$portIndexes->[$r]->[1] && !exists( $trunk{ =
$portIndexes->[$r]->[2] } ) )

size=3D2>{

$mac_address =3D =
lc(dec_hex::dec_to_hex( $fdbPorts->[$q]->[1] ) =
);

if( exists($arpCache{$mac_address} ) ) =
{

$ip =3D =
$arpCache{$mac_address}->[0];

$dns_name =
=3D getName( $ip );

$device_type =3D =
getDeviceType( $ip );

}

size=3D2>else { $ip =3D undef; }

if( =
!defined( $ip ) )

{

size=3D2>if( $mac_address =3D~ /000255/o )

size=3D2>{

$device_type =3D =
'Register';

}

size=3D2>elsif( $mac_address =3D~ /000ff8/o )

size=3D2>{

$device_type =3D 'PSC =
handheld';

}

size=3D2>elsif( $mac_address =3D~ /00a0f8/g )

size=3D2>{

$device_type =3D 'Symbol RF =
device';

}

size=3D2>elsif( $mac_address =3D~ /001795/g )

size=3D2>{

$device_type =3D 'Cisco Systems =
AP';

}

size=3D2>}

my %device =3D (); =

$device{PORT} =3D "@{$ifnames{ =
$portIndexes->[$r]->[2]} }";

size=3D2>$device{MAC} =3D $mac_address;

size=3D2>$device{IP} =3D $ip;

size=3D2>$device{DEVICE} =3D $dns_name;

size=3D2>$device{TYPE} =3D $device_type;

size=3D2>push( @data, \%device );

size=3D2>}

size=3D2>}

}

size=3D2>}

return \@data;

size=3D2>}

sub getName {

size=3D2>my $ip_address =3D shift(@_);

my( =
$nbQuery, $nbStatus, $DNS, $packed_binary_address );

size=3D2>

$packed_binary_address =3D =
inet_aton( $ip_address);

$DNS =3D =
gethostbyaddr( $packed_binary_address, AF_INET );

size=3D2>if( !$DNS ) {

$nbQuery =3D =
Net::NBName->new;

$nbStatus =3D =
$nbQuery->node_status( $ip_address );

if( =
defined $nbStatus )

{

size=3D2>$DNS =3D =
$nbStatus->{names}->[0]->{name};

size=3D2>}

if( !$DNS ) { $DNS =3D 'unknown' =
}

}

return =
$DNS;

}

sub =
getDeviceType {

my $address =3D shift( @_ =
);

my ( $type, $rtt, $tcp_print, $addr, =
$host);

size=3D2>$tcp_print =3D Net::Ping->new("syn");

size=3D2>$tcp_print->{port_num} =3D "9100";

size=3D2>$tcp_print->service_check( 1 );

size=3D2>$tcp_print->ping( $address );

size=3D2>if( ( $host, $rtt, $addr ) =3D $tcp_print->ack =
)

{

$type =3D =
"Printer";

}

size=3D2>else{

$tcp_print =3D =
Net::Ping->new("syn");

size=3D2>$tcp_print->{port_num} =3D "4500";

size=3D2>$tcp_print->service_check( 1 );

size=3D2>$tcp_print->ping( $address );

size=3D2>if( ( $host, $rtt, $addr ) =3D $tcp_print->ack =
)

{

$type =3D =
"Controller"

}

size=3D2>}

return $type;

size=3D2>}

1;


Mitchell Raful MCSE CCNP
face=3DArial=20
size=3D2>MCB Quantico

Personal =
and Family=20
Readiness (MRI)

3044 Catlin =
Avenue
=20

Quantico, VA 22134
face=3DArial=20
size=3D2>Com: 703-784-5991

DSN: =
278-5991
=20

Cell: 804-363-0731


 


------_=_NextPart_001_01C856B2.FC34841D--

Re: Printing for debugging

am 14.01.2008 17:08:09 von Colin Wetherbee

Raful Mr Mitchell H wrote:
> I have my code pasted below. My module, loaded with
> directive in Apache2, works well. However, sometimes switches don't
> respond correctly to bulk queries of fdbPorts object. What I want to do
> is to be able print the value of my variables either to the browser or a
> log file. A regular print statement does not work for this. The
> relevant variables are in a subroutine called from my sub handler.

I'm not entirely sure where, in those lines of unindented HTML, you're
trying to perform your logging. The only thing I could find quickly was
the following code, but I can't be certain that's the subject of your
question.

if( $arp_session->{ErrorNum} ){ print "Got $arp_session->{ErrorStr} for
$router\n"; }

In order to print log messages to Apache's (or your virtual host's)
error log, you can use the following.

use Apache2::RequestUtil;
use Apache2::Log;

Apache2::RequestUtil->request->log->error('some_text');

Substituting other log levels (debug, info, warn, etc.) works, as well.
See the following URL for more information.

http://perl.apache.org/docs/2.0/api/Apache2/Log.html#LogLeve l_Methods

If this isn't what you're seeking, perhaps you could include a more
concise test case and a more elaborate explanation in your next post?

Colin

RE: Printing for debugging

am 14.01.2008 19:53:27 von Raful Mr Mitchell H

VGhhbmtzISAgVXNpbmcgdGhlIEFwYWNoZTI6OlJlcXVlc3RVdGlsIGFuZCBB cGFjaGUyOjpMb2cs
IEkgY2FuIGZpbmQgb3V0IHdoYXQgbXkgdmFyaWFibGVzJyB2YWx1ZXMgYXJl IHRvIGRlYnVnIGFu
ZCBjaGVjayBteSBjb2RlLg0KDQpNaXRjaA0KDQoNCg0KTWl0Y2hlbGwgUmFm dWwgTUNTRSBDQ05Q
DQpNQ0IgUXVhbnRpY28NClBlcnNvbmFsIGFuZCBGYW1pbHkgUmVhZGluZXNz IChNUkkpDQozMDQ0
IENhdGxpbiBBdmVudWUNClF1YW50aWNvLCBWQSAyMjEzNA0KQ29tOiA3MDMt Nzg0LTU5OTENCkRT
TjogMjc4LTU5OTENCkNlbGw6IDgwNC0zNjMtMDczMQ0KDQoNCi0tLS0tT3Jp Z2luYWwgTWVzc2Fn
ZS0tLS0tDQpGcm9tOiBDb2xpbiBXZXRoZXJiZWUgW21haWx0bzpjd3dAZGVu dGVycHJpc2VzLm9y
Z10NClNlbnQ6IE1vbmRheSwgSmFudWFyeSAxNCwgMjAwOCAxMTowOCBBTQ0K VG86IFJhZnVsIE1y
IE1pdGNoZWxsIEgNCkNjOiBNb2RwZXJsIChFLW1haWwpDQpTdWJqZWN0OiBS ZTogUHJpbnRpbmcg
Zm9yIGRlYnVnZ2luZw0KDQoNClJhZnVsIE1yIE1pdGNoZWxsIEggd3JvdGU6 DQo+IEkgaGF2ZSBt
eSBjb2RlIHBhc3RlZCBiZWxvdy4gIE15IG1vZHVsZSwgbG9hZGVkIHdpdGgg PExvY2F0aW9uPiAN
Cj4gZGlyZWN0aXZlIGluIEFwYWNoZTIsIHdvcmtzIHdlbGwuICBIb3dldmVy LCBzb21ldGltZXMg
c3dpdGNoZXMgZG9uJ3QgDQo+IHJlc3BvbmQgY29ycmVjdGx5IHRvIGJ1bGsg cXVlcmllcyBvZiBm
ZGJQb3J0cyBvYmplY3QuICBXaGF0IEkgd2FudCB0byBkbyANCj4gaXMgdG8g YmUgYWJsZSBwcmlu
dCB0aGUgdmFsdWUgb2YgbXkgdmFyaWFibGVzIGVpdGhlciB0byB0aGUgYnJv d3NlciBvciBhIA0K
PiBsb2cgZmlsZS4gIEEgcmVndWxhciBwcmludCBzdGF0ZW1lbnQgZG9lcyBu b3Qgd29yayBmb3Ig
dGhpcy4gIFRoZSANCj4gcmVsZXZhbnQgdmFyaWFibGVzIGFyZSBpbiBhIHN1 YnJvdXRpbmUgY2Fs
bGVkIGZyb20gbXkgc3ViIGhhbmRsZXIuDQoNCkknbSBub3QgZW50aXJlbHkg c3VyZSB3aGVyZSwg
aW4gdGhvc2UgbGluZXMgb2YgdW5pbmRlbnRlZCBIVE1MLCB5b3UncmUgDQp0 cnlpbmcgdG8gcGVy
Zm9ybSB5b3VyIGxvZ2dpbmcuICBUaGUgb25seSB0aGluZyBJIGNvdWxkIGZp bmQgcXVpY2tseSB3
YXMgDQp0aGUgZm9sbG93aW5nIGNvZGUsIGJ1dCBJIGNhbid0IGJlIGNlcnRh aW4gdGhhdCdzIHRo
ZSBzdWJqZWN0IG9mIHlvdXIgDQpxdWVzdGlvbi4NCg0KaWYoICRhcnBfc2Vz c2lvbi0+e0Vycm9y
TnVtfSApeyBwcmludCAiR290ICRhcnBfc2Vzc2lvbi0+e0Vycm9yU3RyfSBm b3IgDQokcm91dGVy
XG4iOyB9DQoNCkluIG9yZGVyIHRvIHByaW50IGxvZyBtZXNzYWdlcyB0byBB cGFjaGUncyAob3Ig
eW91ciB2aXJ0dWFsIGhvc3QncykgDQplcnJvciBsb2csIHlvdSBjYW4gdXNl IHRoZSBmb2xsb3dp
bmcuDQoNCnVzZSBBcGFjaGUyOjpSZXF1ZXN0VXRpbDsNCnVzZSBBcGFjaGUy OjpMb2c7DQoNCkFw
YWNoZTI6OlJlcXVlc3RVdGlsLT5yZXF1ZXN0LT5sb2ctPmVycm9yKCdzb21l X3RleHQnKTsNCg0K
U3Vic3RpdHV0aW5nIG90aGVyIGxvZyBsZXZlbHMgKGRlYnVnLCBpbmZvLCB3 YXJuLCBldGMuKSB3
b3JrcywgYXMgd2VsbC4gDQogIFNlZSB0aGUgZm9sbG93aW5nIFVSTCBmb3Ig bW9yZSBpbmZvcm1h
dGlvbi4NCg0KaHR0cDovL3BlcmwuYXBhY2hlLm9yZy9kb2NzLzIuMC9hcGkv QXBhY2hlMi9Mb2cu
aHRtbCNMb2dMZXZlbF9NZXRob2RzDQoNCklmIHRoaXMgaXNuJ3Qgd2hhdCB5 b3UncmUgc2Vla2lu
ZywgcGVyaGFwcyB5b3UgY291bGQgaW5jbHVkZSBhIG1vcmUgDQpjb25jaXNl IHRlc3QgY2FzZSBh
bmQgYSBtb3JlIGVsYWJvcmF0ZSBleHBsYW5hdGlvbiBpbiB5b3VyIG5leHQg cG9zdD8NCg0KQ29s
aW4NCg0K