I'm trying to negotiate a trivial hello with a Cisco CSR1000V. I can do this by manually pasting things to the SSH command line, so I know the router is working.
The cisco is running:
Cisco IOS XE Software, Version 03.12.00.S - Standard Support Release
Cisco IOS Software, CSR1000V Software (X86_64_LINUX_IOSD-UNIVERSALK9-M), Version 15.4(2)S, RELEASE SOFTWARE (fc2)
Technical Support: http://www.cisco.com/techsupport
Copyright (c) 1986-2014 by Cisco Systems, Inc.
Compiled Wed 26-Mar-14 21:09 by mcpre
Here's my program:
public class TestNetconf {
public static void main(String[] args) throws IOException, JNCException {
Element.setDebugLevel(99);
String emsUserName = "bobby";
String ip = "localhost";
DeviceUser duser = new DeviceUser(emsUserName, "[removed]", "[removed]");
Device dev = new Device("mydev", duser, "10.10.10.10", 22);
try {
dev.connect(emsUserName);
dev.newSession("cfg");
} catch (IOException e) {
System.err.println(e);
System.exit(1);
} catch (JNCException e) {
System.err.println("Can't authenticate " + e);
System.exit(1);
}
}
}
Debug output looks like this:
*NetconfSession: hello:
*Path: tokenize() -> TokenList[ATOM(self),COLONCOLON,ATOM(hello),SLASH,ATOM(capabilities)]
*Path: parse(): TokenList[ATOM(self),COLONCOLON,ATOM(hello),SLASH,ATOM(capabilities)]
*Path: parsePredicates(): TokenList[SLASH,ATOM(capabilities)]
*Path: parse(): TokenList[ATOM(capabilities)]
*Path: parsePredicates(): TokenList[]
*Path: parse() -> [LocationStep{AXIS_SELF,name=hello}, LocationStep{AXIS_CHILD,name=capabilities}]
*Path: eval(): Path[LocationStep{AXIS_SELF,name=hello}LocationStep{AXIS_CHILD,name=capabilities}]
*NetconfSession: capabilities:
<capabilities>
<capability>urn:ietf:params:netconf:base:1.0</capability>
<capability>urn:ietf:params:netconf:capability:writeable-running:1.0</capability>
<capability>urn:ietf:params:netconf:capability:startup:1.0</capability>
<capability>urn:ietf:params:netconf:capability:url:1.0</capability>
<capability>urn:cisco:params:netconf:capability:pi-data-model:1.0</capability>
<capability>urn:cisco:params:netconf:capability:notification:1.0</capability>
</capabilities>
*Path: tokenize() -> TokenList[ATOM(capability)]
*Path: parse(): TokenList[ATOM(capability)]
*Path: parsePredicates(): TokenList[]
*Path: parse() -> [LocationStep{AXIS_CHILD,name=capability}]
*Path: eval(): Path[LocationStep{AXIS_CHILD,name=capability}]
*Path: tokenize() -> TokenList[ATOM(self),COLONCOLON,ATOM(hello),SLASH,ATOM(session-id)]
*Path: parse(): TokenList[ATOM(self),COLONCOLON,ATOM(hello),SLASH,ATOM(session-id)]
*Path: parsePredicates(): TokenList[SLASH,ATOM(session-id)]
*Path: parse(): TokenList[ATOM(session-id)]
*Path: parsePredicates(): TokenList[]
*Path: parse() -> [LocationStep{AXIS_SELF,name=hello}, LocationStep{AXIS_CHILD,name=session-id}]
*Path: eval(): Path[LocationStep{AXIS_SELF,name=hello}LocationStep{AXIS_CHILD,name=session-id}]
*NetconfSession: sessionId = 1398563696
What I see on the Cisco with all debugging turned on is:
*Nov 16 18:11:23.701: GSI: netconf app _s_ssh.[0x7F19AC2DBE70]: new ssh connection from 10.1.17.78
*Nov 16 18:11:23.703: NETCONF: ns_clone.sess=0x7F19535C6670
*Nov 16 18:11:23.704: NETCONF: naap_accept.clone=0x7F19535C6670
*Nov 16 18:11:23.704: NETCONF: _nssd.33.snd.now<?xml version="1.0" encoding="UTF-8"?><hello><capabilities><capability>urn:ietf:params:netconf:base:1.0</capability><capability>urn:ietf:params:netconf:capability:writeable-running:1.0</capability><capability>urn:ietf:params:netconf:capability:startup:1.0</capability><capability>urn:ietf:params:netconf:capability:url:1.0</capability><capability>urn:cisco:params:netconf:capability:pi-data-model:1.0</capability><capability>urn:cisco:params:netconf:capability:notification:1.0</capability></capabilities><session-id>1398564464</session-id></hello>
*Nov 16 18:11:23.704: NETCONF: _nssd.33.snd.don=7F19535C6670 msg=7F19535C7E70
*Nov 16 18:11:23.704: NETCONF: ne_send.sess=0x7F19535C6670
*Nov 16 18:11:23.792: GSI: netconf app _s_ssh.[0x7F19598F5EA8]: <hello xmlns="urn:ietf:params:xml:ns:netconf:base:1.0"><capabilities><capability>urn:ietf:params:netconf:base:1.0</capability>
</capabilities>
</hello>
*Nov 16 18:11:23.792: NETCONF: _namn.30.mlc.don=7F1953518790
*Nov 16 18:11:23.792: NETCONF: _narc.30.rcv.ok=7F19535C6670
*Nov 16 18:11:23.792: NETCONF: netconf_xml_interpret.30.msg_len=151 bytes
*Nov 16 18:11:23.792: NETCONF: netconf_xml_interpret.30.failure<hello xmlns="urn:ietf:params:xml:ns:netconf:base:1.0"><capabilities><capability>urn:ietf:params:netconf:base:1.0</capability>
</capabilities>
</hello>
*Nov 16 18:11:23.792: NETCONF-ERROR: parse error before hello seen
*Nov 16 18:11:23.792: NETCONF: ns_stop.gsi_destroy.delayed
*Nov 16 18:11:23.792: NETCONF: netconf_execute_message.30.nre_type=2
*Nov 16 18:11:23.792: NETCONF: _nmfr.30.now=7F1953358EF0
*Nov 16 18:11:23.792: NETCONF: _nefrp.now=7F1953358EF0
*Nov 16 18:11:24.149: NETCONF: ns_destroy.sess=0x7F19535C6670
The line starting:
Nov 16 18:11:23.792: GSI: netconf app _s_ssh.[0x7F19598F5EA8]: <hello
is the hello
JNC is sending to the Cisco. It doesn't like it for some reason. Formatted, the hello
that JNC is sending (retrieved from the debug logs and formatted) looks like:
<hello xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
<capabilities>
<capability>urn:ietf:params:netconf:base:1.0</capability>
</capabilities>
</hello>
If I send the above hello
(manually via command line ssh using ssh -s 10.10.10.10 netconf
), I get the same error.
If, however, I send the following hello
manually (with an additional xml version
statement), it appears to connect and I can do other things like list the config.
<?xml version="1.0"?>
<hello xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
<capabilities>
<capability>urn:ietf:params:netconf:base:1.0</capability>
</capabilities>
</hello>
It would thus appear the Cisco is expecting, but not receiving, the xml version
line.
Any ideas?