Пример #1
0
/** creates a new hash chain
 *
 * @param       hash_func hash function to be used to generate the hash values
 * @param       hash_length length of the hash values
 * @param       hchain_length number of hash elements
 * @param       hchain_hierarchy the hierarchy level this hash chain will belong to
 * @param       link_tree the link tree, if HHL is used
 * @return  pointer to the newly created hash chain, NULL on error
 */
struct hash_chain *hchain_create(const hash_function hash_func,
                                 const int hash_length,
                                 const int hchain_length,
                                 const int hchain_hierarchy,
                                 struct hash_tree *link_tree)
{
    struct hash_chain *hchain = NULL;
    /* the hash function output might be longer than needed
     * allocate enough memory for the hash function output
     *
     * @note we also allow a concatenation with the link tree root and the jump chain element here */
    unsigned char hash_value[3 * MAX_HASH_LENGTH];
    int           hash_data_length = 0;
    int           i, err = 0;

    HIP_ASSERT(hash_func != NULL);
    // make sure that the hash we want to use is smaller than the max output
    HIP_ASSERT(hash_length > 0 && hash_length <= MAX_HASH_LENGTH);
    HIP_ASSERT(hchain_length > 0);
    HIP_ASSERT(!(hchain_hierarchy == 0 && link_tree));

    // allocate memory for a new hash chain
    HIP_IFEL(!(hchain = calloc(1, sizeof(struct hash_chain))), -1,
             "failed to allocate memory\n");

    // allocate memory for the hash chain elements
    HIP_IFEL(!(hchain->elements = calloc(1, hash_length * hchain_length)),
             -1, "failed to allocate memory\n");

    // set the link tree if we are using different hierarchies
    if (link_tree) {
        hchain->link_tree = link_tree;
        hash_data_length  = 2 * hash_length;
    } else {
        hchain->link_tree = NULL;
        hash_data_length  = hash_length;
    }

    for (i = 0; i < hchain_length; i++) {
        if (i > 0) {
            // (input, input_length, output) -> output_length == 20
            HIP_IFEL(!(hash_func(hash_value, hash_data_length, hash_value)), -1,
                     "failed to calculate hash\n");
            // only consider highest bytes of digest with length of actual element
            memcpy(&hchain->elements[i * hash_length], hash_value, hash_length);
        } else {
            // random bytes as seed -> need a copy in hash_value for further computations
            HIP_IFEL(RAND_bytes(hash_value, hash_length) <= 0, -1,
                     "failed to get random bytes for source element\n");

            memcpy(&hchain->elements[i * hash_length], hash_value, hash_length);
        }

        /* concatenate used part of the calculated hash with the link tree root */
        if (link_tree) {
            memcpy(&hash_value[hash_length], link_tree->root, link_tree->node_length);
        }
    }

    hchain->hash_function    = hash_func;
    hchain->hash_length      = hash_length;
    hchain->hchain_length    = hchain_length;
    hchain->current_index    = hchain_length;
    hchain->hchain_hierarchy = hchain_hierarchy;

    HIP_DEBUG("Hash-chain with %i elements of length %i created!\n",
              hchain_length,
              hash_length);

out_err:
    if (err) {
        // hchain was fully created
        hchain_free(hchain);
        hchain = NULL;
    }

    return hchain;
}
Пример #2
0
/* getter function for the hash chain anchor element
 *
 * @param       hash_chain hash chain from which the anchor should be returned
 * @return      anchor element of the given hash chain
 */
