コード例 #1
0
ファイル: firewall_control.c プロジェクト: anupash/privseams
/**
 * Change the state of hadb state cache in the firewall
 *
 * @param msg the message containing hadb cache information
 *
 * @return zero on success, non-zero on error
 */
static int hip_handle_bex_state_update(struct hip_common *msg)
{
    const struct in6_addr       *src_hit = NULL, *dst_hit = NULL;
    const struct hip_tlv_common *param   = NULL;
    int                          err     = 0, msg_type = 0;

    msg_type = hip_get_msg_type(msg);

    /* src_hit */
    param   = hip_get_param(msg, HIP_PARAM_HIT);
    src_hit = hip_get_param_contents_direct(param);
    HIP_DEBUG_HIT("Source HIT: ", src_hit);

    /* dst_hit */
    param   = hip_get_next_param(msg, param);
    dst_hit = hip_get_param_contents_direct(param);
    HIP_DEBUG_HIT("Destination HIT: ", dst_hit);

    /* update bex_state in firewalldb */
    switch (msg_type) {
    case HIP_MSG_FW_BEX_DONE:
        err = hip_firewall_cache_set_bex_state(src_hit, dst_hit,
                                               HIP_STATE_ESTABLISHED);
        break;
    case HIP_MSG_FW_UPDATE_DB:
        err = hip_firewall_cache_set_bex_state(src_hit, dst_hit,
                                               HIP_STATE_NONE);
        break;
    default:
        break;
    }
    return err;
}
コード例 #2
0
int main_server_tcp(int serversock) {
	int peerfd = 0, err = 0;
	socklen_t locallen;
	unsigned int peerlen;
	struct sockaddr_in6 localaddr, peeraddr;
	char mylovemostdata[IP_MAXPACKET];
	int recvnum, sendnum;
	char addrstr[INET6_ADDRSTRLEN];

	peerlen = sizeof(struct sockaddr_in6);

	peerfd = accept(serversock, (struct sockaddr *)&peeraddr, &peerlen);
	
	if (peerfd < 0) {
		perror("accept");
		err = -1;
		goto out_err;
	}

	locallen = sizeof(localaddr);
	if (!getsockname(serversock,
			 (struct sockaddr *)&localaddr,
			 &locallen))
		HIP_DEBUG_HIT("local addr", &localaddr.sin6_addr);
	HIP_DEBUG_HIT("peer addr", &peeraddr.sin6_addr);
	
	while((recvnum = recv(peerfd, mylovemostdata,
			      sizeof(mylovemostdata), 0)) > 0 ) {
		mylovemostdata[recvnum] = '\0';
		printf("Client sends:\n%s", mylovemostdata);
		fflush(stdout);
		if (recvnum == 0) {
			close(peerfd);
			err = -1;
			break;
		}
		
		/* send reply */
		sendnum = send(peerfd, mylovemostdata, recvnum, 0);
		if (sendnum < 0) {
			perror("send");
			err = -1;
			break;
		}
		printf("Client has been replied.\n");
	}
	if (peerfd)
		close(peerfd);

out_err:
	return err;
}
コード例 #3
0
ファイル: debug.c プロジェクト: anupash/privseams
/**
 * display a LOCATOR parameter contents in a HIP control message
 *
 * @param in_msg the message where the LOCATOR parameter is located
 */
