output PEP device addresses as metadata
[strongswan.git] / src / libcharon / plugins / tnc_ifmap / tnc_ifmap_soap.c
index 5fae6ea..d9b20df 100644 (file)
@@ -65,91 +65,120 @@ struct private_tnc_ifmap_soap_t {
 
 };
 
+/**
+ * Send request and receive result via SOAP
+ */
+static bool send_receive(private_tnc_ifmap_soap_t *this,
+                                                char *request_qname, axiom_node_t *request,
+                                                char *receipt_qname, axiom_node_t **result)
+
+{
+    axiom_node_t *parent, *node;
+    axiom_element_t *el;
+       axutil_qname_t *qname;
+       bool success = FALSE;
+
+       /* send request and receive result */
+       DBG2(DBG_TNC, "sending  ifmap %s", request_qname);
+
+       parent = axis2_svc_client_send_receive(this->svc_client, this->env, request);
+       if (!parent)
+       {
+               DBG1(DBG_TNC, "no ifmap %s received from MAP server", receipt_qname);
+               return FALSE;
+       }
+
+       /* pre-process result */
+       node = axiom_node_get_first_child(parent, this->env);
+       if (node && axiom_node_get_node_type(node, this->env) == AXIOM_ELEMENT)
+       {
+               el = (axiom_element_t *)axiom_node_get_data_element(node, this->env);
+
+               qname = axiom_element_get_qname(el, this->env, node);
+               success = streq(receipt_qname, axutil_qname_to_string(qname, this->env));
+               if (success)
+               {
+                       DBG2(DBG_TNC, "received ifmap %s", receipt_qname);
+                       if (result)
+                       {
+                               *result = parent;
+                       }
+                       else
+                       {
+                               /* no further processing requested */
+                               axiom_node_free_tree(parent, this->env);
+                       }
+                       return TRUE;
+               }
+               /* TODO proper error handling */
+               DBG1(DBG_TNC, "%s", axiom_element_to_string(el, this->env, node));
+       }
+
+       /* free parent in the error case */
+       axiom_node_free_tree(parent, this->env);
+
+       return FALSE;
+}
+
 METHOD(tnc_ifmap_soap_t, newSession, bool,
        private_tnc_ifmap_soap_t *this)
 {
     axiom_node_t *request, *result, *node;
     axiom_element_t *el;
        axiom_namespace_t *ns;
-       axiom_attribute_t *attr;
        axis2_char_t *value;
-       axutil_qname_t *qname;
 
-       bool success = FALSE;
 
        /* build newSession request */
     ns = axiom_namespace_create(this->env, IFMAP_NS, "ifmap");
     el = axiom_element_create(this->env, NULL, "newSession", ns, &request);
-       attr = axiom_attribute_create(this->env, "max-poll-result-size", "1000000", NULL);      
-       axiom_element_add_attribute(el, this->env, attr, request);
 
-       /* send newSession request */
-       result = axis2_svc_client_send_receive(this->svc_client, this->env, request);
-       if (!result)
+       /* send newSession request and receive newSessionResult */
+       if (!send_receive(this, "newSession", request, "newSessionResult", &result))
        {
                return FALSE;
        }
 
        /* process newSessionResult */
        node = axiom_node_get_first_child(result, this->env);
-       if (node && axiom_node_get_node_type(node, this->env) == AXIOM_ELEMENT)
-       {
-               el = (axiom_element_t *)axiom_node_get_data_element(node, this->env);
-               qname = axiom_element_get_qname(el, this->env, node);
-               success = streq("newSessionResult",
-                                                axutil_qname_to_string(qname, this->env));
-                       
-               /* process the attributes */
-               if (success)
-               {
-                       value = axiom_element_get_attribute_value_by_name(el, this->env,
+       el = (axiom_element_t *)axiom_node_get_data_element(node, this->env);
+
+       /* get session-id */
+       value = axiom_element_get_attribute_value_by_name(el, this->env,
                                                                 "session-id");
-                       this->session_id = strdup(value);
-                       value = axiom_element_get_attribute_value_by_name(el, this->env,
+       this->session_id = strdup(value);
+
+       /* get ifmap-publisher-id */
+       value = axiom_element_get_attribute_value_by_name(el, this->env,
                                                                 "ifmap-publisher-id");
-                       this->ifmap_publisher_id = strdup(value);
+       this->ifmap_publisher_id = strdup(value);
 
-                       DBG1(DBG_TNC, "session-id: %s, ifmap-publisher-id: %s",
-                                this->session_id, this->ifmap_publisher_id);
-                       success = this->session_id && this->ifmap_publisher_id;
+       DBG1(DBG_TNC, "session-id: %s, ifmap-publisher-id: %s",
+                                  this->session_id, this->ifmap_publisher_id);
 
-                       value = axiom_element_get_attribute_value_by_name(el, this->env,
-                                                                "max-poll-result-size");
-                       if (value)
-                       {
-                               DBG1(DBG_TNC, "max-poll-result-size: %s", value);
-                       }
+       /* set PEP and PDP device name (defaults to IF-MAP Publisher ID) */
+       this->device_name = lib->settings->get_str(lib->settings,
+                                                               "charon.plugins.tnc-ifmap.device_name",
+                                                                this->ifmap_publisher_id);
+       this->device_name = strdup(this->device_name);
 
-                       /* set PEP and PDP device name (defaults to IF-MAP Publisher ID) */
-                       this->device_name = lib->settings->get_str(lib->settings,
-                                                                        "charon.plugins.tnc-ifmap.device_name",
-                                                                        this->ifmap_publisher_id);
-                       this->device_name = strdup(this->device_name);
-               }
-               else
-               {
-                       DBG1(DBG_TNC, "%s", axiom_element_to_string(el, this->env, node));
-               }
-       }
+       /* free result */
        axiom_node_free_tree(result, this->env);
 
-    return success;
+    return this->session_id && this->ifmap_publisher_id;
 }
 
 METHOD(tnc_ifmap_soap_t, purgePublisher, bool,
        private_tnc_ifmap_soap_t *this)
 {
-       axiom_node_t *request, *result, *node;
+       axiom_node_t *request;
        axiom_element_t *el;
        axiom_namespace_t *ns;
        axiom_attribute_t *attr;
-       axutil_qname_t *qname;
-       bool success = FALSE;
 
        /* build purgePublisher request */
        ns = axiom_namespace_create(this->env, IFMAP_NS, "ifmap");
-       el = axiom_element_create(this->env, NULL, "purgePublisher", ns,
-                                                         &request);
+       el = axiom_element_create(this->env, NULL, "purgePublisher", ns, &request);
        attr = axiom_attribute_create(this->env, "session-id",
                                                                  this->session_id, NULL);      
        axiom_element_add_attribute(el, this->env, attr, request);
@@ -157,43 +186,189 @@ METHOD(tnc_ifmap_soap_t, purgePublisher, bool,
                                                                  this->ifmap_publisher_id, NULL);      
        axiom_element_add_attribute(el, this->env, attr, request);
 
-       /* send purgePublisher request */
-       result = axis2_svc_client_send_receive(this->svc_client, this->env, request);
-       if (!result)
+       /* send purgePublisher request and receive purgePublisherReceived */
+       return send_receive(this, "purgePublisher", request,
+                                                         "purgePublisherReceived", NULL);
+}
+
+/**
+ * Create an access-request based on device_name and ike_sa_id
+ */
+static axiom_node_t* create_access_request(private_tnc_ifmap_soap_t *this,
+                                                                                  u_int32_t id)
+{
+       axiom_element_t *el;
+       axiom_node_t *node;
+       axiom_attribute_t *attr;
+       char buf[BUF_LEN];
+
+       el = axiom_element_create(this->env, NULL, "access-request", NULL, &node);
+
+       snprintf(buf, BUF_LEN, "%s:%d", this->device_name, id);
+       attr = axiom_attribute_create(this->env, "name", buf, NULL);    
+       axiom_element_add_attribute(el, this->env, attr, node);
+
+       return node;
+}
+
+/**
+ * Create an identity
+ */
+static axiom_node_t* create_identity(private_tnc_ifmap_soap_t *this,
+                                                                        identification_t *id, bool is_user)
+{
+       axiom_element_t *el;
+       axiom_node_t *node;
+       axiom_attribute_t *attr;
+       char buf[BUF_LEN], *id_type;
+
+       el = axiom_element_create(this->env, NULL, "identity", NULL, &node);
+
+       snprintf(buf, BUF_LEN, "%Y", id);
+       attr = axiom_attribute_create(this->env, "name", buf, NULL);    
+       axiom_element_add_attribute(el, this->env, attr, node);
+
+       switch (id->get_type(id))
        {
-               return FALSE;
+               case ID_FQDN:
+                       id_type = is_user ? "username" : "dns-name";
+                       break;
+               case ID_RFC822_ADDR:
+                       id_type = "email-address";
+                       break;
+               case ID_DER_ASN1_DN:
+                       id_type = "distinguished-name";
+                       break;
+               default:
+                       id_type = "other";
        }
+       attr = axiom_attribute_create(this->env, "type", id_type, NULL);        
+       axiom_element_add_attribute(el, this->env, attr, node);
 
-       /* process purgePublisherReceived */
-       node = axiom_node_get_first_child(result, this->env);
-       if (node && axiom_node_get_node_type(node, this->env) == AXIOM_ELEMENT)
+       return node;
+}
+
+/**
+ * Create an ip-address
+ */
+static axiom_node_t* create_ip_address(private_tnc_ifmap_soap_t *this,
+                                                                          host_t *host)
+{
+       axiom_element_t *el;
+       axiom_node_t *node;
+       axiom_attribute_t *attr;
+       char buf[BUF_LEN];
+
+       el = axiom_element_create(this->env, NULL, "ip-address", NULL, &node);
+
+       if (host->get_family(host) == AF_INET6)
        {
-               el = (axiom_element_t *)axiom_node_get_data_element(node, this->env);
-               qname = axiom_element_get_qname(el, this->env, node);
-               success = streq("purgePublisherReceived",
-                                                axutil_qname_to_string(qname, this->env));
-               if (!success)
-               {
-                       DBG1(DBG_TNC, "%s", axiom_element_to_string(el, this->env, node));
+               chunk_t address;
+               int len, written, i;
+               char *pos;
+               bool first = TRUE;
+
+               /* output IPv6 address in canonical IF-MAP 2.0 format */
+               address = host->get_address(host);
+               pos = buf;
+               len = sizeof(buf);
+
+               for (i = 0; i < address.len; i = i + 2)
+               {
+                       written = snprintf(pos, len, "%s%x", first ? "" : ":",
+                                                          256*address.ptr[i] +  address.ptr[i+1]);
+                       if (written < 0 || written > len)
+                       {
+                               break;
+                       }
+                       pos += written;
+                       len -= written;
+                       first = FALSE;
                }
        }
-       axiom_node_free_tree(result, this->env);
+       else
+       {
+               snprintf(buf, BUF_LEN, "%H", host);
+       }
+       attr = axiom_attribute_create(this->env, "value", buf, NULL);   
+       axiom_element_add_attribute(el, this->env, attr, node);
+
+       attr = axiom_attribute_create(this->env, "type",
+                                host->get_family(host) == AF_INET ? "IPv4" : "IPv6", NULL);    
+       axiom_element_add_attribute(el, this->env, attr, node);
+
+       return node;
+}
+
+/**
+ * Create a device
+ */
+static axiom_node_t* create_device(private_tnc_ifmap_soap_t *this)
+{
+       axiom_element_t *el;
+       axiom_node_t *node, *node2, *node3;
+       axiom_text_t *text;
 
-   return success;
+       el = axiom_element_create(this->env, NULL, "device", NULL, &node);
+       el = axiom_element_create(this->env, NULL, "name", NULL, &node2);
+       axiom_node_add_child(node, this->env, node2);
+       text = axiom_text_create(this->env, node2, this->device_name, &node3);
+
+       return node;
+}
+
+/**
+ * Create metadata
+ */
+static axiom_node_t* create_metadata(private_tnc_ifmap_soap_t *this,
+                                                                        char *metadata)
+{
+       axiom_element_t *el;
+       axiom_node_t *node, *node2;
+       axiom_attribute_t *attr;
+       axiom_namespace_t *ns_meta;
+
+       el = axiom_element_create(this->env, NULL, "metadata", NULL, &node);
+       ns_meta = axiom_namespace_create(this->env, IFMAP_META_NS, "meta");
+
+       el = axiom_element_create(this->env, NULL, metadata, ns_meta, &node2);
+       axiom_node_add_child(node, this->env, node2);
+       attr = axiom_attribute_create(this->env, "ifmap-cardinality", "singleValue",
+                                                                 NULL);        
+       axiom_element_add_attribute(el, this->env, attr, node2);
+
+       return node;
 }
 
-METHOD(tnc_ifmap_soap_t, publish, bool,
+/**
+ * Create delete filter
+ */
+static axiom_node_t* create_delete_filter(private_tnc_ifmap_soap_t *this,
+                                                                                 char *metadata)
+{
+       axiom_element_t *el;
+       axiom_node_t *node;
+       axiom_attribute_t *attr;
+       char buf[BUF_LEN];
+
+       el = axiom_element_create(this->env, NULL, "delete", NULL, &node);
+
+       snprintf(buf, BUF_LEN, "meta:%s[@ifmap-publisher-id='%s']",
+                        metadata, this->ifmap_publisher_id);
+       attr = axiom_attribute_create(this->env, "filter", buf, NULL);  
+       axiom_element_add_attribute(el, this->env, attr, node);
+
+       return node;
+}
+
+METHOD(tnc_ifmap_soap_t, publish_ike_sa, bool,
        private_tnc_ifmap_soap_t *this, u_int32_t ike_sa_id, identification_t *id,
-       host_t *host, bool up)
+       bool is_user, host_t *host, bool up)
 {
-       axiom_node_t *request, *result, *node, *node2, *node3, *node4;
+       axiom_node_t *request, *node;
        axiom_element_t *el;
        axiom_namespace_t *ns, *ns_meta;
        axiom_attribute_t *attr;
-       axiom_text_t *text;
-       axutil_qname_t *qname;
-       char buf[BUF_LEN], *id_type;
-       bool success = FALSE;
 
        /* build publish request */
        ns = axiom_namespace_create(this->env, IFMAP_NS, "ifmap");
@@ -210,67 +385,22 @@ METHOD(tnc_ifmap_soap_t, publish, bool,
        if (up)
        {
                el = axiom_element_create(this->env, NULL, "update", NULL, &node);
-               axiom_node_add_child(request, this->env, node);
        }
        else
        {
-               el = axiom_element_create(this->env, NULL, "delete", NULL, &node);
-               axiom_node_add_child(request, this->env, node);
-
-               /* add filter */
-               snprintf(buf, BUF_LEN, "meta:authenticated-as[@ifmap-publisher-id='%s']",
-                                this->ifmap_publisher_id);
-               attr = axiom_attribute_create(this->env, "filter", buf, NULL);  
-               axiom_element_add_attribute(el, this->env, attr, node);
+               node = create_delete_filter(this, "authenticated-as");
        }
+       axiom_node_add_child(request, this->env, node);
 
-       /* add access-request */
-       el = axiom_element_create(this->env, NULL, "access-request", NULL, &node2);
-       axiom_node_add_child(node, this->env, node2);
-
-       snprintf(buf, BUF_LEN, "%s:%d", this->device_name, ike_sa_id);
-       attr = axiom_attribute_create(this->env, "name", buf, NULL);    
-       axiom_element_add_attribute(el, this->env, attr, node2);
-
-       /* add identity */
-       el = axiom_element_create(this->env, NULL, "identity", NULL, &node2);
-       axiom_node_add_child(node, this->env, node2);
-
-       snprintf(buf, BUF_LEN, "%Y", id);
-       attr = axiom_attribute_create(this->env, "name", buf, NULL);    
-       axiom_element_add_attribute(el, this->env, attr, node2);
-
-       switch (id->get_type(id))
-       {
-               case ID_FQDN:
-                       id_type = "dns-name";
-                       break;
-               case ID_RFC822_ADDR:
-                       id_type = "email-address";
-                       break;
-               case ID_DER_ASN1_DN:
-                       id_type = "distinguished-name";
-                       break;
-               default:
-                       id_type = "other";
-       }
-       attr = axiom_attribute_create(this->env, "type", id_type, NULL);        
-       axiom_element_add_attribute(el, this->env, attr, node2);
-
+       /* add access-request, identity and [if up] metadata */
+       axiom_node_add_child(node, this->env,
+                                                        create_access_request(this, ike_sa_id));
+       axiom_node_add_child(node, this->env,
+                                                        create_identity(this, id, is_user));
        if (up)
        {
-               /* add metadata */
-               el = axiom_element_create(this->env, NULL, "metadata", NULL, &node2);
-               axiom_node_add_child(node, this->env, node2);
-
-               ns_meta = axiom_namespace_create(this->env, IFMAP_META_NS, "meta");
-
-               el = axiom_element_create(this->env, NULL, "authenticated-as", ns_meta,
-                                                                 &node3);
-               axiom_node_add_child(node2, this->env, node3);
-               attr = axiom_attribute_create(this->env, "ifmap-cardinality",
-                                                                         "singleValue", NULL); 
-               axiom_element_add_attribute(el, this->env, attr, node3);
+               axiom_node_add_child(node, this->env,
+                                                        create_metadata(this, "authenticated-as"));
        }
 
        /**
@@ -279,52 +409,22 @@ METHOD(tnc_ifmap_soap_t, publish, bool,
        if (up)
        {
                el = axiom_element_create(this->env, NULL, "update", NULL, &node);
-               axiom_node_add_child(request, this->env, node);
        }
        else
        {
-               el = axiom_element_create(this->env, NULL, "delete", NULL, &node);
-               axiom_node_add_child(request, this->env, node);
-
-               /* add filter */
-               snprintf(buf, BUF_LEN, "meta:access-request-ip[@ifmap-publisher-id='%s']",
-                                this->ifmap_publisher_id);
-               attr = axiom_attribute_create(this->env, "filter", buf, NULL);
-               axiom_element_add_attribute(el, this->env, attr, node);
+               node = create_delete_filter(this, "access-request-ip");
        }
+       axiom_node_add_child(request, this->env, node);
 
-       /* add access-request */
-       el = axiom_element_create(this->env, NULL, "access-request", NULL, &node2);
-       axiom_node_add_child(node, this->env, node2);
-
-       snprintf(buf, BUF_LEN, "%s:%d", this->device_name, ike_sa_id);
-       attr = axiom_attribute_create(this->env, "name", buf, NULL);    
-       axiom_element_add_attribute(el, this->env, attr, node2);
-
-       /* add ip-address */
-       el = axiom_element_create(this->env, NULL, "ip-address", NULL, &node2);
-       axiom_node_add_child(node, this->env, node2);
-
-       snprintf(buf, BUF_LEN, "%H", host);
-       attr = axiom_attribute_create(this->env, "value", buf, NULL);   
-       axiom_element_add_attribute(el, this->env, attr, node2);
-
-       attr = axiom_attribute_create(this->env, "type",
-                                host->get_family(host) == AF_INET ? "IPv4" : "IPv6", NULL);    
-       axiom_element_add_attribute(el, this->env, attr, node2);
-
+       /* add access-request, ip-address and [if up] metadata */
+       axiom_node_add_child(node, this->env,
+                                                        create_access_request(this, ike_sa_id));
+       axiom_node_add_child(node, this->env,
+                                                        create_ip_address(this, host));
        if (up)
        {
-               /* add metadata */
-               el = axiom_element_create(this->env, NULL, "metadata", NULL, &node2);
-               axiom_node_add_child(node, this->env, node2);
-               ns_meta = axiom_namespace_create(this->env, IFMAP_META_NS, "meta");
-               el = axiom_element_create(this->env, NULL, "access-request-ip", ns_meta,
-                                                                 &node3);
-               axiom_node_add_child(node2, this->env, node3);
-               attr = axiom_attribute_create(this->env, "ifmap-cardinality",
-                                                                         "singleValue", NULL); 
-               axiom_element_add_attribute(el, this->env, attr, node3);
+               axiom_node_add_child(node, this->env,
+                                                        create_metadata(this, "access-request-ip"));
        }
 
        /**
@@ -333,83 +433,66 @@ METHOD(tnc_ifmap_soap_t, publish, bool,
        if (up)
        {
                el = axiom_element_create(this->env, NULL, "update", NULL, &node);
-               axiom_node_add_child(request, this->env, node);
        }
        else
        {
-               el = axiom_element_create(this->env, NULL, "delete", NULL, &node);
-               axiom_node_add_child(request, this->env, node);
-
-               /* add filter */                
-               snprintf(buf, BUF_LEN, "meta:authenticated-by[@ifmap-publisher-id='%s']",
-                                this->ifmap_publisher_id);
-               attr = axiom_attribute_create(this->env, "filter", buf, NULL);
-               axiom_element_add_attribute(el, this->env, attr, node);
+               node = create_delete_filter(this, "authenticated-by");
        }
+       axiom_node_add_child(request, this->env, node);
 
-       /* add access-request */
-       el = axiom_element_create(this->env, NULL, "access-request", NULL, &node2);
-       axiom_node_add_child(node, this->env, node2);
-
-       snprintf(buf, BUF_LEN, "%s:%d", this->device_name, ike_sa_id);
-       attr = axiom_attribute_create(this->env, "name", buf, NULL);    
-       axiom_element_add_attribute(el, this->env, attr, node2);
-
-       /* add device */
-       el = axiom_element_create(this->env, NULL, "device", NULL, &node2);
-       axiom_node_add_child(node, this->env, node2);
-       el = axiom_element_create(this->env, NULL, "name", NULL, &node3);
-       axiom_node_add_child(node2, this->env, node3);
-       text = axiom_text_create(this->env, node3, this->device_name, &node4);
-
+       /* add access-request, device and [if up] metadata */
+       axiom_node_add_child(node, this->env,
+                                                        create_access_request(this, ike_sa_id));
+       axiom_node_add_child(node, this->env,
+                                                        create_device(this));
        if (up)
        {
-               /* add metadata */
-               el = axiom_element_create(this->env, NULL, "metadata", NULL, &node2);
-               axiom_node_add_child(node, this->env, node2);
-               ns_meta = axiom_namespace_create(this->env, IFMAP_META_NS, "meta");
-               el = axiom_element_create(this->env, NULL, "authenticated-by", ns_meta,
-                                                                 &node3);
-               axiom_node_add_child(node2, this->env, node3);
-               attr = axiom_attribute_create(this->env, "ifmap-cardinality",
-                                                                         "singleValue", NULL); 
-               axiom_element_add_attribute(el, this->env, attr, node3);
+               axiom_node_add_child(node, this->env,
+                                                        create_metadata(this, "authenticated-by"));
        }
 
-       /* send publish request */
-       result = axis2_svc_client_send_receive(this->svc_client, this->env, request);
-       if (!result)
-       {
-               return FALSE;
-       }
+       /* send publish request and receive publishReceived */
+       return send_receive(this, "publish", request, "publishReceived", NULL);
+}
 
-       /* process publishReceived */
-       node = axiom_node_get_first_child(result, this->env);
-       if (node && axiom_node_get_node_type(node, this->env) == AXIOM_ELEMENT)
-       {
-               el = (axiom_element_t *)axiom_node_get_data_element(node, this->env);
-               qname = axiom_element_get_qname(el, this->env, node);
-               success = streq("publishReceived",
-                                               axutil_qname_to_string(qname, this->env));
-               if (!success)
-               {
-                       DBG1(DBG_TNC, "%s", axiom_element_to_string(el, this->env, node));
-               }
-       }
-       axiom_node_free_tree(result, this->env);
+METHOD(tnc_ifmap_soap_t, publish_device_ip, bool,
+       private_tnc_ifmap_soap_t *this, host_t *host)
+{
+       axiom_node_t *request, *node;
+       axiom_element_t *el;
+       axiom_namespace_t *ns, *ns_meta;
+       axiom_attribute_t *attr;
 
-   return TRUE;
+       /* build publish request */
+       ns = axiom_namespace_create(this->env, IFMAP_NS, "ifmap");
+       el = axiom_element_create(this->env, NULL, "publish", ns, &request);
+       ns_meta = axiom_namespace_create(this->env, IFMAP_META_NS, "meta");
+       axiom_element_declare_namespace(el, this->env, request, ns_meta);       
+       attr = axiom_attribute_create(this->env, "session-id", this->session_id,
+                                                                 NULL);        
+       axiom_element_add_attribute(el, this->env, attr, request);
+       el = axiom_element_create(this->env, NULL, "update", NULL, &node);
+       axiom_node_add_child(request, this->env, node);
+
+       /* add device, ip-address and metadata */
+       axiom_node_add_child(node, this->env,
+                                                        create_device(this));
+       axiom_node_add_child(node, this->env,
+                                                        create_ip_address(this, host));
+       axiom_node_add_child(node, this->env,
+                                                        create_metadata(this, "device-ip"));
+
+       /* send publish request and receive publishReceived */
+       return send_receive(this, "publish", request, "publishReceived", NULL);
 }
 
 METHOD(tnc_ifmap_soap_t, endSession, bool,
        private_tnc_ifmap_soap_t *this)
 {
-       axiom_node_t *request, *result, *node;
+       axiom_node_t *request;
        axiom_element_t *el;
        axiom_namespace_t *ns;
        axiom_attribute_t *attr;
-       axutil_qname_t *qname;
-       bool success = FALSE;
 
        /* build endSession request */
        ns = axiom_namespace_create(this->env, IFMAP_NS, "ifmap");
@@ -417,31 +500,8 @@ METHOD(tnc_ifmap_soap_t, endSession, bool,
        attr = axiom_attribute_create(this->env, "session-id", this->session_id, NULL); 
        axiom_element_add_attribute(el, this->env, attr, request);
 
-       /* send endSession request */
-       result = axis2_svc_client_send_receive(this->svc_client, this->env, request);
-       if (!result)
-       {
-               return FALSE;
-       }
-
-       /* process endSessionResult */
-       node = axiom_node_get_first_child(result, this->env);
-       if (node && axiom_node_get_node_type(node, this->env) == AXIOM_ELEMENT)
-       {
-               el = (axiom_element_t *)axiom_node_get_data_element(node, this->env);
-               qname = axiom_element_get_qname(el, this->env, node);
-               success = streq("endSessionResult",
-                                                axutil_qname_to_string(qname, this->env));
-               if (!success)
-               {
-                       DBG1(DBG_TNC, "%s", axiom_element_to_string(el, this->env, node));
-               }
-       }
-       axiom_node_free_tree(result, this->env);
-
-   return success;
-
-   return TRUE;
+       /* send endSession request and receive end SessionResult */
+       return send_receive(this, "endSession", request, "endSessionResult", NULL);
 }
 
 METHOD(tnc_ifmap_soap_t, destroy, void,
@@ -449,11 +509,7 @@ METHOD(tnc_ifmap_soap_t, destroy, void,
 {
        if (this->session_id)
        {
-               DBG2(DBG_TNC, "sending ifmap->endSession");
-               if (!endSession(this))
-               {
-                       DBG1(DBG_TNC, "ifmap->endSession with MAP server failed");
-               }
+               endSession(this);
                free(this->session_id);
                free(this->ifmap_publisher_id);
                free(this->device_name);        
@@ -504,7 +560,8 @@ tnc_ifmap_soap_t *tnc_ifmap_soap_create()
                .public = {
                        .newSession = _newSession,
                        .purgePublisher = _purgePublisher,
-                       .publish = _publish,
+                       .publish_ike_sa = _publish_ike_sa,
+                       .publish_device_ip = _publish_device_ip,
                        .endSession = _endSession,
                        .destroy = _destroy,
                },