+ delete_payload_t *delete_request = NULL;
+ ike_sa_id_t *ike_sa_id;
+ iterator_t *payloads;
+ message_t *response;
+ crypter_t *crypter;
+ signer_t *signer;
+ status_t status;
+
+ if (message->get_exchange_type(message) != INFORMATIONAL)
+ {
+ this->logger->log(this->logger, ERROR | LEVEL1, "Message of type %s not supported in state ike_sa_established",
+ mapping_find(exchange_type_m,message->get_exchange_type(message)));
+ return FAILED;
+ }
+
+ if (!message->get_request(message))
+ {
+ this->logger->log(this->logger, ERROR | LEVEL1, "INFORMATIONAL responses not handled in state ike_sa_established");
+ return FAILED;
+ }
+
+ ike_sa_id = this->ike_sa->public.get_id(&(this->ike_sa->public));
+
+ /* get signer for verification and crypter for decryption */
+ if (!ike_sa_id->is_initiator(ike_sa_id))
+ {
+ crypter = this->ike_sa->get_crypter_initiator(this->ike_sa);
+ signer = this->ike_sa->get_signer_initiator(this->ike_sa);
+ }
+ else
+ {
+ crypter = this->ike_sa->get_crypter_responder(this->ike_sa);
+ signer = this->ike_sa->get_signer_responder(this->ike_sa);
+ }
+
+ /* parse incoming message */
+ status = message->parse_body(message, crypter, signer);
+ if (status != SUCCESS)
+ {
+ this->logger->log(this->logger, AUDIT, "INFORMATIONAL request decryption failed. Ignoring message");
+ return status;
+ }
+
+ /* build empty INFORMATIONAL message */
+ this->ike_sa->build_message(this->ike_sa, INFORMATIONAL, FALSE, &response);
+
+ payloads = message->get_payload_iterator(message);
+
+ while (payloads->has_next(payloads))
+ {
+ payload_t *payload;
+ payloads->current(payloads, (void**)&payload);
+
+ switch (payload->get_type(payload))
+ {
+ case NOTIFY:
+ {
+ notify_payload_t *notify_payload = (notify_payload_t *) payload;
+ /* handle the notify directly, abort if no further processing required */
+ status = this->process_notify_payload(this, notify_payload,response);
+ if (status != SUCCESS)
+ {
+ payloads->destroy(payloads);
+ response->destroy(response);
+ return status;
+ }
+ }
+ case DELETE:
+ {
+ delete_request = (delete_payload_t *) payload;
+ }
+ default:
+ {
+ this->logger->log(this->logger, ERROR|LEVEL1, "Ignoring Payload %s (%d)",
+ mapping_find(payload_type_m, payload->get_type(payload)), payload->get_type(payload));
+ break;
+ }
+ }
+ }
+ /* iterator can be destroyed */
+ payloads->destroy(payloads);
+
+ if (delete_request)
+ {
+ status = this->build_delete_payload(this, delete_request, response);
+ if (status == DELETE_ME)
+ {
+ status = this->ike_sa->send_response(this->ike_sa, response);
+ if (status != SUCCESS)
+ {
+ this->logger->log(this->logger, AUDIT, "Unable to send INFORMATIONAL reply");
+ response->destroy(response);
+ return FAILED;
+ }
+ response->destroy(response);
+ return status;
+ }
+ }
+
+
+ status = this->ike_sa->send_response(this->ike_sa, response);
+ /* message can now be sent (must not be destroyed) */
+ if (status != SUCCESS)
+ {
+ this->logger->log(this->logger, AUDIT, "Unable to send INFORMATIONAL reply");
+ response->destroy(response);
+ return FAILED;
+ }
+
+ return SUCCESS;
+}
+
+/**
+ * Implementation of private_ike_sa_established_t.build_sa_payload;
+ */
+static status_t build_delete_payload (private_ike_sa_established_t *this, delete_payload_t *request, message_t *response_message)
+{
+ delete_payload_t *response;
+ if (request->get_protocol_id(request) == IKE)
+ {
+ this->logger->log(this->logger, AUDIT, "DELETE request for IKE_SA received. Create delete reply.");
+
+ response = delete_payload_create();
+ response->set_protocol_id(response,IKE);
+
+ response_message->add_payload(response_message,(payload_t *)response);
+ /* IKE_SA has to get deleted */
+ return DELETE_ME;
+ }
+
+ this->logger->log(this->logger, AUDIT, "DELETE payload for CHILD_SAs not supported and handled.");
+