Confd_notification_send error "Malformed XML"

Hi,

we are working with external DB and have other user interfaces beside confd.
When the DB is changed as a result of configuration rather then confd, we should send a notification to the netconf client. we do that using confd_notification_send.

When we call confd_notification_send, we receive CONFD_OK.
But when I check the confd_devel.log I see the folloing:
" 23-Apr-2017::10:17:30.169 isim_Host1 confd[7165]: devel-c Failed to send notification for stream NETCONF: Malformed XML".

How can I know what is the problem? can I see the full XML or get more details somehow?

I attach below the relevant code.

thanks in advance
Inbal

… (maapi_connect…)
if (maapi_xpath2kpath(MappiSocket, “/interfaces/interface”, &p_KeyPath) != CONFD_OK) //translate the keypath
{
DEBUG(netConfTraceP, << “Cannot translate xpath\n”);
}
maapi_close(MappiSocket);

CONFD_SET_TAG_XMLBEGIN(&values[i],   ncn_netconf_config_change, ncn__ns);  i++;
CONFD_SET_TAG_XMLBEGIN(&values[i],   ncn_changed_by,            ncn__ns);  i++;
CONFD_SET_TAG_STR(&values[i],        ncn_username,              "Admin");  i++;
CONFD_SET_TAG_UINT32(&values[i],     ncn_session_id,            0);        i++;
CONFD_SET_TAG_IPV4(&values[i],       ncn_source_host,           an_addr);  i++;
CONFD_SET_TAG_XMLEND(&values[i],     ncn_changed_by,            ncn__ns);  i++;
CONFD_SET_TAG_ENUM_VALUE(&values[i], ncn_datastore,             ncn_running); i++;
CONFD_SET_TAG_XMLBEGIN(&values[i],   ncn_edit,                  ncn__ns);  i++;
CONFD_SET_TAG_OBJECTREF(&values[i],  ncn_target,                p_KeyPath);i++;
CONFD_SET_TAG_XMLEND(&values[i],     ncn_edit,                  ncn__ns);  i++;
CONFD_SET_TAG_XMLEND(&values[i],     ncn_netconf_config_change, ncn__ns);  i++;

You don’t show enough of the code or the data model for me to be able to say for sure what the issue is. If you allocate your tagged value array on the stack it could be that it goes out of scope before you call confd_notification_send().

This forum post describe a function, print_modification(), that can be used to print the content of a tagged value array.

If you pass your filled in tagged value array to print_modifications() you should be able to see if the data match what you expect. Or, if there is an error in print_modifications(), get a better understanding of what’s wrong based on how far print_modifications() get.

Thank you for your reply.

I added the print_midification() call just before I call the confd_notification_send() call.
Here is the output:

ConfDAdaptorManager confd_notification_send
(null) begin
(null) begin
username “Admin”
session-id 0
source-host 160.160.160.160
(null) end
datastore enum<0>
(null) begin
target /eci-bgp:bgp/peer-groups/peer-group
(null) end
(null) end
TRACE NOTIFICATION_SEND NETCONF

It seems like sonehow yang ietf-hetconf-notification symbols are not known or not translated right. Is my observation correct?
I tried to add the related .fxs file but I got error in confd startup.

Can you advise how to resolve it ?

thanks in advance
Inbal

As @jjohansson mentioned you seem to have a memory allocation problem with your “values”.

As a reference here’s a quick working hack to send a netconf config change notification:

$ pwd
/Users/tailf/confd-6.3/examples.confd/netconf_notifications
$ diff -u ../netconf_notifications-orig .
diff -u ../netconf_notifications-orig/Makefile ./Makefile
--- ../netconf_notifications-orig/Makefile	2017-04-25 16:15:41.000000000 +0200
+++ ./Makefile	2017-04-25 15:23:59.000000000 +0200
@@ -35,23 +35,26 @@

-all: notifier notifier_builtin_replay_store notif.fxs $(CDB_DIR) ssh-keydir
+all: notifier notifier_builtin_replay_store notif.fxs notifications.fxs ietf-netconf-notifications.h $(CDB_DIR) ssh-keydir
 	@echo "Build complete"
 
+ietf-netconf-notifications.h:
+	$(CONFDC) --emit-h ietf-netconf-notifications.h $(CONFD_DIR)/etc/confd/ietf-netconf-notifications.fxs
+
 notifier: notifier.o
 	 $(CC) notifier.o $(LIBS) $(CFLAGS) -ansi -pedantic -o $@
 
-notifier.o: notifier.c notif.h
+notifier.o: notifier.c notif.h ietf-netconf-notifications.h
 
 notifier_builtin_replay_store: notifier_builtin_replay_store.o
 	 $(CC) notifier_builtin_replay_store.o $(LIBS) $(CFLAGS) -o $@
 
