コード例 #1
0
ファイル: libhipopendht.c プロジェクト: surki/hipl
/**
 * handle_locator_value - This function copies the 2nd address (ipv4) from
 * the locator from packet returned from lookup
 * 
 * @param *packet response returned from the lookup service
 * @param *locator_ipv4 opaque pointer passed to point to the ipv4 address
 * @return status of the operation 0 on success, -1 on failure
 */
int handle_locator_value (unsigned char *packet, void *locator_ipv4)
{
	struct hip_locator *locator;
	struct hip_locator_info_addr_item *locator_address_item = NULL;
	int locator_item_count = 0;
	struct in6_addr addr6;
	struct in_addr addr4;
   
	locator = hip_get_param((struct hip_common *)packet, HIP_PARAM_LOCATOR);

	if (locator) {
		locator_item_count = hip_get_locator_addr_item_count(locator);
		locator_item_count--;
		locator_address_item = hip_get_locator_first_addr_item(locator);
		memcpy(&addr6, 
			(struct in6_addr*)&locator_address_item[locator_item_count].address, 
				sizeof(struct in6_addr));
		if (IN6_IS_ADDR_V4MAPPED(&addr6)) {
			IPV6_TO_IPV4_MAP(&addr6, &addr4);
			sprintf((char*)locator_ipv4, "%s", inet_ntoa(addr4));
		} else {
			hip_in6_ntop(&addr6, (char*)locator_ipv4);
			_HIP_DEBUG("Value: %s\n", (char*)locator_ipv4);
		}
		return 0 ;
	} else
		return -1;	
}
コード例 #2
0
ファイル: nsupdate.c プロジェクト: surki/hipl
/*
 * This function converts the netdev_address structure src into
 * a character string, which is copied to a character buffer dst, which is cnt bytes long.
 */
const char *netdev_address_to_str(struct netdev_address *src, char *dst, socklen_t cnt)
{
	struct sockaddr *tmp_sockaddr_ptr = (struct sockaddr*) &(src->addr);
	struct sockaddr_in *tmp_sockaddr_in_ptr = (struct sockaddr_in*) tmp_sockaddr_ptr;
	struct sockaddr_in6 *tmp_sockaddr_in6_ptr = (struct sockaddr_in6*) tmp_sockaddr_ptr;

	struct in_addr tmp_in_addr;
	struct in6_addr *tmp_in6_addr_ptr = NULL;

	void *inet_ntop_src = NULL;
	int af = tmp_sockaddr_ptr->sa_family ; // might be changed because of ip4->ip6 mapping

	switch (af) {
		case AF_INET:
			inet_ntop_src = & (tmp_sockaddr_in_ptr->sin_addr);
			break;

		case AF_INET6:
			tmp_in6_addr_ptr = & (tmp_sockaddr_in6_ptr->sin6_addr);
			if (IN6_IS_ADDR_V4MAPPED(tmp_in6_addr_ptr)) {
				IPV6_TO_IPV4_MAP(tmp_in6_addr_ptr, &tmp_in_addr)
				af = AF_INET;
				inet_ntop_src = &tmp_in_addr;
			} else
				inet_ntop_src = tmp_in6_addr_ptr;
			break;
	}
	
	return inet_ntop(af, inet_ntop_src, dst, cnt);
}
コード例 #3
0
ファイル: debug.c プロジェクト: anupash/privseams
/**
 * print a HIT
 *
 * @param debug_level the urgency of the message (DEBUG_LEVEL_XX)
 * @param file the file from where the debug call was made
 * @param line the line of the debug call in the source file
 * @param function the name of function where the debug call is located
 * @param str string to be printed before the HIT
 * @param hit the HIT to be printed
 * @note Do not call this function directly. Instead, use the
 *       HIP_DEBUG_HIT and HIP_INFO_HIT macros.
 */
void hip_print_hit(int debug_level, const char *file, int line, const char *function,
                   const char *str, const struct in6_addr *hit)
{
    if (hit == NULL) {
        HIP_DEBUG("%s: NULL\n", str);
        return;
    } else {
        char dst[INET6_ADDRSTRLEN];

        if (IN6_IS_ADDR_V4MAPPED(hit)) {
            struct in_addr in_addr;
            IPV6_TO_IPV4_MAP(hit, &in_addr);
            hip_print_lsi(debug_level, file, line, function, str, &in_addr);
        } else {
            hip_in6_ntop(hit, dst);
            hip_print_str(debug_level, file, line, function, "%s: %s\n", str, dst);
        }
        return;
    }
}
コード例 #4
0
ファイル: libhipopendht.c プロジェクト: surki/hipl
/** 
 * opendht_read_response - Reads from the given socket and parses the XML RPC response
 * @param sockfd Socket to be used with the send
 * @param answer Buffer where the response value will be saved
 *
 * @return Returns integer, same as in read_packet_content
 * TODO: see read_packet_content
 */