unsigned char *hchain_get_anchor(const struct hash_chain *hash_chain)
{
    HIP_ASSERT(hash_chain);

    return hchain_element_by_index(hash_chain, hash_chain->hchain_length - 1);
}
Пример #3
0
/* Moved function doxy descriptor to the header file. Lauri 11.03.2008 */
int hip_read_control_msg_all(int socket, struct hip_common *hip_msg,
                             struct in6_addr *saddr,
                             struct in6_addr *daddr,
                             hip_portpair_t *msg_info,
                             int encap_hdr_size, int is_ipv4)
{
	struct sockaddr_storage addr_from, addr_to;
	struct sockaddr_in *addr_from4 = ((struct sockaddr_in *) &addr_from);
	struct sockaddr_in6 *addr_from6 =
		((struct sockaddr_in6 *) &addr_from);
        struct cmsghdr *cmsg;
        struct msghdr msg;
	union {
		struct in_pktinfo *pktinfo_in4;
		struct inet6_pktinfo *pktinfo_in6;
	} pktinfo;
        struct iovec iov;
        char cbuff[CMSG_SPACE(256)];
        int err = 0, len;
	int cmsg_level, cmsg_type;

	HIP_ASSERT(saddr);
	HIP_ASSERT(daddr);

	HIP_DEBUG("hip_read_control_msg_all() invoked.\n");

	HIP_IFEL(((len = hip_peek_recv_total_len(socket, encap_hdr_size, HIP_DEFAULT_MSG_TIMEOUT))<= 0),
		 -1, "Bad packet length (%d)\n", len);

	memset(msg_info, 0, sizeof(hip_portpair_t));
	memset(&msg, 0, sizeof(msg));
	memset(cbuff, 0, sizeof(cbuff));
	memset(&addr_to, 0, sizeof(addr_to));

        /* setup message header with control and receive buffers */
        msg.msg_name = &addr_from;
        msg.msg_namelen = sizeof(struct sockaddr_storage);
        msg.msg_iov = &iov;
        msg.msg_iovlen = 1;

        memset(cbuff, 0, sizeof(cbuff));
        msg.msg_control = cbuff;
        msg.msg_controllen = sizeof(cbuff);
        msg.msg_flags = 0;

        iov.iov_len = len;
        iov.iov_base = hip_msg;

	pktinfo.pktinfo_in4 = NULL;

	len = recvmsg(socket, &msg, 0);

	HIP_IFEL((len < 0), -1, "ICMP%s error: errno=%d, %s\n",
		 (is_ipv4 ? "v4" : "v6"), errno, strerror(errno));

	cmsg_level = (is_ipv4) ? IPPROTO_IP : IPPROTO_IPV6;
	cmsg_type = (is_ipv4) ? IP_PKTINFO : IPV6_2292PKTINFO;

	/* destination address comes from ancillary data passed
	 * with msg due to IPV6_PKTINFO socket option */
	for (cmsg=CMSG_FIRSTHDR(&msg); cmsg; cmsg=CMSG_NXTHDR(&msg,cmsg)){
		if ((cmsg->cmsg_level == cmsg_level) &&
		    (cmsg->cmsg_type == cmsg_type)) {
			/* The structure is a union, so this fills also the
			   pktinfo_in6 pointer */
			pktinfo.pktinfo_in4 =
				(struct in_pktinfo*)CMSG_DATA(cmsg);
			break;
		}
	}

	/* If this fails, change IPV6_2292PKTINFO to IPV6_PKTINFO in
	   hip_init_raw_sock_v6 */
	HIP_IFEL(!pktinfo.pktinfo_in4, -1,
		 "Could not determine dst addr, dropping\n");

	/* UDP port numbers */
	if (is_ipv4 && encap_hdr_size == HIP_UDP_ZERO_BYTES_LEN) {
		HIP_DEBUG("hip_read_control_msg_all() source port = %d\n",
			  ntohs(addr_from4->sin_port));
		msg_info->src_port = ntohs(addr_from4->sin_port);
		/* Destination port is known from the bound socket. */
		msg_info->dst_port = hip_get_local_nat_udp_port();
	}

	/* IPv4 addresses */
	if (is_ipv4) {
		struct sockaddr_in *addr_to4 = (struct sockaddr_in *) &addr_to;
		IPV4_TO_IPV6_MAP(&addr_from4->sin_addr, saddr);
		IPV4_TO_IPV6_MAP(&pktinfo.pktinfo_in4->ipi_addr,
				 daddr);
		addr_to4->sin_family = AF_INET;
		addr_to4->sin_addr = pktinfo.pktinfo_in4->ipi_addr;
		addr_to4->sin_port = msg_info->dst_port;
	} else /* IPv6 addresses */ {
		struct sockaddr_in6 *addr_to6 =
			(struct sockaddr_in6 *) &addr_to;
		memcpy(saddr, &addr_from6->sin6_addr,
		       sizeof(struct in6_addr));
		memcpy(daddr, &pktinfo.pktinfo_in6->ipi6_addr,
		       sizeof(struct in6_addr));
		addr_to6->sin6_family = AF_INET6;
		ipv6_addr_copy(&addr_to6->sin6_addr, daddr);
	}

//added by santtu
	if (hip_read_control_msg_plugin_handler(hip_msg,len, saddr,msg_info->src_port))
		goto out_err;
//endadd

	if (is_ipv4 && (encap_hdr_size == IPV4_HDR_SIZE)) {/* raw IPv4, !UDP */
		/* For some reason, the IPv4 header is always included.
		   Let's remove it here. */
		memmove(hip_msg, ((char *)hip_msg) + IPV4_HDR_SIZE,
			HIP_MAX_PACKET - IPV4_HDR_SIZE);
	} else if (is_ipv4 && encap_hdr_size == HIP_UDP_ZERO_BYTES_LEN) {
		/* remove 32-bits of zeroes between UDP and HIP headers */
		memmove(hip_msg, ((char *)hip_msg) + HIP_UDP_ZERO_BYTES_LEN,
			HIP_MAX_PACKET - HIP_UDP_ZERO_BYTES_LEN);
	}

	HIP_IFEL(hip_verify_network_header(hip_msg,
					   (struct sockaddr *) &addr_from,
					   (struct sockaddr *) &addr_to,
					   len - encap_hdr_size), -1,
		 "verifying network header failed\n");



	if (saddr)
		HIP_DEBUG_IN6ADDR("src", saddr);
	if (daddr)
		HIP_DEBUG_IN6ADDR("dst", daddr);

 out_err:
	return err;
}
Пример #4
0
/**
 * 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");
        }
    }
Пример #5
0
Файл: cache.c Проект: surki/hipl
/**
 * firewall_cache_db_match:
 * Search in the cache database the given peers of hits, lsis or ips
 */
