Beispiel #1
0
/**
 * Update firewall on host association state. Currently used by the
 * LSI mode in the firewall.
 *
 * @param action HIP_MSG_FW_UPDATE_DB or HIP_MSG_FW_BEX_DONE
 * @param hit_s optional source HIT
 * @param hit_r optional destination HIT
 *
 * @return zero on success or negative on failure
 */
int hip_firewall_set_bex_data(int action, struct in6_addr *hit_s, struct in6_addr *hit_r)
{
    struct hip_common *msg = NULL;
    int                err = 0, n = 0, r_is_our;

    if (!hip_get_firewall_status()) {
        goto out_err;
    }

    /* Makes sure that the hits are sent always in the same order */
    r_is_our = hip_hidb_hit_is_our(hit_r);

    HIP_IFEL(!(msg = malloc(HIP_MAX_PACKET)), -1, "alloc\n");
    hip_msg_init(msg);
    HIP_IFEL(hip_build_user_hdr(msg, action, 0), -1,
             "Build hdr failed\n");

    HIP_IFEL(hip_build_param_contents(msg,
                                      r_is_our ? hit_s : hit_r, HIP_PARAM_HIT,
                                      sizeof(struct in6_addr)), -1, "build param contents failed\n");
    HIP_IFEL(hip_build_param_contents(msg,
                                      r_is_our ? hit_r : hit_s, HIP_PARAM_HIT,
                                      sizeof(struct in6_addr)), -1, "build param contents failed\n");

    n = sendto(hip_firewall_sock_lsi_fd,
               (char *) msg,
               hip_get_msg_total_len(msg),
               0,
               (struct sockaddr *) &hip_firewall_addr,
               sizeof(struct sockaddr_in6));

    HIP_IFEL(n < 0, -1, "Send to firewall failed. str errno %s\n", strerror(errno));

    HIP_DEBUG("BEX DATA Send to firewall OK.\n");

out_err:
    free(msg);
    return err;
}
Beispiel #2
0
int hip_send_recv_daemon_info(struct hip_common *msg, int send_only, int opt_socket) {
	int hip_user_sock = 0, err = 0, n, len;
	struct sockaddr_in6 addr;

	if (!send_only)
		return hip_send_recv_daemon_info_internal(msg, opt_socket);

	if (opt_socket) {
		hip_user_sock = opt_socket;
	} else {
		HIP_IFE(((hip_user_sock = socket(AF_INET6, SOCK_DGRAM, 0)) < 0), -1);
		memset(&addr, 0, sizeof(addr));
		addr.sin6_family = AF_INET6;
		addr.sin6_addr = in6addr_loopback;
		
		HIP_IFEL(hip_daemon_bind_socket(hip_user_sock,
						(struct sockaddr *) &addr), -1,
			 "bind failed\n");
		HIP_IFEL(hip_daemon_connect(hip_user_sock), -1,
			 "connect failed\n");
	}

	len = hip_get_msg_total_len(msg);
	n = send(hip_user_sock, msg, len, 0);

	if (n < len) {
		HIP_ERROR("Could not send message to daemon.\n");
		err = -1;
		goto out_err;
	}

 out_err:
	if (!opt_socket && hip_user_sock)
		close(hip_user_sock);

	return err;
}
Beispiel #3
0
/**
	Handle message from agent socket.
*/
int connhipd_handle_msg(struct hip_common *msg,
                        struct sockaddr_un *addr)
{
	/* Variables. */
	struct hip_tlv_common *param = NULL, *param2 = NULL;
	struct hip_common *emsg;
	hip_hdr_type_t type;
	HIT_Remote hit, *r;
	HIT_Local *l;
	socklen_t alen;
	struct in6_addr *lhit, *rhit;
	int err = 0, ret, n, direction, check;
	char chit[128], *type_s;
	
	struct in6_addr hitr ;
	type = hip_get_msg_type(msg);