int opendht_read_response(int sockfd, char * answer)
{
    int ret = 0, pton_ret = 0;
    int bytes_read = 0, total = 0;
    char read_buffer[HIP_MAX_PACKET];
    //char tmp_buffer[HIP_MAX_PACKET];
    struct in_addr ipv4;
    struct in6_addr ipv6 = {0};

    if (sockfd <= 0 || answer == NULL) {
	    HIP_ERROR("sockfd=%p, answer=%p\n", sockfd, answer);
	    return -1;
    }

    memset(read_buffer, '\0', sizeof(read_buffer));
    do
        {
            bytes_read = recv(sockfd, &read_buffer[total],
			      sizeof(read_buffer), 0);
	    total += bytes_read;
        }
    while (bytes_read > 0 && total < sizeof(read_buffer) - 1);

    /* Parse answer */
    memset(answer, '\0', 1);
    ret = 0;
    ret = read_packet_content(read_buffer, answer);

    /* If answer was IPv4 address mapped to IPv6 revert to IPv4 format*/
    pton_ret = inet_pton(AF_INET6, answer, &ipv6);

    if (pton_ret && IN6_IS_ADDR_V4MAPPED(&ipv6)) {
	    IPV6_TO_IPV4_MAP(&ipv6, &ipv4);
	    sprintf(answer, "%s", inet_ntoa(ipv4));
    }

 out_err:

    return ret;
}
コード例 #5
0
ファイル: lsi.c プロジェクト: surki/hipl
int hip_fw_handle_incoming_hit(ipq_packet_msg_t *m,
			       struct in6_addr *ip_src,
			       struct in6_addr *ip_dst,
			       int lsi_support,
			       int sys_opp_support)
{
        int bind6 = 0, proto4_LSI = 0, proto4_IP = 0, err = 0, verdict = 1;
	int ip_hdr_size = 0, portDest = 0, process_as_lsi;
	char *proto = NULL;
	hip_lsi_t lsi_our = {0}, lsi_peer = {0};
	struct in6_addr src_addr, dst_addr;
	struct in_addr src_v4, dst_v4;
	struct ip6_hdr* ip6_hdr = (struct ip6_hdr*) m->payload;
	firewall_port_cache_hl_t *port_cache_entry = NULL;

	ip_hdr_size = sizeof(struct ip6_hdr);

	switch (ip6_hdr->ip6_nxt) {
	case IPPROTO_UDP:
		portDest = ((struct udphdr*)((m->payload) + ip_hdr_size))->dest;
		proto = "udp6";
		break;
	case IPPROTO_TCP:
		portDest = ((struct tcphdr*)((m->payload) + ip_hdr_size))->dest;
		proto = "tcp6";
		break;
	case IPPROTO_ICMPV6:
		HIP_DEBUG("ICMPv6 packet\n");
		//goto out_err;
		break;
	default:
		HIP_DEBUG("Unhandled packet %d\n", ip6_hdr->ip6_nxt);
		//goto out_err;
		break;
	}

	/* port caching */
	port_cache_entry = firewall_port_cache_db_match(portDest,
							ip6_hdr->ip6_nxt);

	if( port_cache_entry &&
	    (port_cache_entry->traffic_type ==
	     FIREWALL_PORT_CACHE_IPV6_TRAFFIC) ){
		verdict = 1;
		HIP_DEBUG("Cached port, accepting\n");
		goto out_err;
	}

	if (sys_opp_support && lsi_support) {
		/* Currently preferring LSIs over opp. connections */
		process_as_lsi = 1;
	} else if (lsi_support) {
		process_as_lsi = 1;
	} else if (sys_opp_support) {
		process_as_lsi = 0;
	} else {
		HIP_ASSERT(1);
	}

	//HIP_IFEL(firewall_cache_db_match(ip_src, ip_dst,
	HIP_IFEL(firewall_cache_db_match(ip_dst, ip_src,
				&lsi_our, &lsi_peer,
				&dst_addr, &src_addr,
				NULL),
		-1, "Failed to obtain from cache\n");

	if (process_as_lsi) {
		HIP_DEBUG("Trying lsi transformation\n");
		HIP_DEBUG_LSI("lsi_our: ", &lsi_our);
		HIP_DEBUG_LSI("lsi_peer: ", &lsi_peer);
		IPV4_TO_IPV6_MAP(&lsi_our, &src_addr);
		IPV4_TO_IPV6_MAP(&lsi_peer, &dst_addr);
		HIP_IFEL(reinject_packet(&dst_addr, &src_addr, m, 6, 1), -1,
			 "Failed to reinject with LSIs\n");
		HIP_DEBUG("Successful LSI transformation.\n");

		if (ip6_hdr->ip6_nxt == IPPROTO_ICMPV6)
			verdict = 1; /* broadcast: dst may be ipv4 or ipv6 */
		else
			verdict = 0; /* drop original */
	} else {
		HIP_DEBUG("Trying sys opp transformation\n");
		IPV6_TO_IPV4_MAP(&src_addr, &src_v4);
		IPV6_TO_IPV4_MAP(&dst_addr, &dst_v4);
		HIP_DEBUG_IN6ADDR("ip_src: ", &src_addr);
		HIP_DEBUG_IN6ADDR("ip_dst: ", &dst_addr);
		HIP_IFEL(reinject_packet(&src_addr, &dst_addr, m, 6, 1), -1,
			 "Failed to reinject with IP addrs\n");
		HIP_DEBUG("Successfull sysopp transformation. Drop orig\n");
		verdict = 0;
	}

out_err:

	if (err)
		return 1; /* Accept original */
	else
		return verdict;
}
コード例 #6
0
ファイル: reinject.c プロジェクト: anupash/privseams
/**
 * Translate and reinject an incoming packet back to the networking stack.
 * Supports TCP, UDP and ICMP. LSI code uses this to translate
 * the HITs from an incoming packet to the corresponding LSIs. Also,
 * the system-based opportunistic mode uses this to translate the HITs of
 * an incoming packet to an IPv4 or IPv6 address.
 *
 * @param src_hit source HIT of the packet
 * @param dst_hit destination HIT of the packet
 * @param msg a pointer to the transport layer header of the packet
 * @param len the length of the packet in bytes
 * @param proto the transport layer protocol of the packet
 * @param ttl new ttl value for the transformed packet
 *
 * @return zero on success and non-zero on error
 */
