my
$prompt
=
qr/ [\$#] +$/
;
my
$more_pattern
=
qr/--More--/
;
my
$timeout
= 10;
sub
get_paginated_output {
my
(
$command
,
$expect
) =
@_
;
my
$more_flag
= 0;
my
@lines
=
undef
;
my
@alllines
=
undef
;
$expect
->
send
(
$command
.
"\n"
);
while
(1) {
my
(
$pos
,
$error
,
$match
,
$before
,
$after
) =
$expect
->expect(
$timeout
, -re,
$prompt
, -re,
$more_pattern
);
if
(
$match
) {
if
(
$match
=~
$more_pattern
) {
$more_flag
= 1;
@lines
=
split
(/\R/,
$before
);
push
(
@alllines
,
grep
{
$_
=~ /\S/}
@lines
);
debug(
"skipping through --More-- pagination"
);
$expect
->
send
(
" "
);
}
elsif
(
$match
=~
$prompt
) {
$more_flag
= 0;
@lines
=
split
(/\R/,
$before
);
push
(
@alllines
,
grep
{
$_
=~ /\S/}
@lines
);
foreach
my
$line
(
@alllines
) {
debug(
"output collected: $line"
)
if
$line
;
}
last
;
}
}
}
return
@alllines
;
}
sub
arpnip_context {
my
(
$expect
,
$prompt
,
$timeout
,
$arpentries
) =
@_
;
my
@data
= get_paginated_output(
"get system arp"
,
$expect
);
my
$re_ipv4_arp
=
qr/^($RE{net}{IPv4})\s*\d+\s*($RE{net}{MAC})\s*\S+$/
;
foreach
(
@data
) {
if
(
$_
&& /
$re_ipv4_arp
/) {
debug
"\tfound IPv4: $1 => MAC: $2"
;
push
(
@$arpentries
, {
ip
=> $1,
mac
=> $2 });
}
}
@data
= get_paginated_output(
"diagnose ipv6 neighbor-cache list"
,
$expect
);
my
$re_ipv6_arp
=
qr/^ifindex=\d+\s+ifname=\S+\s+($RE{net}{IPv6}{-sep => ':'}{-style => 'HeX'})\s+($RE{net}{MAC}).*$/
;
foreach
(
@data
) {
if
(
$_
&& /
$re_ipv6_arp
/) {
debug
"\tfound IPv6: $1 => MAC: $2"
;
push
(
@$arpentries
, {
ip
=> $1,
mac
=> $2 });
}
}
}
sub
arpnip {
my
(
$self
,
$hostlabel
,
$ssh
,
$args
) =
@_
;
debug
"$hostlabel $$ arpnip()"
;
my
(
$pty
,
$pid
) =
$ssh
->open2pty;
unless
(
$pty
) {
warn
"unable to run remote command [$hostlabel] "
.
$ssh
->error;
return
();
}
$Expect::Debug
= 0;
$Expect::Exp_Internal
= 0;
my
$expect
= Expect->init(
$pty
);
$expect
->raw_pty(1);
my
(
$pos
,
$error
,
$match
,
$before
,
$after
);
if
(
$args
->{banner}) {
my
$banner
=
qr/^\(Press 'a' to accept\):/
;
(
$pos
,
$error
,
$match
,
$before
,
$after
) =
$expect
->expect(
$timeout
, -re,
$banner
);
$expect
->
send
(
"a"
);
}
(
$pos
,
$error
,
$match
,
$before
,
$after
) =
$expect
->expect(
$timeout
, -re,
$prompt
);
my
@data
= get_paginated_output(
"get system status"
,
$expect
);
my
$multi_vdom
= 0;
foreach
(
@data
) {
if
(
$_
&& /^Virtual domain configuration: (multiple|
split
-task)$/) {
$multi_vdom
= 1;
last
;
}
}
my
$arpentries
= [];
if
(
$multi_vdom
) {
$expect
->
send
(
"config global\n"
);
$expect
->expect(
$timeout
, -re,
$prompt
);
my
@data
= get_paginated_output(
"get system vdom-property"
,
$expect
);
my
$vdoms
= [];
foreach
(
@data
) {
push
(
@$vdoms
, $1)
if
$_
&& (/^==\s*\[\s*(\S+)\s*\]$/);
}
$expect
->
send
(
"end\n"
);
$expect
->expect(
$timeout
, -re,
$prompt
);
foreach
(
@$vdoms
) {
$expect
->
send
(
"config vdom\n"
);
$expect
->expect(
$timeout
, -re,
$prompt
);
$expect
->
send
(
"edit $_\n"
);
debug (
"switched to config vdom; edit $_"
);
$expect
->expect(
$timeout
, -re,
$prompt
);
arpnip_context(
$expect
,
$prompt
,
$timeout
,
$arpentries
);
$expect
->
send
(
"end\n"
);
$expect
->expect(
$timeout
, -re,
$prompt
);
}
}
else
{
arpnip_context(
$expect
,
$prompt
,
$timeout
,
$arpentries
);
}
$expect
->
send
(
"exit\n"
);
$expect
->soft_close();
return
@$arpentries
;
}
1;