tail-f-systems / JNC

JNC (Java NETCONF Client) is the name of a Java library for communicating with NETCONF agents, and a plugin for pyang (http://code.google.com/p/pyang/) to generate Java classes from YANG models, to be used by the JNC library.
Other
77 stars 87 forks source link

Failure to negotiate netconf hello with Cisco CSR1000V - missing xml version #38

Closed abligh closed 9 years ago

abligh commented 9 years ago

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?

abligh commented 9 years ago

With this patch:

diff --git a/jnc/src/com/tailf/jnc/NetconfSession.java b/jnc/src/com/tailf/jnc/NetconfSession.java
index 0d25abe..60a4124 100644
--- a/jnc/src/com/tailf/jnc/NetconfSession.java
+++ b/jnc/src/com/tailf/jnc/NetconfSession.java
@@ -1559,6 +1559,7 @@ public class NetconfSession {
      * side are the base NETCONF capability.
      */
     void encode_hello(Transport out) {
+       out.print("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
         out.print("<hello xmlns=\"" + Capabilities.NS_NETCONF + "\">");
         out.print("<capabilities>");
         out.println("<capability>" + Capabilities.NETCONF_BASE_CAPABILITY

It will negotiate a hello.

However, it then dies as follows:

*NetconfSession: reply= 
<?xml version="1.0" encoding="UTF-8"?><rpc-reply xmlns="urn:ietf:params:netconf:base:1.0"><rpc-error><error-type>rpc</error-type><error-tag>missing-element</error-tag><error-severity>error</error-severity><error-info><bad-element>xml</bad-element></error-info></rpc-error></rpc-reply>
[Fatal Error] :2:6: The processing instruction target matching "[xX][mM][lL]" is not allowed.
Exception in thread "main" Parse error: parse error: org.xml.sax.SAXParseException: The processing instruction target matching "[xX][mM][lL]" is not allowed.
    at com.tailf.jnc.XMLParser.parse(XMLParser.java:139)
    at com.tailf.jnc.XMLParser.parse(XMLParser.java:154)
    at com.tailf.jnc.NetconfSession.recv_rpc_reply(NetconfSession.java:1483)
    at com.tailf.jnc.NetconfSession.recv_rpc_reply_data(NetconfSession.java:1460)
    at com.tailf.jnc.NetconfSession.getConfig(NetconfSession.java:443)
    at com.tailf.jnc.NetconfSession.getConfig(NetconfSession.java:433)
    at testnetconf.TestNetconf.main(TestNetconf.java:46)

It looks like JNC really neither wants to send or receive <?xml ... ?> but the Cisco insists on it. Who is right here?

abligh commented 9 years ago

Apparently both JNC and the Cisco are broken.

From RFC 6241 section 3:

A NETCONF message MAY begin with an XML declaration (see Section 2.8 of [W3C.REC-xml-20001006]).

MAY in RFC terms means this is optional. The Cisco is therefore at fault for requiring it on Netconf commands received. JNC is also at fault in refusing to accept responses containing it.

klacke commented 9 years ago

The Cisco CSR1000v doesn't have a working netconf impl. that can be used. No need to pursue that ...

/klacke

On 16/11/14 23:00, Alex Bligh wrote:

Apparently both JNC and the Cisco are broken.

From RFC 6241 section 3:

A NETCONF message MAY begin with an XML declaration (see Section 2.8
of [W3C.REC-xml-20001006]).

|MAY| in RFC terms means this is optional. The Cisco is therefore at fault for requiring it on Netconf commands received. JNC is also at fault in refusing to accept responses containing it.

— Reply to this email directly or view it on GitHub https://github.com/tail-f-systems/JNC/issues/38#issuecomment-63241659.

t-anh commented 9 years ago

Dear @klacke
can you give me the document which describe "The Cisco CSR1000v doesn't have a working netconf impl." Thanks

klacke commented 9 years ago

Don't have such a doc, I just know this. XR has working netconf by now, not IOS.

They have something, but it's not NETCONF, just NETCONFish.

/klacke

On 03/12/14 01:09, t-anh wrote:

Dear @klacke https://github.com/klacke

can you give me the document which describe "The Cisco CSR1000v doesn't have a working netconf impl." Thanks

— Reply to this email directly or view it on GitHub https://github.com/tail-f-systems/JNC/issues/38#issuecomment-65375535.

t-anh commented 9 years ago

Now I'm using Cisco CSR 1000v 3.11s, and it support NETCONF.

SaidJunior commented 9 years ago

Hello ,

Can i have the whole list on devices that support NETCONF ?

thank you

2014-12-04 11:10 GMT+01:00 t-anh notifications@github.com:

Now I'm using Cisco CSR 1000v 3.11s, and it support NETCONF.

— Reply to this email directly or view it on GitHub https://github.com/tail-f-systems/JNC/issues/38#issuecomment-65606574.

[image: UBIqube Solutions] http://www.ubiqube.com

Said MALAH / R&D Apprentice Enginner +33 (0)7 53 65 01 75/ sma@ubiqube.com

UBIqube Solutions Office: +33 438 498 364 / Fax: +33 438 498 361 Parc Sud Galaxie 5, rue des Tropiques 38130 Échirolles France www.ubiqube.com

[image: Facebook] http://www.facebook.com/saiid.junior [image: Twitter] http://www.twitter.com/Saiid.juni0r [image: Instagram] http://instagram.com/Said_Malah [image: Skype] http://skype.com/SAID+MALAH

abligh commented 9 years ago

t-anh: I opened this issue precisely because neither Cisco CSR 1000v (3.12) nor JNC appear to follow the Netconf standard:

Apparently both JNC and the Cisco are broken.

From RFC 6241 section 3:

A NETCONF message MAY begin with an XML declaration (see Section 2.8 of [W3C.REC-xml-20001006]).

MAY in RFC terms means this is optional. The Cisco is therefore at fault for requiring it on Netconf commands received. JNC is also at fault in refusing to accept responses containing it.

klacke commented 9 years ago

I agree that the <?xml header should be both sent and received by JNC. Needs to be fixed.

As for the NETCONF impl on CSR 1000v , maybe you know more than me here, but last time I looked it was completely worthless. You're stumbling on the <?xml header, if you were to get pass that, the list of anomalies continues forever. Furthermore, the payload was just CLI commands wrapped in garbled XML. The CSR 1000v NETCONF is probably just there to fill a tickmark in some RFQ.