void hip_print_locator_addresses(const struct hip_common *in_msg)
{
    const struct hip_locator                 *locator;
    const struct hip_locator_info_addr_item  *ptr   = NULL;
    const struct hip_locator_info_addr_item  *item  = NULL;
    const struct hip_locator_info_addr_item2 *item2 = NULL;
    const char                               *address_pointer;

    locator = hip_get_param(in_msg, HIP_PARAM_LOCATOR);
    if (locator) {
        address_pointer = (const char *) (locator + 1);

        for (; address_pointer < ((const char *) locator) +
             hip_get_param_contents_len(locator); ) {
            ptr = (const struct hip_locator_info_addr_item *) address_pointer;
            if (ptr->locator_type == HIP_LOCATOR_LOCATOR_TYPE_UDP) {
                item2 = (const struct hip_locator_info_addr_item2 *)
                        address_pointer;
                HIP_DEBUG_HIT("LOCATOR", &item2->address);
                HIP_DEBUG("Locator address offset is %d\n",
                          address_pointer - (const char *) (locator + 1));
                address_pointer += sizeof(struct hip_locator_info_addr_item2);
            } else if (ptr->locator_type == HIP_LOCATOR_LOCATOR_TYPE_ESP_SPI) {
                item = (const struct hip_locator_info_addr_item *)
                       address_pointer;
                HIP_DEBUG_HIT("LOCATOR", &item->address);
                address_pointer += sizeof(struct hip_locator_info_addr_item);
            } else if (ptr->locator_type == HIP_LOCATOR_LOCATOR_TYPE_IPV6) {
                item = (const struct hip_locator_info_addr_item *)
                       address_pointer;
                HIP_DEBUG_HIT("LOCATOR", &item->address);
                address_pointer += sizeof(struct hip_locator_info_addr_item);
            } else {
                address_pointer += sizeof(struct hip_locator_info_addr_item);
            }
        }
    }
}
コード例 #4
0
ファイル: esp_prot_fw_msg.c プロジェクト: anupash/privseams
/**
 * Notifies the hipd about an anchor change in the hipfw
 *
 * @param   entry the sadb entry for the outbound direction
 * @return  0 on success, -1 on error, 1 for inbound sadb entry
 */
int send_anchor_change_to_hipd(const struct hip_sa_entry *entry)
{
    int                err         = 0;
    int                hash_length = 0;
    long               i           = 0;
    unsigned char     *anchor      = NULL;
    struct hip_common *msg         = NULL;
    struct hash_chain *hchain      = NULL;
    struct hash_tree  *htree       = NULL;

    HIP_ASSERT(entry != NULL);
    HIP_ASSERT(entry->direction == HIP_SPI_DIRECTION_OUT);

    HIP_IFEL((hash_length = esp_prot_get_hash_length(entry->esp_prot_transform)) <= 0,
             -1, "error or tried to resolve UNUSED transform\n");

    HIP_IFEL(!(msg = malloc(HIP_MAX_PACKET)), -1,
             "failed to allocate memory\n");

    hip_msg_init(msg);

    HIP_IFEL(hip_build_user_hdr(msg, HIP_MSG_ANCHOR_CHANGE, 0), -1,
             "build hdr failed\n");

    HIP_DEBUG_HIT("src_hit", &entry->inner_src_addr);
    HIP_IFEL(hip_build_param_contents(msg, &entry->inner_src_addr,
                                      HIP_PARAM_HIT, sizeof(struct in6_addr)),
             -1, "build param contents failed\n");

    HIP_DEBUG_HIT("dst_hit", &entry->inner_dst_addr);
    HIP_IFEL(hip_build_param_contents(msg, &entry->inner_dst_addr,
                                      HIP_PARAM_HIT, sizeof(struct in6_addr)),
             -1, "build param contents failed\n");

    HIP_DEBUG("direction: %i\n", entry->direction);
    HIP_IFEL(hip_build_param_contents(msg, &entry->direction,
                                      HIP_PARAM_INT, sizeof(int)), -1,
             "build param contents failed\n");

    HIP_DEBUG("esp_prot_transform: %u\n", entry->esp_prot_transform);
    HIP_IFEL(hip_build_param_contents(msg, &entry->esp_prot_transform,
                                      HIP_PARAM_ESP_PROT_TFM, sizeof(uint8_t)),
             -1, "build param contents failed\n");

    HIP_DEBUG("esp_prot_num_parallel_hchains: %i\n", num_parallel_hchains);
    HIP_IFEL(hip_build_param_contents(msg, &num_parallel_hchains,
                                      HIP_PARAM_INT, sizeof(int)), -1,
             "build param contents failed\n");

    for (i = 0; i < num_parallel_hchains; i++) {
        // the anchor change has already occurred on fw-side
        if (entry->esp_prot_transform == ESP_PROT_TFM_TREE) {
            htree  = entry->active_hash_items[i];
            anchor = htree->root;
        } else {
            hchain = entry->active_hash_items[i];
            anchor = hchain_get_anchor(hchain);
        }

        HIP_HEXDUMP("anchor: ", anchor, hash_length);
        HIP_IFEL(hip_build_param_contents(msg, anchor,
                                          HIP_PARAM_HCHAIN_ANCHOR, hash_length),
                 -1, "build param contents failed\n");
    }

    HIP_DUMP_MSG(msg);

    /* send msg to hipd and receive corresponding reply */
    HIP_IFEL(hip_send_recv_daemon_info(msg, 1, hip_fw_sock), -1,
             "send_recv msg failed\n");

    /* check error value */
    HIP_IFEL(hip_get_msg_err(msg), -1, "hipd returned error message!\n");

    HIP_DEBUG("send_recv msg succeeded\n");

out_err:
    free(msg);
    return err;
}
コード例 #5
0
ファイル: esp_prot_fw_msg.c プロジェクト: anupash/privseams
/**
 * Invokes an UPDATE message containing an anchor element as a hook to
 * next hash structure to be used when the active one depletes
 *
 * @param   entry the sadb entry for the outbound direction
 * @param   anchors the anchor elements to be sent
 * @param   hash_item_length length of the respective hash item
 * @param   soft_update indicates if HHL-based updates should be used
 * @param   anchor_offset the offset of the anchor element in the link tree
 * @param   link_trees the link trees for the anchor elements, in case of HHL
 * @return  0 on success, -1 on error
 */