	if (type == SO_HIP_AGENT_PING_REPLY)
	{
		HIP_DEBUG("Received ping reply from daemon. Connection to daemon established.\n");
		gui_set_info(lang_get("gui-info-000"));
		hip_agent_connected = 1;
	}
	else if (type == SO_HIP_SET_NAT_ON)
	{
		gui_update_nat(1);
		HIP_DEBUG("NAT extensions on.\n");
	}
	else if (type == SO_HIP_SET_NAT_OFF)
	{
		gui_update_nat(0);
		HIP_DEBUG("NAT extensions off.\n");
	}
	else if (type == SO_HIP_DAEMON_QUIT)
	{
		HIP_DEBUG("Daemon quit. Waiting daemon to wake up again...\n");
		gui_set_info(lang_get("gui-info-001"));
		hip_agent_connected = 0;
	}
	else if (type == SO_HIP_ADD_DB_HI)
	{
		HIP_DEBUG("Message received successfully from daemon with type"
		          " HIP_ADD_DB_HI (%d).\n", type);
		n = 0;

		while((param = hip_get_next_param(msg, param)))
		{
			if (hip_get_param_type(param) == HIP_PARAM_HIT)
			{
				lhit = (struct in6_addr *)hip_get_param_contents_direct(param);
				HIP_HEXDUMP("Adding local HIT:", lhit, 16);
				print_hit_to_buffer(chit, lhit);
				hit_db_add_local(chit, lhit);
				n++;
			}
		}
	}
	else if (type == SO_HIP_UPDATE_HIU)
	{
		n = 0;
		
		gui_hiu_clear();
		
		while((param = hip_get_next_param(msg, param)))
		{
			/*param2 = hip_get_next_param(msg, param);
			if (param2 == NULL) break;*/
			
			if (hip_get_param_type(param) == HIP_PARAM_HIT)/* &&
			    hip_get_param_type(param2) == HIP_PARAM_HIT)*/
			{
				rhit = (struct in6_addr *)hip_get_param_contents_direct(param);
				//lhit = hip_get_param_contents_direct(param2);
				r = hit_db_find(NULL, rhit);
				if (r)
				{
					gui_hiu_add(r);
					n++;
				}
			}
		}
		
		gui_hiu_count(n);
	}
	else if (type == HIP_I1 || type == HIP_R1)
	{
		NAMECPY(hit.name, "");
		URLCPY(hit.url, "<notset>");
		URLCPY(hit.port, "");

		HIP_DEBUG("Message from daemon, %d bytes.\n", hip_get_msg_total_len(msg));

		/* Get original message, which is encapsulated inside received one. */
		emsg = (struct hip_common *)hip_get_param_contents(msg, HIP_PARAM_ENCAPS_MSG);
		HIP_IFEL(!emsg, -1, "Could not get msg parameter!\n");

		HIP_HEXDUMP("msg->hits: ", &emsg->hits, 16);
		HIP_HEXDUMP("msg->hitr: ", &emsg->hitr, 16);

		/* Find out, which of the HITs in the message is local HIT. */
		l = hit_db_find_local(NULL, &emsg->hits);
		if (!l)
		{
			l = hit_db_find_local(NULL, &emsg->hitr);
			if (l)
			{
				memcpy(&hit.hit, &emsg->hits, sizeof(hit.hit));
			}
			HIP_IFEL(!l, -1, "Did not find local HIT for message!\n");
		}
		else
		{
			memcpy(&hit.hit, &emsg->hitr, sizeof(hit.hit));
		}

		HIP_DEBUG("Received %s %s from daemon.\n", "incoming",
		          type == HIP_I1 ? "I1" : "R1");

		/* Check the remote HIT from database. */
		if (l) 
		{
			memcpy(&hitr,&hit.hit, sizeof(struct in6_addr));
			ret = check_hit(&hit, 0);
			/*Send our hits -- peer hit to daemon*/
			if (ret == 1)
				ret = 0; /*hit already exist in the database and is accepted
							so no need to send it to daemon*/
			else if (ret == 0)
				connhipd_send_hitdata_to_daemon (msg, &hitr, &hit.g->l->lhit) ;
			/* Reset local HIT, if outgoing I1. */
			/*HIP_HEXDUMP("Old local HIT: ", &msg->hits, 16);
			HIP_HEXDUMP("New local HIT: ", &hit.g->l->lhit, 16);
			HIP_HEXDUMP("Old remote HIT: ", &msg->hitr, 16);
			HIP_HEXDUMP("New remote HIT: ", &hit.hit, 16);*/
		}
		/* If neither HIT in message was local HIT, then drop the packet! */
		else
		{
			HIP_DEBUG("Failed to find local HIT from database for packet."
			          " Rejecting packet automatically.\n");
			HIP_HEXDUMP("msg->hits: ", &msg->hits, 16);
			HIP_HEXDUMP("msg->hitr: ", &msg->hits, 16);
			ret = -1;
		}
		
		/*
			Now either reject or accept the packet,
			according to previous results.
		*/
		if (ret == 0)
		{
			HIP_DEBUG("Message accepted, sending back to daemon, %d bytes.\n",
                      hip_get_msg_total_len(msg));
			n = hip_send_recv_daemon_info((char *)msg, 1, hip_agent_sock);
			HIP_IFEL(n < 0, -1, "Could not send message back to daemon"
			                    " (%d: %s).\n", errno, strerror(errno));
			HIP_DEBUG("Reply sent successfully.\n");
		}
		else if (type == HIP_R1)
		{
			HIP_DEBUG("Message rejected.\n");
			n = 1;
			HIP_IFE(hip_build_param_contents(msg, &n, HIP_PARAM_AGENT_REJECT, sizeof(n)), -1);
			n = hip_send_recv_daemon_info((char *)msg, 1, hip_agent_sock);
			HIP_IFEL(n < 0, -1, "Could not send message back to daemon"
			                    " (%d: %s).\n", errno, strerror(errno));
			HIP_DEBUG("Reply sent successfully.\n");
		}
		else
		{
			HIP_DEBUG("Message rejected.\n");
		}
	}

out_err:
//	HIP_DEBUG("Message handled.\n");
	return (err);
}
Beispiel #4
0
/**
	This thread keeps the HIP daemon connection alive.
*/
void *connhipd_thread(void *data)
{
	/* Variables. */
	int err = 0, n, len, ret, max_fd;
	struct sockaddr_in6 agent_addr;
	struct hip_common *msg = (struct hip_common *)data;
	socklen_t alen;
	fd_set read_fdset;
	struct timeval tv;

	HIP_DEBUG("Waiting messages...\n");

	/* Start handling. */
	hip_agent_thread_started = 1;
	while (hip_agent_thread_started)
	{
		FD_ZERO(&read_fdset);
		FD_SET(hip_agent_sock, &read_fdset);
		max_fd = hip_agent_sock;
		tv.tv_sec = 1;
		tv.tv_usec = 0;

		if (hip_agent_connected < 1)
		{
			/* Test connection. */
			//HIP_IFEL(hip_agent_connected < -60, -1, "Could not connect to daemon.\n");
			//HIP_DEBUG("Pinging daemon...\n");
			hip_build_user_hdr(msg, SO_HIP_AGENT_PING, 0);
			n = hip_send_recv_daemon_info((char *)msg, 1, hip_agent_sock);
			//if (n < 0) HIP_DEBUG("Could not send ping to daemon, waiting.\n");
			hip_agent_connected--;
		}
		
		/* Wait for incoming packets. */
		if (select(max_fd + 1, &read_fdset, NULL,NULL, &tv) == -1)
		{
			HIP_ERROR("select() error: %s.\n", strerror(errno));
			err = -1;
			goto out_err;
		}

		if (!hip_agent_thread_started) continue;
		if (!FD_ISSET(hip_agent_sock, &read_fdset)) continue;

		memset(&agent_addr, 0, sizeof(agent_addr));
		alen = sizeof(agent_addr);
		n = recvfrom(hip_agent_sock, msg, sizeof(struct hip_common), MSG_PEEK,
		             (struct sockaddr *)&agent_addr, &alen);
		if (n < 0)
		{
			HIP_ERROR("Error receiving message header from daemon.\n");
			err = -1;
			goto out_err;
		}

//		HIP_DEBUG("Header received successfully\n");
		alen = sizeof(agent_addr);
		len = hip_get_msg_total_len(msg);

		n = recvfrom(hip_agent_sock, msg, len, 0,
		             (struct sockaddr *)&agent_addr, &alen);

		if (n < 0)
		{
			HIP_ERROR("Error receiving message parameters from daemon.\n");
			err = -1;
			goto out_err;
		}

		//HIP_DEBUG("Received message from daemon (%d bytes)\n", n);

		//HIP_ASSERT(n == len);
		if (n != len) {
			HIP_ERROR("Received packet length and HIP msg len dont match %d != %d!!!\n", n, len);
			continue;
		}

		if (agent_addr.sin6_port != ntohs(HIP_DAEMON_LOCAL_PORT)) {
			HIP_DEBUG("Drop, message not from hipd");
			continue;
		}

		connhipd_handle_msg(msg, &agent_addr);
	}


out_err:
	/* Send quit message to daemon. */
	hip_build_user_hdr(msg, SO_HIP_AGENT_QUIT, 0);
	n = hip_send_recv_daemon_info((char *)msg, 1, hip_agent_sock);
	if (n < 0)
		HIP_ERROR("Could not send quit message to daemon.\n");

	if (hip_agent_sock)
		close(hip_agent_sock);
	if (msg != NULL)
		HIP_FREE(msg);

	hip_agent_thread_started = 0;
	agent_exit();

	HIP_DEBUG("Connection thread exit.\n");

	/* This function cannot have a returning value */
	/*return (err);*/

}
Beispiel #5
0
/**
 * Finds out how much data is coming from a socket
 *
 * @param  socket         a file descriptor.
 * @param  encap_hdr_size udp etc header size
 * @param  timeout        -1 for blocking sockets, 0 or positive nonblocking
 * @return Number of bytes received on success or a negative error value on
 *         error.
 */