int firewall_cache_db_match(    struct in6_addr *hit_our,
				struct in6_addr *hit_peer,
				hip_lsi_t       *lsi_our,
				hip_lsi_t       *lsi_peer,
				struct in6_addr *ip_our,
				struct in6_addr *ip_peer,
				int *state){
	int i, err = 0, entry_in_cache = 0;
	firewall_cache_hl_t *this;
	hip_list_t *item, *tmp;
	struct in6_addr all_zero_v6 = {0};
	struct in_addr  all_zero_v4 = {0};
	struct hip_common *msg = NULL;
	firewall_cache_hl_t *ha_curr = NULL;
	firewall_cache_hl_t *ha_match = NULL;
	struct hip_tlv_common *current_param = NULL;

	HIP_ASSERT( (hit_our && hit_peer) ||
		    (lsi_our && lsi_peer)    );

	if(hit_peer){
		ha_match = (firewall_cache_hl_t *)hip_ht_find(
						firewall_cache_db,
						(void *)hit_peer);
		if(ha_match){
			HIP_DEBUG("Matched using hash\n");
			entry_in_cache = 1;
			goto out_err;
		}
	}

	HIP_DEBUG("Check firewall cache db\n");

	HIP_LOCK_HT(&firewall_cache_db);

	list_for_each_safe(item, tmp, firewall_cache_db, i){
		this = list_entry(item);

		if( lsi_our && lsi_peer) {
		  HIP_DEBUG_INADDR("this->our", &this->lsi_our.s_addr);
		  HIP_DEBUG_INADDR("this->peer", &this->lsi_peer.s_addr);
		  HIP_DEBUG_INADDR("our", lsi_our);
		  HIP_DEBUG_INADDR("peer", lsi_peer);
		}

		if( hit_our && hit_peer &&
		    (ipv6_addr_cmp(hit_peer, &this->hit_peer) == 0 ) &&
		    (ipv6_addr_cmp(hit_our,  &this->hit_our)  == 0 )    ){
			ha_match = this;
			break;
		}
		if( lsi_our && lsi_peer &&
		    lsi_peer->s_addr == this->lsi_peer.s_addr &&
		    lsi_our->s_addr  == this->lsi_our.s_addr     ){
			ha_match = this;
			break;
		}
		if( ip_our && ip_peer &&
		    ip_peer->s6_addr == this->ip_peer.s6_addr &&
		    ip_our->s6_addr  == this->ip_our.s6_addr     ) {
			ha_match = this;
			break;
		}
	}
Пример #6
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;
}
Пример #7
0
/**
 * generate HIP keying material
 * @param kij Diffie-Hellman Kij (as in the HIP drafts)
 * @param kij_len the length of the Kij material
 * @param keymat pointer to a keymat structure which will be updated according
 *           to the generated keymaterial
 * @param dstbuf the generated keymaterial will be written here
 * @param dstbuflen the length of the buffer to which to write to
 * @param hit1 source HIT
 * @param hit2 destination HIT
 * @param calc_index where the one byte index is stored (n of Kn)
 * @param I the I value
 * @param J the J value
 *
 */