int send_trigger_update_to_hipd(const struct hip_sa_entry *entry,
                                const unsigned char *anchors[MAX_NUM_PARALLEL_HCHAINS],
                                const int hash_item_length,
                                const int soft_update,
                                const int *anchor_offset,
                                struct hash_tree *link_trees[MAX_NUM_PARALLEL_HCHAINS])
{
    int                  err           = 0;
    int                  i             = 0;
    struct hip_common   *msg           = NULL;
    int                  hash_length   = 0;
    struct hash_chain   *hchain        = NULL;
    struct hash_tree    *htree         = NULL;
    struct hash_tree    *link_tree     = NULL;
    int                  secret_length = 0;
    int                  branch_length = 0;
    int                  root_length   = 0;
    const unsigned char *secret        = NULL;
    unsigned char       *branch_nodes  = NULL;
    const unsigned char *root          = NULL;

    HIP_ASSERT(entry != NULL);

    HIP_IFEL((hash_length = esp_prot_get_hash_length(entry->esp_prot_transform)) <= 0,
             -1, "error or tried to resolve UNUSED transform\n");

    HIP_IFEL(!(msg = malloc(HIP_MAX_PACKET)), -1,
             "failed to allocate memory\n");

    hip_msg_init(msg);

    HIP_IFEL(hip_build_user_hdr(msg, HIP_MSG_TRIGGER_UPDATE, 0), -1,
             "build hdr failed\n");

    HIP_DEBUG_HIT("src_hit", &entry->inner_src_addr);
    HIP_IFEL(hip_build_param_contents(msg, &entry->inner_src_addr,
                                      HIP_PARAM_HIT, sizeof(struct in6_addr)),
             -1, "build param contents failed\n");

    HIP_DEBUG_HIT("dst_hit", &entry->inner_dst_addr);
    HIP_IFEL(hip_build_param_contents(msg, &entry->inner_dst_addr,
                                      HIP_PARAM_HIT, sizeof(struct in6_addr)),
             -1, "build param contents failed\n");

