Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Teldat support #166

Open
nicolatron opened this issue Feb 1, 2022 · 5 comments
Open

Teldat support #166

nicolatron opened this issue Feb 1, 2022 · 5 comments

Comments

@nicolatron
Copy link
Contributor

nicolatron commented Feb 1, 2022

This is a plea for help, not an issue with netdot.

I'm trying to improve functionalities with Teldat routers.

As for SNMP teldat routers give interface information and most things quite nicely. But ip/mask information is missing, to obtain it for vrfs you need to use different communities/contexts, and this also give you access to a subset of the snmp trees with only ip/mask information for the interfaces present in relevant VRF. So I cannot just add each vrf as separate devices becouse snmp_info will fail (no descr etc). Also I counln't found a OID to retrieve the configured VRFs from the "general" no-VRF device either (so i could somehow walk the information on the different VRFs). So I gave up on the SNMP approach.

I'm trying to use the CLI for getting ARP and FWT, to prior add there a function to extract the ip/mask information and populate it in netdot database for that device, then get arp and fwt data for the now ip-enabled interfaces).

Maybe this could be made with something like it is done on Aironet.pm but to me all that is SNMP-based, so with my limited knowledge I'd thought to append my modifications on a Device/CLI/teldat.pm script.

As I'm making slow progess, now I'm stuck becouse as part of the Teldat privilege de-escalation i need to send CONTROL-P and I don't know how to do it.

Explanation:
Teldat has 4 different privilege levels with different commands.
Witch an example of a teldat session after just entering the generic un-privileged prompt:

ADM020 *p 4


ADM020 Config>feature vrf

-- VRF user configuration --
ADM020 VRF config>show config
; Showing Menu and Submenus Configuration for access-level 15 ...
; ATLAS60Router  PMC 28 65 Version 11.01.00.20.24

      vrf VoIP
      vrf VPN_ADM
ADM020 VRF config> 

****HERE YOU NEED TO SEND Control-p to get back to generic prompt and change privelege level to issue different commands


ADM020 *p 3
Console Operator

[...]

My question is I guess about Net::CLI::Interact probably, how can I send control characters?.
I've tried with several variances of:

    $s->cmd('\xa');
    $s->cmd('\x0a');
    $s->cmd('\\x0a');
    $s->cmd('\\\x0a'); #yes, i know
    $s->cmd('\010);
    $s->cmd('\cP');
    $s->cmd('^p');

but does not work. always get something like:

[   0.854830] du   SEEN:
\xa
CLI Error: Command error
ADM020 Config>

Edit: Found the solution to this, just needed to use " instead of '.
$s->cmd("\cP");
Does work. :-)

Also, is there an easy way to use phrasebook macros from Netdot CLI implementation?. If not... how can I change the prompt after changing a privilege level?.
ie:
$self->_cli_cmd(%$args, host=>$host, cmd=>'p 4', personality=>'teldat');
will change the prompt from generic to Config. But netdot keeps trying to match generic prompt, which fails.

I've done tests using Net::Appliance::Session directly and I'm doing this using:
$s->macro('begin_pfour');

And on teldat/pb

prompt generic
    match /[\/a-zA-Z0-9._\[\]-]+ \* ?$/

prompt pfour
    match /[Cc]onfig> ?$/

prompt pthree
    match /[\/a-zA-Z0-9._\[\]-]+ \+ ?$/

prompt privileged
    match /# ?$/

prompt configure
    match /Config> ?$/

prompt user
    match /[Uu]sername: ?$/

prompt pass
    match /[Pp]assword: ?$/

macro paging
    send  
    match generic

macro begin_pfour
    send p 4
    match pfour

macro begin_pthree
    send p 3
    match pthree

macro endp
    send ^p
    match generic

macro disconnect
    send logout
    follow /Do you wish to end connection \(Yes\/No\)\?/ with Yes\n

But without access to macros I don't know how to make my code aware of the prompt change.

About this I'm thinking about modifying CLI.pm either adding a new parameter $macro to _cli_cmd or maybe adding a new sub _cli_macro(), what do you think?.

Edit: I've make test adding $macro parameter to _cli_cmd and doing this (if $macro is present $cmd is ignored):

        if ($macro) {
            $logger->debug(sub{"$host: issuing CLI macro: '$macro' over $transport"});
            @output = $s->macro($macro, {timeout=>$timeout});
            $s->close();
        }

So far it seems to be working, and not breaking anything but will need more testing.