void hip_make_keymat(char *kij,
                     size_t kij_len,
                     struct hip_keymat_keymat *keymat,
                     void *dstbuf,
                     size_t dstbuflen,
                     struct in6_addr *hit1,
                     struct in6_addr *hit2,
                     uint8_t *calc_index,
                     const uint8_t I[PUZZLE_LENGTH],
                     const uint8_t J[PUZZLE_LENGTH])
{
    int              bufsize;
    uint8_t          index_nbr = 1;
    size_t           dstoffset = 0;
    void            *seedkey;
    struct in6_addr *smaller_hit, *bigger_hit;
    int              hit1_is_bigger;
    uint8_t         *shabuffer = NULL;

    HIP_DEBUG("\n");
    if (dstbuflen < HIP_AH_SHA_LEN) {
        HIP_ERROR("dstbuf is too short (%d)\n", dstbuflen);
        return;
    }

    HIP_ASSERT(sizeof(index_nbr) == HIP_KEYMAT_INDEX_NBR_SIZE);

    hit1_is_bigger = hip_hit_is_bigger(hit1, hit2);

    bigger_hit  = hit1_is_bigger ? hit1 : hit2;
    smaller_hit = hit1_is_bigger ? hit2 : hit1;
    shabuffer   = hip_create_keymat_buffer(kij, kij_len, HIP_AH_SHA_LEN,
                                           smaller_hit, bigger_hit, I, J);
    if (!shabuffer) {
        HIP_ERROR("No memory for keymat\n");
        return;
    }

    bufsize = kij_len + 2 * sizeof(struct in6_addr) +
              2 * sizeof(uint64_t) + 1;

    // XX FIXME: is this correct
    hip_build_digest(HIP_DIGEST_SHA1, shabuffer, bufsize, dstbuf);

    dstoffset = HIP_AH_SHA_LEN;
    index_nbr++;

    /*
     * K2 = SHA1(Kij | K1 | 2)
     * K3 = SHA1(Kij | K2 | 3)
     * ...
     */
    seedkey = dstbuf;
    hip_update_keymat_buffer(shabuffer, seedkey, HIP_AH_SHA_LEN,
                             kij_len, index_nbr);

    while (dstoffset < dstbuflen) {
        hip_build_digest(HIP_DIGEST_SHA1, shabuffer,
                         kij_len + HIP_AH_SHA_LEN + 1,
                         (uint8_t *) dstbuf + dstoffset);
        seedkey    = (uint8_t *) dstbuf + dstoffset;
        dstoffset += HIP_AH_SHA_LEN;
        index_nbr++;
        hip_update_keymat_buffer(shabuffer, seedkey, HIP_AH_SHA_LEN,
                                 kij_len, index_nbr);
    }

    keymat->offset    = 0;
    keymat->keymatlen = dstoffset;
    keymat->keymatdst = dstbuf;

    if (calc_index) {
        *calc_index = index_nbr;
    } else {
        HIP_ERROR("NULL calc_index\n");
    }

    free(shabuffer);
}
Пример #8
0
/**
 * hip_make_keymat - generate HIP keying material
 * @param kij Diffie-Hellman Kij (as in the HIP drafts)
 * @param kij_len the length of the Kij material
 * @param keymat pointer to a keymat structure which will be updated according
 *           to the generated keymaterial
 * @param dstbuf the generated keymaterial will be written here
 * @param hit1 source HIT
 * @param hit2 destination HIT
 * @param calc_index where the one byte index is stored (n of Kn)
 *
 */