    HIP_DEBUG("esp_prot_transform: %u\n", entry->esp_prot_transform);
    HIP_IFEL(hip_build_param_contents(msg, &entry->esp_prot_transform,
                                      HIP_PARAM_ESP_PROT_TFM, sizeof(uint8_t)),
             -1, "build param contents failed\n");

    // also send the hchain/htree length for all update items
    HIP_IFEL(hip_build_param_contents(msg, &hash_item_length, HIP_PARAM_INT,
                                      sizeof(int)), -1, "build param contents failed\n");
    HIP_DEBUG("added hash_item_length: %i\n", hash_item_length);

    HIP_DEBUG("num_parallel_hchains: %u\n", num_parallel_hchains);
    HIP_IFEL(hip_build_param_contents(msg, &num_parallel_hchains,
                                      HIP_PARAM_INT, sizeof(long)), -1,
             "build param contents failed\n");

    // add update anchors
    for (i = 0; i < num_parallel_hchains; i++) {
        HIP_HEXDUMP("anchor: ", anchors[i], hash_length);
        HIP_IFEL(hip_build_param_contents(msg, anchors[i],
                                          HIP_PARAM_HCHAIN_ANCHOR,
                                          hash_length), -1,
                 "build param contents failed\n");
    }

    // now transmit root for each next hash item for tree-based updates, if available
    for (i = 0; i < num_parallel_hchains; i++) {
        if (entry->esp_prot_transform == ESP_PROT_TFM_TREE) {
            htree     = entry->next_hash_items[i];
            link_tree = htree->link_tree;
        } else {
            hchain    = entry->next_hash_items[i];
            link_tree = hchain->link_tree;
        }

        if (link_tree) {
            /* if the next_hchain has got a link_tree, we need its root for
             * the verification of the next_hchain's elements */
            root = htree_get_root(link_tree, &root_length);
        }

        // only transmit root length once
        if (i == 0) {
            HIP_DEBUG("root_length: %i\n", root_length);
            HIP_IFEL(hip_build_param_contents(msg, &root_length,
                                              HIP_PARAM_INT,
                                              sizeof(int)), -1,
                     "build param contents failed\n");
        }

        if (root) {
            HIP_HEXDUMP("root: ", root, root_length);
            HIP_IFEL(hip_build_param_contents(msg, root,
                                              HIP_PARAM_ROOT, root_length), -1,
                     "build param contents failed\n");
        }
    }

    HIP_DEBUG("soft_update: %i\n", soft_update);
    HIP_IFEL(hip_build_param_contents(msg, &soft_update, HIP_PARAM_INT,
                                      sizeof(int)), -1,
             "build param contents failed\n");

    if (soft_update) {
        for (i = 0; i < num_parallel_hchains; i++) {
            secret = htree_get_secret(link_trees[i],
                                      anchor_offset[i], &secret_length);
            HIP_IFEL(!(branch_nodes = htree_get_branch(link_trees[i],
                                                       anchor_offset[i], NULL,
                                                       &branch_length)), -1,
                     "failed to get branch nodes\n");

            HIP_DEBUG("anchor_offset: %i\n", anchor_offset[i]);
            HIP_IFEL(hip_build_param_contents(msg, &anchor_offset[i],
                                              HIP_PARAM_INT,
                                              sizeof(int)), -1,
                     "build param contents failed\n");

            HIP_DEBUG("secret_length: %i\n", secret_length);
            HIP_IFEL(hip_build_param_contents(msg, &secret_length,
                                              HIP_PARAM_INT,
                                              sizeof(int)), -1,
                     "build param contents failed\n");

            HIP_DEBUG("branch_length: %i\n", branch_length);
            HIP_IFEL(hip_build_param_contents(msg, &branch_length,
                                              HIP_PARAM_INT,
                                              sizeof(int)), -1,
                     "build param contents failed\n");

            HIP_HEXDUMP("secret: ", secret, secret_length);
            HIP_IFEL(hip_build_param_contents(msg, secret,
                                              HIP_PARAM_SECRET,
                                              secret_length), -1,
                     "build param contents failed\n");

            HIP_HEXDUMP("branch_nodes: ", branch_nodes, branch_length);
            HIP_IFEL(hip_build_param_contents(msg, branch_nodes,
                                              HIP_PARAM_BRANCH_NODES,
                                              branch_length), -1,
                     "build param contents failed\n");
        }
    }