int hip_peek_recv_total_len(int socket, int encap_hdr_size,
			    unsigned long timeout)
{
	int bytes = 0, err = 0, flags = MSG_PEEK;
	unsigned long timeout_left = timeout;
	int hdr_size = encap_hdr_size + sizeof(struct hip_common);
	char *msg = NULL;
	hip_common_t *hip_hdr = NULL;
	struct timespec ts;

	ts.tv_sec = 0;
	ts.tv_nsec =  100000000;

        /* We're using system call here add thus reseting errno. */
	errno = 0;

	msg = (char *)malloc(hdr_size);
	HIP_IFEL(!msg, -ENOMEM, "Error allocating memory.\n");

	/* Make sure the socket does not block (bug id 806) */
	if (timeout >= 0)
		flags |= MSG_DONTWAIT;

	do {
		errno = 0;
		nanosleep(&ts, NULL);
		bytes = recv(socket, msg, hdr_size, flags);
		timeout_left -= ts.tv_nsec;
		_HIP_DEBUG("tol=%ld, ts=%ld, bytes=%d errno=%d\n",
			   timeout_left, ts.tv_nsec, bytes, errno);
	} while (timeout_left > 0 && errno == EAGAIN && bytes < 0);

	if(bytes < 0) {
		HIP_ERROR("recv() peek error (is hipd running?)\n");
		err = -EAGAIN;
		goto out_err;
	} else if (bytes < hdr_size) {
		HIP_ERROR("Packet payload is smaller than HIP header. Dropping.\n");
		/* Read and discard the datagram */
		recv(socket, msg, 0, 0);
		err = -bytes;
		goto out_err;
	}

	hip_hdr = (struct hip_common *) (msg + encap_hdr_size);
	bytes = hip_get_msg_total_len(hip_hdr);

	if(bytes == 0) {
		HIP_ERROR("HIP message is of zero length. Dropping.\n");
		recv(socket, msg, 0, 0);
		err = -EBADMSG;
		errno = EBADMSG;
		goto out_err;
	}

	/* The maximum possible length value is equal to HIP_MAX_PACKET.
	if(bytes > HIP_MAX_PACKET) {
		HIP_ERROR("HIP message max length exceeded. Dropping.\n");
		recv(socket, msg, 0, 0);
		err = -EMSGSIZE;
		errno = EMSGSIZE;
		goto out_err;
	} */

	bytes += encap_hdr_size;

 out_err:
	if (msg != NULL)
		free(msg);

	if (err)
		return err;

	return bytes;
}
Beispiel #6
0
/*
 * Don't call this function directly. Use hip_send_recv_daemon_info instead
 */