void hip_make_keymat(char *kij, size_t kij_len,
		     struct hip_keymat_keymat *keymat, 
		     void *dstbuf, size_t dstbuflen, struct in6_addr *hit1,
		     struct in6_addr *hit2, u8 *calc_index,
		     uint64_t I, uint64_t J)
{
	int bufsize, err = 0;
	uint8_t index_nbr = 1;
	int dstoffset = 0;
	void *seedkey;
	struct in6_addr *smaller_hit, *bigger_hit;
	int hit1_is_bigger;
	u8 *shabuffer = NULL;

	HIP_DEBUG("\n");
	if (dstbuflen < HIP_AH_SHA_LEN) {
		HIP_ERROR("dstbuf is too short (%d)\n", dstbuflen);
		return;
	}

	_HIP_ASSERT(dstbuflen % 32 == 0);
	HIP_ASSERT(sizeof(index_nbr) == HIP_KEYMAT_INDEX_NBR_SIZE);

	hit1_is_bigger = hip_hit_is_bigger(hit1, hit2);

	bigger_hit =  hit1_is_bigger ? hit1 : hit2;
	smaller_hit = hit1_is_bigger ? hit2 : hit1;

	_HIP_HEXDUMP("kij", kij, kij_len);
	_HIP_DEBUG("I=0x%llx J=0x%llx\n", I, J);
	_HIP_HEXDUMP("bigger hit", bigger_hit, 16);
	_HIP_HEXDUMP("smaller hit", smaller_hit, 16);
	_HIP_HEXDUMP("index_nbr", (char *) &index_nbr,
		     HIP_KEYMAT_INDEX_NBR_SIZE);

	shabuffer = hip_create_keymat_buffer(kij, kij_len, HIP_AH_SHA_LEN,
					     smaller_hit, bigger_hit, I, J);
	if (!shabuffer) {
		HIP_ERROR("No memory for keymat\n");
		return;
	}

	bufsize = kij_len + 2 * sizeof(struct in6_addr) +
		2 * sizeof(uint64_t) + 1;
	//bufsize = kij_len+2*sizeof(struct in6_addr)+ 1;

	// XX FIXME: is this correct
	hip_build_digest(HIP_DIGEST_SHA1, shabuffer, bufsize, dstbuf);

	_HIP_HEXDUMP("keymat digest", dstbuf, HIP_AH_SHA_LEN);

	dstoffset = HIP_AH_SHA_LEN;
	index_nbr++;

	/*
	 * K2 = SHA1(Kij | K1 | 2)
	 * K3 = SHA1(Kij | K2 | 3)
	 * ...
	 */
	seedkey = dstbuf;
	hip_update_keymat_buffer(shabuffer, seedkey, HIP_AH_SHA_LEN,
				 kij_len, index_nbr);

	while (dstoffset < dstbuflen) {
		hip_build_digest(HIP_DIGEST_SHA1, shabuffer,
				 kij_len + HIP_AH_SHA_LEN + 1,
				 dstbuf + dstoffset);
		seedkey = dstbuf + dstoffset;
		dstoffset += HIP_AH_SHA_LEN;
		index_nbr++;
		hip_update_keymat_buffer(shabuffer, seedkey, HIP_AH_SHA_LEN,
					 kij_len, index_nbr);
	}

	keymat->offset = 0;
	keymat->keymatlen = dstoffset;
	keymat->keymatdst = dstbuf;

	if (calc_index)
		*calc_index = index_nbr;
	else
		HIP_ERROR("NULL calc_index\n");

	_HIP_DEBUG("keymat index_nbr=%u\n", index_nbr);
	_HIP_HEXDUMP("GENERATED KEYMAT: ", dstbuf, dstbuflen);
	if (shabuffer)
		HIP_FREE(shabuffer);

	return;
}
Пример #9
0
/** handles a user-message sent by the firewall when the bex-store is updated
 *
 * @param msg   the user-message sent by fw
 * @return      0 if ok, != 0 else
 */