    HIP_DUMP_MSG(msg);

    /* send msg to hipd and receive corresponding reply */
    HIP_IFEL(hip_send_recv_daemon_info(msg, 1, hip_fw_sock), -1,
             "send_recv msg failed\n");

    /* check error value */
    HIP_IFEL(hip_get_msg_err(msg), -1, "hipd returned error message!\n");

    HIP_DEBUG("send_recv msg succeeded\n");

out_err:
    free(msg);
    free(branch_nodes);
    return err;
}
コード例 #6
0
/**
 * main_server_native - it handles the functionality of the client-native
 * @param socktype the type of socket
 * @param port_name the prot number
 *
 * @return 1 with success, 0 otherwise.
 */
int main_server_native(int socktype, char *port_name, char *name)
{
	struct endpointinfo hints, *res = NULL;
	struct sockaddr_eid peer_eid;
	struct sockaddr_hip our_sockaddr, peer_sock;
	char mylovemostdata[IP_MAXPACKET];
	int recvnum, sendnum, serversock = 0, sockfd = 0, err = 0, on = 1;
	int endpoint_family = PF_HIP;
	socklen_t peer_eid_len = sizeof(struct sockaddr_hip);

	/* recvmsg() stuff for UDP multihoming */
	char control[CMSG_SPACE(40)];
	struct cmsghdr *cmsg;
	struct inet6_pktinfo *pktinfo;
	struct iovec iov = { &mylovemostdata, sizeof(mylovemostdata) - 1 };
	struct msghdr msg = { &peer_sock, sizeof(peer_sock), &iov, 1,
						&control, sizeof(control), 0 };

	serversock = socket(endpoint_family, socktype, 0);
	if (serversock < 0) {
		HIP_PERROR("socket: ");
		err = 1;
		goto out_err;
	}

	setsockopt(serversock, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
	if (socktype == SOCK_DGRAM)
		setsockopt(serversock, IPPROTO_IPV6, IPV6_2292PKTINFO, &on, sizeof(on));

	memset(&hints, 0, sizeof(struct endpointinfo));
	hints.ei_family = endpoint_family;
	hints.ei_socktype = socktype;

	HIP_DEBUG("Native server calls getendpointinfo\n");

	err = getendpointinfo(NULL, port_name, &hints, &res);
	if (err || !res) {
		HIP_ERROR("Resolving of peer identifiers failed (%d)\n", err);
		goto out_err;
	}

	memset(&our_sockaddr, 0, sizeof(struct sockaddr_hip));
	if (name) {
		HIP_IFEL(inet_pton(AF_INET6, name, &our_sockaddr.ship_hit) != 1,
						    1, "Failed to parse HIT\n");
	}
	our_sockaddr.ship_port = htons(atoi(port_name));
	HIP_DEBUG("Binding to port %d\n", ntohs(our_sockaddr.ship_port));
	our_sockaddr.ship_family = endpoint_family;

	if (bind(serversock, &our_sockaddr, sizeof(struct sockaddr_hip)) < 0) {
		HIP_PERROR("bind: ");
		err = 1;
		goto out_err;
	}
	
	HIP_DEBUG("Native server calls listen\n");

	if (socktype == SOCK_STREAM && listen(serversock, 1) < 0) {
		HIP_PERROR("listen: ");
		err = 1;
		goto out_err;
	}

	HIP_DEBUG("Native server waits connection request\n");

	while(1) {
		if (socktype == SOCK_STREAM) {
			sockfd = accept(serversock, (struct sockaddr *) &peer_sock,
					&peer_eid_len);
			if (sockfd < 0) {
				HIP_PERROR("accept: ");
				err = 1;
				goto out_err;
			}

			while((recvnum = recv(sockfd, mylovemostdata,
					      sizeof(mylovemostdata), 0)) > 0 ) {
				mylovemostdata[recvnum] = '\0';
				printf("%s", mylovemostdata);
				fflush(stdout);

				sendnum = send(sockfd, mylovemostdata, recvnum, 0);
				if (sendnum < 0) {
					HIP_PERROR("send: ");
					err = 1;
					goto out_err;
				}
			}
		} else { /* UDP */
			sockfd = serversock;
			serversock = 0;
			while((recvnum = recvmsg(sockfd, &msg, 0)) > 0) {
				for (cmsg = CMSG_FIRSTHDR(&msg); cmsg; cmsg = CMSG_NXTHDR(&msg, cmsg)) {
					if (cmsg->cmsg_level == IPPROTO_IPV6 &&
					    cmsg->cmsg_type == IPV6_2292PKTINFO) {
						pktinfo = CMSG_DATA(cmsg);
						break;
					}
				}
				HIP_DEBUG_HIT("localaddr", &pktinfo->ipi6_addr);
				iov.iov_len = strlen(mylovemostdata);

				/* ancillary data contains the src
				 * and dst addresses */
				sendnum = sendmsg(sockfd, &msg, 0);
				if (sendnum < 0) {
					HIP_PERROR("sendto: ");
					err = 1;
					goto out_err;
				}
			}
		}
	}

out_err:

	if (res)
		free_endpointinfo(res);

	if (sockfd)
		close(sockfd); // discard errors
	if (serversock)
		close(serversock); // discard errors

	return err;
}
コード例 #7
0
ファイル: pfkeyapi.c プロジェクト: surki/hipl
/* Security associations in the kernel with BEET are bounded to the outer
 * address, meaning IP addresses. As a result the parameters to be given
 * should be such an addresses and not the HITs.
 */
uint32_t hip_add_sa(struct in6_addr *saddr, struct in6_addr *daddr,
		    struct in6_addr *src_hit, struct in6_addr *dst_hit,
		    uint32_t spi, int ealg, struct hip_crypto_key *enckey,
		    struct hip_crypto_key *authkey,
		    int already_acquired, int direction, int update,
		    hip_ha_t *entry)
{

	int so, len, err = 0, e_keylen, a_keylen;
	int aalg = ealg;
	u_int wsize = 4;  /* XXX static size of window */
	struct sockaddr_storage ss_addr, dd_addr;
	struct sockaddr *s_saddr;
	struct sockaddr *d_saddr;
	uint32_t reqid = 0;
	u_int32_t seq = 0;
	u_int flags = 0; // always zero
	u_int64_t lifebyte = 0, lifetime = 0;
	//u_int8_t l_natt_type = HIP_UDP_ENCAP_ESPINUDP_NON_IKE;
	u_int8_t l_natt_type = HIP_UDP_ENCAP_ESPINUDP;
	// FIXME: this parameter maybe should be related to some esp parameters (according to racoon source code)
	u_int16_t l_natt_frag = 0;
	/* Mappings from HIP to PFKEY algo names */
	u_int e_types[] = {SADB_EALG_NULL, SADB_X_EALG_AESCBC, SADB_EALG_3DESCBC, SADB_EALG_3DESCBC,
			   SADB_X_EALG_BLOWFISHCBC, SADB_EALG_NULL, SADB_EALG_NULL};
	u_int a_algos[] = {SADB_AALG_NONE, SADB_AALG_SHA1HMAC, SADB_AALG_SHA1HMAC, SADB_AALG_MD5HMAC,
			   SADB_AALG_SHA1HMAC, SADB_AALG_SHA1HMAC, SADB_AALG_MD5HMAC};
	u_int e_type = e_types[ealg];
	u_int a_type = a_algos[aalg];
	in_port_t sport = entry->local_udp_port;
	in_port_t dport = entry->peer_udp_port;

	a_keylen = hip_auth_key_length_esp(ealg);
	e_keylen = hip_enc_key_length(ealg);

	get_random_bytes(&reqid, sizeof(uint32_t));
	get_random_bytes(&seq, sizeof(uint32_t));

	HIP_DEBUG("\n");
	HIP_DEBUG_HIT("src_hit", src_hit);
	HIP_DEBUG_HIT("dst_hit", dst_hit);
	HIP_DEBUG_IN6ADDR("saddr", saddr);
	HIP_DEBUG_IN6ADDR("daddr", daddr);
	HIP_IFEL((!saddr || !daddr), 1, "Addresses not valid when adding SA's\n");

	HIP_IFEL(((so = pfkey_open()) < 0), 1, "ERROR in opening pfkey socket: %s\n", ipsec_strerror());

	s_saddr = (struct sockaddr*) &ss_addr;
	d_saddr = (struct sockaddr*) &dd_addr;
	get_sock_addr_from_in6(s_saddr, saddr);
	get_sock_addr_from_in6(d_saddr, daddr);

	if (direction == HIP_SPI_DIRECTION_OUT)
	{
		entry->outbound_sa_count++;
	}
	else
	{
		entry->inbound_sa_count++;
	}


	// NOTE: port numbers remains in host representation
	if (update) {
		if (sport) {
			// pfkey_send_update_nat when update = 1 and sport != 0
			HIP_IFEBL(((len = pfkey_send_update_nat(so, SADB_SATYPE_ESP, HIP_IPSEC_DEFAULT_MODE, 
								s_saddr, d_saddr, spi, reqid, wsize,
								(void*) enckey, e_type, e_keylen, 
								a_type, a_keylen, flags,
								0, lifebyte, lifetime, 0, seq,
								l_natt_type, sport, dport, NULL,
								l_natt_frag)) < 0),
				  1, pfkey_close(so), "ERROR in updating sa for nat: %s\n", ipsec_strerror());
		} else {
			// pfkey_send_update when update = 1 and sport == 0
			HIP_IFEBL(((len = pfkey_send_update(so, SADB_SATYPE_ESP, HIP_IPSEC_DEFAULT_MODE,
							    s_saddr, d_saddr, spi, reqid, wsize,
							    (void*) enckey, e_type, e_keylen,
							    a_type, a_keylen, flags,
							    0, lifebyte, lifetime, 0, seq)) < 0),
				  1, pfkey_close(so), "ERROR in updating sa: %s\n", ipsec_strerror());
		}
	} else {
		if (sport) {
			// pfkey_send_add_nat when update = 0 and sport != 0 	
			HIP_IFEBL(((len = pfkey_send_add_nat(so, SADB_SATYPE_ESP, HIP_IPSEC_DEFAULT_MODE,
							     s_saddr, d_saddr, spi, reqid, wsize,
							     (void*) enckey, e_type, e_keylen, 
							     a_type, a_keylen, flags,
							     0, lifebyte, lifetime, 0, seq,
							     l_natt_type, sport, dport, NULL,
							     l_natt_frag)) < 0),
				  1, pfkey_close(so), "ERROR in adding sa for nat: %s\n", ipsec_strerror());
		} else {
			// pfkey_send_add when update = 0 and sport == 0
			HIP_IFEBL(((len = pfkey_send_add(so, SADB_SATYPE_ESP, HIP_IPSEC_DEFAULT_MODE,
							 s_saddr, d_saddr, spi, reqid, wsize,
							 (void*) enckey, e_type, e_keylen,
							 a_type, a_keylen, flags,
							 0, lifebyte, lifetime, 0, seq)) < 0),
				  1, pfkey_close(so), "ERROR in adding sa: %s\n", ipsec_strerror());
		}
	}

	return 0;

out_err:
	return err;
}