int hip_send_recv_daemon_info_internal(struct hip_common *msg, int opt_socket) {

	int hip_user_sock = 0, err = 0, n = 0, len = 0;
	struct sockaddr_in6 addr;
	uint8_t msg_type_old, msg_type_new;
	
	msg_type_old = hip_get_msg_type(msg);

	// We're using system call here and thus reseting errno.
	errno = 0;

	if (opt_socket) {
		hip_user_sock = opt_socket;
	} else {
		HIP_IFE(((hip_user_sock = socket(AF_INET6, SOCK_DGRAM, 0)) < 0), EHIP);

		memset(&addr, 0, sizeof(addr));
		addr.sin6_family = AF_INET6;
		addr.sin6_addr = in6addr_loopback;

		HIP_IFEL(hip_daemon_bind_socket(hip_user_sock,
						(struct sockaddr *) &addr), -1,
			 "bind failed\n");
		/* Connect to hipd. Otherwise e.g. "hipconf get ha all"
		   blocks when hipd is not running. */
		HIP_IFEL(hip_daemon_connect(hip_user_sock), -1,
			 "connect failed\n");
	}

	if ((len = hip_get_msg_total_len(msg)) < 0) {
		err = -EBADMSG;
		goto out_err;
	}

	/* Require a response from hipd */
	hip_set_msg_response(msg, 1);

	n = hip_sendto_hipd(hip_user_sock, msg, len);
	if (n < len) {
		HIP_ERROR("Could not send message to daemon.\n");
		err = -ECOMM;
		goto out_err;
	}

	HIP_DEBUG("Waiting to receive daemon info.\n");

	if((len = hip_peek_recv_total_len(hip_user_sock, 0, HIP_DEFAULT_MSG_TIMEOUT)) < 0) {
		err = len;
		goto out_err;
	}

	n = recv(hip_user_sock, msg, len, 0);

	/* You have a message synchronization problem if you see this error. */
	msg_type_new = hip_get_msg_type(msg);
	HIP_IFEL((msg_type_new != msg_type_old), -1,
		 "Message sync problem. Expected %d, got %d\n",
		 msg_type_old, msg_type_new);

	HIP_DEBUG("%d bytes received from HIP daemon\n", n);

	if (n == 0) {
		HIP_INFO("The HIP daemon has performed an "\
			 "orderly shutdown.\n");
		// Note. This is not an error condition, thus we return zero.
		goto out_err;
	} else if(n < sizeof(struct hip_common)) {
		HIP_ERROR("Could not receive message from daemon.\n");
		goto out_err;
	}

	if (hip_get_msg_err(msg)) {
		HIP_ERROR("HIP message contained an error.\n");
		err = -EHIP;
	}

	_HIP_DEBUG("Message received successfully\n");

 out_err:

	if (!opt_socket && hip_user_sock)
		close(hip_user_sock);

	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;
}