int hip_firewall_send_incoming_pkt(const struct in6_addr *src_hit,
                                   const struct in6_addr *dst_hit,
                                   uint8_t *msg, uint16_t len,
                                   int proto,
                                   int ttl)
{
    int                     err               = 0, sent, sa_size;
    int                     firewall_raw_sock = 0, is_ipv6 = 0, on = 1;
    struct ip              *iphdr             = NULL;
    struct udphdr          *udp               = NULL;
    struct tcphdr          *tcp               = NULL;
    struct icmphdr         *icmp              = NULL;
    struct sockaddr_storage src               = { 0 }, dst       = { 0 };
    struct sockaddr_in6    *sock_src6         = NULL, *sock_dst6 = NULL;
    struct sockaddr_in     *sock_src4         = NULL, *sock_dst4 = NULL;
    struct in6_addr         any               = IN6ADDR_ANY_INIT;

    HIP_ASSERT(src_hit != NULL && dst_hit != NULL);

    sock_src4 = (struct sockaddr_in *) &src;
    sock_dst4 = (struct sockaddr_in *) &dst;
    sock_src6 = (struct sockaddr_in6 *) &src;
    sock_dst6 = (struct sockaddr_in6 *) &dst;

    if (IN6_IS_ADDR_V4MAPPED(src_hit)) {
        sock_src4->sin_family = AF_INET;
        sock_dst4->sin_family = AF_INET;
        IPV6_TO_IPV4_MAP(src_hit, &sock_src4->sin_addr);
        IPV6_TO_IPV4_MAP(dst_hit, &sock_dst4->sin_addr);
        sa_size = sizeof(struct sockaddr_in);
        HIP_DEBUG_LSI("src4 addr ", &sock_src4->sin_addr);
        HIP_DEBUG_LSI("dst4 addr ", &sock_dst4->sin_addr);
    } else {
        sock_src6->sin6_family = AF_INET6;
        ipv6_addr_copy(&sock_src6->sin6_addr, src_hit);
        sock_dst6->sin6_family = AF_INET6;
        ipv6_addr_copy(&sock_dst6->sin6_addr, dst_hit);
        sa_size = sizeof(struct sockaddr_in6);
        is_ipv6 = 1;
    }

    switch (proto) {
    case IPPROTO_UDP:
        if (is_ipv6) {
            HIP_DEBUG(" IPPROTO_UDP v6\n");
            firewall_raw_sock              = firewall_raw_sock_udp_v6;
            ((struct udphdr *) msg)->check = ipv6_checksum(IPPROTO_UDP,
                                                           &sock_src6->sin6_addr,
                                                           &sock_dst6->sin6_addr, msg, len);
        } else {
            HIP_DEBUG(" IPPROTO_UDP v4\n");
            firewall_raw_sock = firewall_raw_sock_udp_v4;

            udp = (struct udphdr *) msg;

            sa_size = sizeof(struct sockaddr_in);

            udp->check = htons(0);
            udp->check = ipv4_checksum(IPPROTO_UDP,
                                       (uint8_t *) &sock_src4->sin_addr,
                                       (uint8_t *) &sock_dst4->sin_addr,
                                       (uint8_t *) udp, len);
            memmove(msg + sizeof(struct ip), udp, len);
        }
        break;
    case IPPROTO_TCP:
        tcp        = (struct tcphdr *) msg;
        tcp->check = htons(0);

        if (is_ipv6) {
            HIP_DEBUG(" IPPROTO_TCP v6\n");
            firewall_raw_sock = firewall_raw_sock_tcp_v6;
            tcp->check        = ipv6_checksum(IPPROTO_TCP, &sock_src6->sin6_addr,
                                              &sock_dst6->sin6_addr, msg, len);
        } else {
            HIP_DEBUG(" IPPROTO_TCP v4\n");
            firewall_raw_sock = firewall_raw_sock_tcp_v4;

            tcp->check = ipv4_checksum(IPPROTO_TCP,
                                       (uint8_t *) &sock_src4->sin_addr,
                                       (uint8_t *) &sock_dst4->sin_addr,
                                       (uint8_t *) tcp, len);

            memmove(msg + sizeof(struct ip), tcp, len);
        }
        break;
    case IPPROTO_ICMP:
        firewall_raw_sock = firewall_raw_sock_icmp_v4;
        icmp              = (struct icmphdr *) msg;
        icmp->checksum    = htons(0);
        icmp->checksum    = inchksum(icmp, len);
        memmove(msg + sizeof(struct ip), icmp, len);
        break;
    case IPPROTO_ICMPV6:
        goto not_sending;
        break;
    default:
        HIP_ERROR("No protocol family found\n");
        break;
    }

    if (!is_ipv6) {
        iphdr         = (struct ip *) msg;
        iphdr->ip_v   = 4;
        iphdr->ip_hl  = sizeof(struct ip) >> 2;
        iphdr->ip_tos = 0;
        iphdr->ip_len = len + iphdr->ip_hl * 4;
        iphdr->ip_id  = htons(0);
        iphdr->ip_off = 0;
        iphdr->ip_ttl = ttl;
        iphdr->ip_p   = proto;
        iphdr->ip_src = sock_src4->sin_addr;
        iphdr->ip_dst = sock_dst4->sin_addr;
        iphdr->ip_sum = htons(0);

        /* @todo: move the socket option to fw initialization */
        if (setsockopt(firewall_raw_sock, IPPROTO_IP,
                       IP_HDRINCL, &on, sizeof(on))) {
            HIP_IFEL(err, -1, "setsockopt IP_HDRINCL ERROR\n");
        }

        sent = sendto(firewall_raw_sock, iphdr,
                      iphdr->ip_len, 0,
                      (struct sockaddr *) &dst, sa_size);
        if (sent != (int) (len + sizeof(struct ip))) {
            HIP_ERROR("Could not send the all requested" \
                      " data (%d/%d)\n", sent,
                      iphdr->ip_len);
        } else {
            HIP_DEBUG("sent=%d/%d \n",
                      sent, (len + sizeof(struct ip)));
            HIP_DEBUG("Packet sent ok\n");
        }
    }
コード例 #7
0
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;
}