Example #1
0
/** sends a list of all available anchor elements in the BEX store
 * to the hipd
 *
 * @param   hcstore the BEX store
 * @param   use_hash_trees indicates whether hash chains or hash trees are stored
 * @return  0 on success, -1 on error
 */
int send_bex_store_update_to_hipd(struct hchain_store *hcstore,
                                  const int use_hash_trees)
{
    struct hip_common *msg = NULL;
    int                err = 0;

    HIP_ASSERT(hcstore != NULL);

    HIP_DEBUG("sending bex-store update to hipd...\n");

    HIP_IFEL(!(msg = create_bex_store_update_msg(hcstore, use_hash_trees)),
             -1, "failed to create bex store anchors update message\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;
}
Example #2
0
File: opptcp.c Project: surki/hipl
/**
 * Send the ip of a peer to hipd, so that it can:
 * - unblock the packets that are sent to a particular peer.
 * - add it to the blacklist database.
 *
 * @param peer_ip	peer ip.
 * @return		nothing
 */
int hip_fw_unblock_and_blacklist(const struct in6_addr *peer_ip){
	struct hip_common *msg = NULL;
	int err = 0;

	HIP_DEBUG("\n");

	HIP_IFE(!(msg = hip_msg_alloc()), -1);

	HIP_IFEL(hip_build_param_contents(msg, (void *)(peer_ip),
					HIP_PARAM_IPV6_ADDR,
					sizeof(struct in6_addr)),
			-1, "build param HIP_PARAM_IPV6_ADDR failed\n");

	/* build the message header */
	HIP_IFEL(hip_build_user_hdr(msg, SO_HIP_OPPTCP_UNBLOCK_AND_BLACKLIST, 0),
		 -1, "build hdr failed\n");
	HIP_DUMP_MSG(msg);

	/* send and receive msg to/from hipd */
	HIP_IFEL(hip_send_recv_daemon_info(msg, 1, hip_fw_async_sock), -1, "send_recv msg failed\n");
	_HIP_DEBUG("send_recv msg succeed\n");
	/* check error value */
	HIP_IFEL(hip_get_msg_err(msg), -1, "Got erroneous message!\n");

out_err:
	return err;
}
Example #3
0
File: opptcp.c Project: surki/hipl
/**
 * Send the necessary data to hipd, so that a tcp packet is sent from there. This was done because it was not possible to send a packet directly from here.
 * 
 * @param *hdr		pointer to the packet that is to be sent.
 * @param packet_size	the size of the packet.
 * @param ip_version	ipv4 or ipv6.
 * @param addHit	whether the local HIT is to be added at the tcp options
 * @param addOption	whether the i1 option is to be added at the tcp options
 * @return		nothing
 */
int hip_request_send_tcp_packet(void *hdr,
				int   packet_size,
				int   ip_version,
				int   addHit,
				int   addOption){
	const struct hip_common *msg = NULL;
	int err = 0;
	
	HIP_DEBUG("\n");

	HIP_IFE(!(msg = hip_msg_alloc()), -1);

	HIP_IFEL(hip_build_param_contents(msg, (void *)hdr,
					  HIP_PARAM_IP_HEADER,
					  packet_size),
		-1, "build param HIP_PARAM_IP_HEADER failed\n");
	
	HIP_IFEL(hip_build_param_contents(msg, (int *)(&packet_size),
					  HIP_PARAM_PACKET_SIZE,
					  sizeof(int)),
		-1, "build param HIP_PARAM_PACKET_SIZE failed\n");

	HIP_IFEL(hip_build_param_contents(msg, (int *)(&ip_version),
					  HIP_PARAM_TRAFFIC_TYPE,
					  sizeof(int)),
		-1, "build param HIP_PARAM_TRAFFIC_TYPE failed\n");

	HIP_IFEL(hip_build_param_contents(msg, (int *)(&addHit),
					  HIP_PARAM_ADD_HIT,
					  sizeof(int)),
		-1, "build param HIP_PARAM_ADD_HIT failed\n");

	HIP_IFEL(hip_build_param_contents(msg, (int *)(&addOption),
					  HIP_PARAM_ADD_OPTION,
					  sizeof(int)),
		-1, "build param HIP_PARAM_ADD_OPTION failed\n");

	/* build the message header */
	HIP_IFEL(hip_build_user_hdr(msg, SO_HIP_OPPTCP_SEND_TCP_PACKET, 0),
		-1, "build hdr failed\n");
	HIP_DUMP_MSG(msg);
	/* send and receive msg to/from hipd */
	HIP_IFEL(hip_send_recv_daemon_info(msg, 1, hip_fw_async_sock), -1, "send_recv msg failed\n");
	_HIP_DEBUG("send_recv msg succeed\n");
	/* check error value */
	//HIP_IFEL(hip_get_msg_err(msg), -1, "Got erroneous message!\n");

 out_err:
	return err;
}
Example #4
0
/**
 * connhipd_send_hitdata_to_daemon - builds a param containing hits to be
 * sent to the daemon
 * @param *msg packet to be sent to daemon
 * @param *hitr remote hit accepted
 * @param *hitl local hit used
 * @return 0 on success, -1 on error
 */
int connhipd_send_hitdata_to_daemon(struct hip_common * msg , struct in6_addr * hitr, struct in6_addr * hitl)
{
	int err = 0;
	struct hip_uadb_info uadb_info ;
	char hittest[40];
	HIP_DEBUG("Building User Agent DB info message to be sent to daemon.\n");
	memcpy(&uadb_info.hitr,hitr, sizeof(struct in6_addr)) ;
	memcpy(&uadb_info.hitl,hitl, sizeof(struct in6_addr)) ;
	hip_in6_ntop(&uadb_info.hitr, hittest);
    HIP_DEBUG("Value: %s\n", hittest);
	
	memcpy(uadb_info.cert,"certificate\0",sizeof("certificate\0"));
	
	hip_build_param_hip_uadb_info(msg, &uadb_info);
	HIP_DUMP_MSG (msg);
out_err:
	return (err);
}
Example #5
0
/**
 * 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;
}
Example #6
0
/**
 * 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;
}
Example #7
0
/**
 * Sends the preferred transform to hipd implicitely turning on
 * the esp protection extension there
 *
 * @param   activate 1 to activate, 0 to deactivate the extension in the hipd
 * @return  0 on success, -1 on error
 */
int send_esp_prot_to_hipd(const int activate)
{
    struct hip_common *msg            = NULL;
    int                num_transforms = 0;
    int                err            = 0, i;
    uint8_t            transform      = 0;

    HIP_ASSERT(activate >= 0);

    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_ESP_PROT_TFM, 0), -1,
             "build hdr failed\n");

    if (activate > 0) {
        /*** activation case ***/
        HIP_DEBUG("sending preferred esp prot transforms to hipd...\n");

        // all "in use" transforms + UNUSED
        num_transforms = NUM_TRANSFORMS + 1;

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

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

        HIP_DEBUG("adding num_parallel_hchains: %i\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");

        for (i = 0; i < num_transforms; i++) {
            HIP_DEBUG("adding transform %i: %u\n", i + 1, token_transform);
            HIP_IFEL(hip_build_param_contents(msg, &token_transform,
                                              HIP_PARAM_ESP_PROT_TFM,
                                              sizeof(uint8_t)), -1,
                     "build param contents failed\n");
        }
    } else {
        /*** deactivation case ***/
        HIP_DEBUG("sending esp prot transform ESP_PROT_TFM_UNUSED to hipd...\n");

        // we are only sending ESP_PROT_TFM_UNUSED
        num_transforms = 1;
        transform      = ESP_PROT_TFM_UNUSED;

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

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

        HIP_DEBUG("adding num_parallel_hchains: %i\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");

        HIP_DEBUG("adding transform ESP_PROT_TFM_UNUSED: %u\n", transform);
        HIP_IFEL(hip_build_param_contents(msg, &transform,
                                          HIP_PARAM_ESP_PROT_TFM, sizeof(uint8_t)), -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;
}
static int send_raw_from_one_src(const struct in6_addr *local_addr,
                                 const struct in6_addr *peer_addr,
                                 const in_port_t src_port,
                                 const in_port_t dst_port,
                                 struct hip_common *msg)
{
    int                     err = 0, sa_size, sent, len = 0, dupl, try_again, udp = 0;
    struct sockaddr_storage src, dst;
    int                     src_is_ipv4 = 0, dst_is_ipv4 = 0, memmoved = 0;
    struct sockaddr_in6    *src6        = NULL, *dst6 = NULL;
    struct sockaddr_in     *src4        = NULL, *dst4 = NULL;
    struct in6_addr         my_addr;
    /* Points either to v4 or v6 raw sock */
    int hipfw_raw_sock_output = 0;

    /* Verify the existence of obligatory parameters. */
    HIP_ASSERT(peer_addr != NULL && msg != NULL);

    HIP_DEBUG("Sending %s packet\n",
              hip_message_type_name(hip_get_msg_type(msg)));
    HIP_DEBUG_IN6ADDR("hip_send_raw(): local_addr", local_addr);
    HIP_DEBUG_IN6ADDR("hip_send_raw(): peer_addr", peer_addr);
    HIP_DEBUG("Source port=%d, destination port=%d\n", src_port, dst_port);
    HIP_DUMP_MSG(msg);

    //check msg length
    if (!hip_check_network_msg_len(msg)) {
        err = -EMSGSIZE;
        HIP_ERROR("bad msg len %d\n", hip_get_msg_total_len(msg));
        goto out_err;
    }

    dst_is_ipv4 = IN6_IS_ADDR_V4MAPPED(peer_addr);
    len         = hip_get_msg_total_len(msg);

    /* Some convinient short-hands to avoid too much casting (could be
     * an union as well) */
    src6 = (struct sockaddr_in6 *) &src;
    dst6 = (struct sockaddr_in6 *) &dst;
    src4 = (struct sockaddr_in *) &src;
    dst4 = (struct sockaddr_in *) &dst;

    memset(&src, 0, sizeof(src));
    memset(&dst, 0, sizeof(dst));

    if (dst_port && dst_is_ipv4) {
        HIP_DEBUG("Using IPv4 UDP socket\n");
        hipfw_raw_sock_output = hipfw_nat_sock_output_udp;
        sa_size               = sizeof(struct sockaddr_in);
        udp                   = 1;
    } else if (dst_is_ipv4) {
        HIP_DEBUG("Using IPv4 raw socket\n");
        //hipfw_raw_sock_output = hipfw_raw_sock_output_v4;
        //sa_size             = sizeof(struct sockaddr_in);
    } else {
        HIP_DEBUG("Using IPv6 raw socket\n");
        //hipfw_raw_sock_output = hipfw_raw_sock_output_v6;
        //sa_size             = sizeof(struct sockaddr_in6);
    }

    if (local_addr) {
        HIP_DEBUG("local address given\n");

        memcpy(&my_addr, local_addr, sizeof(struct in6_addr));
    } else {
        HIP_DEBUG("no local address, selecting one\n");
        HIP_IFEL(select_source_address(&my_addr, peer_addr), -1,
                 "Cannot find source address\n");
    }

    src_is_ipv4 = IN6_IS_ADDR_V4MAPPED(&my_addr);

    if (src_is_ipv4) {
        IPV6_TO_IPV4_MAP(&my_addr, &src4->sin_addr);
        src4->sin_family = AF_INET;
        HIP_DEBUG_INADDR("src4", &src4->sin_addr);
    } else {
        memcpy(&src6->sin6_addr, &my_addr,
               sizeof(struct in6_addr));
        src6->sin6_family = AF_INET6;
        HIP_DEBUG_IN6ADDR("src6", &src6->sin6_addr);
    }

    if (dst_is_ipv4) {
        IPV6_TO_IPV4_MAP(peer_addr, &dst4->sin_addr);
        dst4->sin_family = AF_INET;

        HIP_DEBUG_INADDR("dst4", &dst4->sin_addr);
    } else {
        memcpy(&dst6->sin6_addr, peer_addr, sizeof(struct in6_addr));
        dst6->sin6_family = AF_INET6;
        HIP_DEBUG_IN6ADDR("dst6", &dst6->sin6_addr);
    }

    if (src6->sin6_family != dst6->sin6_family) {
        /* @todo: Check if this may cause any trouble.
         * It happens every time we send update packet that contains few locators in msg, one is
         * the IPv4 address of the source, another is IPv6 address of the source. But even if one of
         * them is ok to send raw IPvX to IPvX raw packet, another one cause the trouble, and all
         * updates are dropped.  by Andrey "laser".
         *
         */
        err = -1;
        HIP_ERROR("Source and destination address families differ\n");
        goto out_err;
    }

    hip_zero_msg_checksum(msg);
    if (!udp) {
        msg->checksum = hip_checksum_packet((char *) msg,
                                            (struct sockaddr *) &src,
                                            (struct sockaddr *) &dst);
    }


    /* Handover may cause e.g. on-link duplicate address detection
     * which may cause bind to fail. */

    HIP_IFEL(bind(hipfw_raw_sock_output, (struct sockaddr *) &src, sa_size),
             -1, "Binding to raw sock failed\n");

    /* For some reason, neither sendmsg or send (with bind+connect)
     * do not seem to work properly. Thus, we use just sendto() */

    len = hip_get_msg_total_len(msg);

    if (udp) {
        struct udphdr *uh = (struct udphdr *) msg;

        /* Insert 32 bits of zero bytes between UDP and HIP */
        memmove(((char *) msg) + HIP_UDP_ZERO_BYTES_LEN + sizeof(struct udphdr), msg, len);
        memset(((char *) msg), 0, HIP_UDP_ZERO_BYTES_LEN  + sizeof(struct udphdr));
        len += HIP_UDP_ZERO_BYTES_LEN + sizeof(struct udphdr);

        uh->source = htons(src_port);
        uh->dest   = htons(dst_port);
        uh->len    = htons(len);
        uh->check  = 0;
        memmoved   = 1;
    }

    for (dupl = 0; dupl < 1; dupl++) {
        for (try_again = 0; try_again < 2; try_again++) {
            sent = sendto(hipfw_raw_sock_output, msg, len, 0,
                          (struct sockaddr *) &dst, sa_size);
            if (sent != len) {
                HIP_ERROR("Could not send the all requested" \
                          " data (%d/%d)\n", sent, len);
                HIP_DEBUG("strerror %s\n", strerror(errno));
                sleep(2);
            } else {
                HIP_DEBUG("sent=%d/%d ipv4=%d\n",
                          sent, len, dst_is_ipv4);
                HIP_DEBUG("Packet sent ok\n");
                break;
            }
        }
    }
out_err:

    /* Reset the interface to wildcard or otherwise receiving
     * broadcast messages fails from the raw sockets. A better
     * solution would be to have separate sockets for sending
     * and receiving because we cannot receive a broadcast while
     * sending */
    if (dst_is_ipv4) {
        src4->sin_addr.s_addr = INADDR_ANY;
        src4->sin_family      = AF_INET;
        sa_size               = sizeof(struct sockaddr_in);
    } else {
        struct in6_addr any = IN6ADDR_ANY_INIT;
        src6->sin6_family = AF_INET6;
        ipv6_addr_copy(&src6->sin6_addr, &any);
        sa_size = sizeof(struct sockaddr_in6);
    }
    bind(hipfw_raw_sock_output, (struct sockaddr *) &src, sa_size);

    if (udp && memmoved) {
        /* Remove 32 bits of zero bytes between UDP and HIP */
        len -= HIP_UDP_ZERO_BYTES_LEN + sizeof(struct udphdr);
        memmove((char *) msg, ((char *) msg) + HIP_UDP_ZERO_BYTES_LEN + sizeof(struct udphdr),
                len);
        memset(((char *) msg) + len, 0,
               HIP_UDP_ZERO_BYTES_LEN + sizeof(struct udphdr));
    }

    if (err) {
        HIP_ERROR("strerror: %s\n", strerror(errno));
    }

    return err;
}