-notifier_builtin_replay_store.o: notifier_builtin_replay_store.c notif.h
+notifier_builtin_replay_store.o: notifier_builtin_replay_store.c notif.h ietf-netconf-notifications.h
 
 %.h: %.fxs
 	$(CONFDC) --emit-h $*.h $<
diff -u ../netconf_notifications-orig/notifier_builtin_replay_store.c ./notifier_builtin_replay_store.c
--- ../netconf_notifications-orig/notifier_builtin_replay_store.c	2017-04-25 16:15:41.000000000 +0200
+++ ./notifier_builtin_replay_store.c	2017-04-25 16:00:30.000000000 +0200
@@ -14,8 +14,10 @@
 
 #include <confd_lib.h>
 #include <confd_dp.h>
+#include <confd_maapi.h>
 
 #include "notif.h"
+#include "ietf-netconf-notifications.h"
 
 #define OK(val) (assert((val) == CONFD_OK))
 
@@ -81,6 +83,55 @@
     OK(confd_notification_send(live_ctx, &eventTime, vals, nvals));
 }
 
+static int maapi_socket(int *msock, struct sockaddr_in *addr)
+{
+  if ((*msock = socket(PF_INET, SOCK_STREAM, 0)) < 0 ) {
+    confd_fatal("failed to create socket");
+    return CONFD_ERR;
+  }
+  if (maapi_connect(*msock, (struct sockaddr*)addr, sizeof (struct sockaddr_in)) < 0) {
+    confd_fatal("failed to connect");
+    return CONFD_ERR;
+  }
+  
+  return CONFD_OK;
+}
+
+static void send_cfg_change(void)
+{
+    confd_tag_value_t vals[11];
+    int i = 0;
+    struct in_addr in;
+    confd_hkeypath_t *kp;
+    int msock;
+    struct sockaddr_in addr;
+
+    addr.sin_addr.s_addr = inet_addr("127.0.0.1");
+    addr.sin_family = AF_INET;
+    addr.sin_port = htons(CONFD_PORT);
+
+    maapi_socket(&msock, &addr);
+    maapi_xpath2kpath(msock, "/interfaces/interface", &kp);
+    close(msock);
+
+    inet_pton(AF_INET, "160.160.160.160", &in);
+
+    CONFD_SET_TAG_XMLBEGIN(&vals[i],   ncn_netconf_config_change, ncn__ns);  i++;
+    CONFD_SET_TAG_XMLBEGIN(&vals[i],   ncn_changed_by,            ncn__ns);      i++;
+    CONFD_SET_TAG_STR(&vals[i],        ncn_username,              "admin");  i++;
+    CONFD_SET_TAG_UINT32(&vals[i],     ncn_session_id,            0);        i++;
+    CONFD_SET_TAG_IPV4(&vals[i],       ncn_source_host,           in);  i++;
+    CONFD_SET_TAG_XMLEND(&vals[i],     ncn_changed_by,            ncn__ns);  i++;
+    CONFD_SET_TAG_ENUM_VALUE(&vals[i], ncn_datastore,             ncn_running); i++;
+    CONFD_SET_TAG_XMLBEGIN(&vals[i],   ncn_edit,                  ncn__ns);  i++;
+    CONFD_SET_TAG_OBJECTREF(&vals[i],  ncn_target,                kp);i++;
+    CONFD_SET_TAG_XMLEND(&vals[i],     ncn_edit,                  ncn__ns);  i++;
+    CONFD_SET_TAG_XMLEND(&vals[i],     ncn_netconf_config_change, ncn__ns);  i++;
+
+    send_notification(vals, i);
+    confd_free_hkeypath(kp);
+}
+
 static void send_notifup_1(int index, int flags1, int flags2)
 {
     confd_tag_value_t vals[9];
@@ -233,7 +284,7 @@
     ncb.fd = workersock;
     ncb.get_log_times = NULL;
     ncb.replay = NULL;
-    strcpy(ncb.streamname, "interface");
+    strcpy(ncb.streamname, "NETCONF");
     ncb.cb_opaque = NULL;
     if (confd_register_notification_stream(dctx, &ncb, &live_ctx) != CONFD_OK) {
         confd_fatal("Couldn't register stream %s\n", ncb.streamname);
@@ -275,6 +326,10 @@
                 if (!read(0, &c, 1))
                     exit(0);
                 switch (c) {
+		case 'n':
+                    printf("sending cfg change\n");
+                    send_cfg_change();
+                    break;
                 case 'u':
                     printf("sending linkUp notification\n");
                     send_notifup_1(1, 2112, 32);

Hi,

Thanks for your help.
I added my relevant code in the end so you can see. the memory allocation is the same as in the sample you wrote.
It seems like the places I get “null” is for ncn__ns (on XML begin and end).
Is it possible that the h file I compiled and the values I use from there is un-recognized by confd?
Is this version already contains the ietf-netconf-notification.fxs? I am asking that since I was unable to add this fxs file to etc directory.

Thanks
Inbal

the code:
void ConfDAdaptorManager::CommitWasDone(int a_TableId)
{

DEBUG(netConfTraceP, <<"ConfDAdaptorManager::CommitWasDone was called for table Id = " << a_TableId);
printf("ConfDAdaptorManager::CommitWasDone was called\n");

confd_tag_value_t values[11];
int i = 0;
confd_hkeypath_t *p_KeyPath;
struct sockaddr_in SocketAddress;
struct in_addr an_addr = {0xa0a0a0a0};

//create socket to translate the keypath
int MappiSocket;
SocketAddress.sin_addr.s_addr = inet_addr("127.0.0.1");
SocketAddress.sin_family = AF_INET;
SocketAddress.sin_port = htons(CONFD_PORT);
printf("ConfDAdaptorManager::CommitWasDone  maapi start\n");

if ((MappiSocket = socket(PF_INET, SOCK_STREAM, 0)) < 0)
{
    DEBUG(netConfTraceP, <<"ConfDAdaptorManager::CommitWasDone socket creation failed " );
}
if (maapi_connect(MappiSocket, (struct sockaddr *)&SocketAddress, sizeof (SocketAddress)) < 0)
{
    DEBUG(netConfTraceP, <<"ConfDAdaptorManager::CommitWasDone socket connect failed " );
}
if (maapi_xpath2kpath(MappiSocket, path, &p_KeyPath) != CONFD_OK) //translate the keypath
{
    DEBUG(netConfTraceP, << "Cannot translate xpath\n");
}
maapi_close(MappiSocket);
DEBUG(netConfTraceP, <<"ConfDAdaptorManager::CommitWasDone  maapi_close ");
printf("ConfDAdaptorManager::CommitWasDone  maapi_close\n");

CONFD_SET_TAG_XMLBEGIN(&values[i],   ncn_netconf_config_change, ncn__ns);  i++;
CONFD_SET_TAG_XMLBEGIN(&values[i],   ncn_changed_by,            ncn__ns);  i++;
CONFD_SET_TAG_STR(&values[i],        ncn_username,              "Admin");  i++;
CONFD_SET_TAG_UINT32(&values[i],     ncn_session_id,            0);        i++;
CONFD_SET_TAG_IPV4(&values[i],       ncn_source_host,           an_addr);  i++;
CONFD_SET_TAG_XMLEND(&values[i],     ncn_changed_by,            ncn__ns);  i++;
CONFD_SET_TAG_ENUM_VALUE(&values[i], ncn_datastore,             ncn_running); i++;
CONFD_SET_TAG_XMLBEGIN(&values[i],   ncn_edit,                  ncn__ns);  i++;
CONFD_SET_TAG_OBJECTREF(&values[i],  ncn_target,                p_KeyPath);i++;
CONFD_SET_TAG_XMLEND(&values[i],     ncn_edit,                  ncn__ns);  i++;
CONFD_SET_TAG_XMLEND(&values[i],     ncn_netconf_config_change, ncn__ns);  i++;

DEBUG(netConfTraceP, <<"ConfDAdaptorManager::CommitWasDone  CONFD_SET_TAG done ");
printf("ConfDAdaptorManager::CommitWasDone  CONFD_SET_TAG done \n");

struct confd_datetime eventTime;

struct tm tm;
struct timeval tv;

gettimeofday(&tv, NULL);
gmtime_r(&tv.tv_sec, &tm);

memset(&eventTime, 0, sizeof(eventTime));
eventTime.year = 1900 + tm.tm_year;
eventTime.month = tm.tm_mon + 1;
eventTime.day = tm.tm_mday;
eventTime.sec = tm.tm_sec;
eventTime.micro = tv.tv_usec;
eventTime.timezone = 0;
eventTime.timezone_minutes = 0;
eventTime.hour = tm.tm_hour;
eventTime.min = tm.tm_min;

printf("ConfDAdaptorManager::CommitWasDone  confd_notification_send \n");

print_modifications(values, i, NULL, 0);
int status = confd_notification_send(m_LiveContext, &eventTime, values, i);

Did you load the schema information from ConfD to libconfd using maapi_load_schemas() or confd_load_schemas()?

Also, is your fxs located where your load path point to?
For example, if confd is started with --addloadpath $(CONFD_DIR)/etc/confd the fxs need to be located under $(CONFD_DIR)/etc/confd/ietf-netconf-notifications.fxs