int anchor_db_update(const struct hip_common *msg)
{
    const struct hip_tlv_common *param  = NULL;
    const unsigned char         *anchor = NULL;
    int                          err    = 0, i, j;
    uint8_t                      esp_transforms[MAX_NUM_TRANSFORMS];

    HIP_ASSERT(msg != NULL);

    // if this function is called, the extension should be active
    if (esp_prot_active) {
        memset(esp_transforms, 0, MAX_NUM_TRANSFORMS * sizeof(uint8_t));

        HIP_DEBUG("updating hchain anchorDB...\n");

        /* XX TODO ineffcient -> only add non-existing elements instead of
         *         uniniting and adding all elements again */
        anchor_db_uninit();

        /*** set up anchor_db.num_anchors and anchor_db.anchor_lengths ***/
        // get first int value
        HIP_IFEL(!(param = hip_get_param(msg, HIP_PARAM_UINT)),
                 -1, "parameter missing in user-message from fw\n");

        // don't set up anything for UNUSED transform
        for (i = 0; i < esp_prot_num_transforms - 1; i++) {
            // needed for redirection to correct slot in anchor_db
            esp_transforms[i] = *(const uint8_t *)
                                hip_get_param_contents_direct(param);
            HIP_DEBUG("esp_transform is %u\n", esp_transforms[i]);

            HIP_IFEL(!(param = hip_get_next_param(msg, param)),
                     -1, "parameter missing in user-message from fw\n");
            anchor_db.num_anchors[esp_transforms[i]] = *(const int *)
                                                       hip_get_param_contents_direct(param);
            HIP_DEBUG("num_anchors is %i\n", anchor_db.num_anchors[esp_transforms[i]]);

            HIP_IFEL(!(param = hip_get_next_param(msg, param)),
                     -1, "parameter missing in user-message from fw\n");
            anchor_db.anchor_lengths[esp_transforms[i]] = *(const int *)
                                                          hip_get_param_contents_direct(param);
            HIP_DEBUG("anchor_length is %i\n", anchor_db.anchor_lengths[esp_transforms[i]]);

            HIP_IFEL(!(param = hip_get_next_param(msg, param)),
                     -1, "parameter missing in user-message from fw\n");
        }

        for (i = 0; i < esp_prot_num_transforms - 1; i++) {
            HIP_DEBUG("transform %u:\n", esp_transforms[i]);

            for (j = 0; j < anchor_db.num_anchors[esp_transforms[i]]; j++) {
                HIP_IFEL(!(anchor_db.anchors[esp_transforms[i]][j] =
                               malloc(anchor_db.anchor_lengths[esp_transforms[i]])),
                         -1, "failed to allocate memory\n");

                anchor = hip_get_param_contents_direct(param);
                memcpy(anchor_db.anchors[esp_transforms[i]][j], anchor,
                       anchor_db.anchor_lengths[esp_transforms[i]]);
                HIP_HEXDUMP("adding anchor: ", anchor_db.anchors[esp_transforms[i]][j],
                            anchor_db.anchor_lengths[esp_transforms[i]]);

                HIP_IFEL(!(param = hip_get_next_param(msg, param)),
                         -1, "parameter missing in user-message from fw\n");
                anchor_db.hash_item_length[esp_transforms[i]] = *(const int *)
                                                                hip_get_param_contents_direct(param);
                HIP_DEBUG("adding hash_item_length: %i\n",
                          anchor_db.hash_item_length[esp_transforms[i]]);

                // exclude getting the next param for the very last loop
                if (!(i == esp_prot_num_transforms - 2 && j == anchor_db.num_anchors[esp_transforms[i]] - 1)) {
                    HIP_IFEL(!(param = hip_get_next_param(msg, param)),
                             -1, "parameter missing in user-message from fw\n");
                }
            }
        }

        HIP_DEBUG("anchor_db successfully updated\n");
    } else {
        HIP_ERROR("received anchor_db update, but esp protection extension disabled\n");

        err = -1;
        goto out_err;
    }

out_err:
    return err;
}
Пример #10
0
/** returns the hash-item-length for a given transform
 *
 * @param transform     the ESP protection extension transform
 * @return              hash-item-length, 0 for UNUSED transform
 */
int anchor_db_get_hash_item_length(const uint8_t transform)
{
    HIP_ASSERT(transform > 0);

    return anchor_db.hash_item_length[transform];
}
Пример #11
0
/** returns the anchor-length for a given transform
 *
 * @param transform     the ESP protection extension transform
 * @return              anchor-length, 0 for UNUSED transform
 */
int anchor_db_get_anchor_length(const uint8_t transform)
{
    HIP_ASSERT(transform > 0);

    return anchor_db.anchor_lengths[transform];
}