My work in progess is in my own netdot fork , which contains a fork of latest cvicente repo + a merge of latest vink78 repo (to include PaloAlto API which I use). My changes include CLI supoprt for some more devices and my current tries at teldat, all of which I don't see ready for a pull request.

Thank you very much.

@mzagrabe
Copy link
Contributor

mzagrabe commented Feb 1, 2022 via email

@nicolatron nicolatron reopened this Feb 2, 2022
@nicolatron
Copy link
Contributor Author

nicolatron commented Feb 2, 2022

Thank you Brian and mzgrave for the help. I closed this too fast.

Now I can send control-p using $s->cmd("\cP") just fine, problem is I cannot send it from macros.
Using this macro has the same effect ans using $s->cmd('\cP')

macro disconnect
    send \cP
    send logout
    follow /Do you wish to end connection \(Yes\/No\)\?/ with Yes\n

Error being:

[   0.854116] du   SEEN:
\cP
CLI Error: Command error

Just noticed yesterday that _cli_cmd is a "one line" command, handles change of privilege if needed, but every call to the function opens and closes Net::Appliance::Session session, so every call to it is atomic and unrelated to the last one.

To talk to teldat this doesn't suit my needs, as it needs several commands to get for example ip address.

I've made some modifications to _cli_cmd, to alllow the execution of custom macros and to be able to pass parameter (one for now) to that macros, with that I can make more or less complex macros to get to the point where i can execute my commands. Like for example:

my @output = $self->_cli_cmd(%$args, host=>$host, cmd=>'interface-addresses', macro=>'get_ip_vrf', personality=>'teldat', macro_param=>$line);

macro get_ip_vrf
    send p 3
    match p3
    send protocol ip
    match p3
    send vrf %s
    match p3

Just commited the new code to my repo on teldat branch.

@nicolatron
Copy link
Contributor Author

nicolatron commented Feb 4, 2022

I've make it to the point where I can add the ip information to the interfaces and get the relevant networks created using the update_ip function in Interface.pm.
What update_ip seems not to provide is a way to assing the created subnet to a given site (in my case the same site where the device resides). I'm looking for a way to assign the subnet to the site afterwards, but cannot find a function/method like Ipblock->add_site or Site->assing_ipblock or something similar, anyone knows where does this kind of functionality reside?.
I know the underneath database relation on sitesubnet table, but hope there was an already coded way to do it... somewhere.
Also... is there a way to get to the IP assigned to an interface from the interface itself?.
In ipblock table there's a device field, but on interface table there's no ipblock field, there is a physaddr I could start looking from there.

@nicolatron
Copy link
Contributor Author

nicolatron commented Feb 10, 2022

Solved the mac to IP thing with:

       if ( my $phy = PhysAddr->search(address=>$ethernet)->first ) {
           my (@arp) = $phy->get_last_n_arp(1);
           my $ipb = Ipblock->retrieve($arp[0][0][1]);
           $address = $ipb->full_address;
          }

What still drives me crazy is how to enter a new sitesubnet relation.
Or thigs like (where $dev is a instance of Netdot::Model::Device) $dev->interfaces beign used everywhere but there is no interfaces method defined in Device.pm or any other place I could fine, it seems to me after many tinkering that it is some kind of DBI abstraction probably related with the definitions on etc/netdot.meta that maps data on database to objects atributes. But still trying to figure it out.

In Ipblock.pm:search_like there are some references to site to subnet mapping but I cannot guess how to manipulate them from that code...

    # Use the SiteSubnet relationship if available
    map { $blocks{$_->subnet} = $_->subnet } map { $_->subnets } @sites; 
    
    # Add the entities related to the sites matching the criteria
    map { push @ents, $_->entity } map { $_->entities } @sites; 
    # Get the Ipblocks related to those entities
    map { $blocks{$_} = $_ } 
    map { $_->used_blocks, $_->owned_blocks } @ents;

Any help or pointers to documentation explaining how that parts works appreciated.

@nicolatron
Copy link
Contributor Author

For those walking on my shoes, it seems that "hidden" methods corresponds to the DBI abstraction and how it converts data from the database into objects. Relations are defined on etc/netdot.meta
More information on how it all works on https://metacpan.org/pod/Class::DBI
For my adding to sitesubnet needs, this code will suffice, it yields errors if relation already exists, but will check beforehand if it exists and that'll suffice for my needs.
$newsubnet->add_to_sites({ site => $dev->site->id, subnet => $newsubnet->id,});

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants