コード例 #1
0
ファイル: lsi.c プロジェクト: surki/hipl
int hip_is_packet_lsi_reinjection(hip_lsi_t *lsi)
{
	hip_lsi_t *local_lsi;
	int err = 0;

	HIP_IFEL(!(local_lsi = hip_fw_get_default_lsi()), -1,
		 "Failed to get default LSI");
	if (local_lsi->s_addr == lsi->s_addr)
		err = 1;
	else
		err = 0;
	
	HIP_DEBUG_LSI("local lsi", local_lsi);
	HIP_DEBUG("Reinjection: %d\n", err);
out_err:
	return err;
}
コード例 #2
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;
}
コード例 #3
0
ファイル: lsi.c プロジェクト: surki/hipl
/**
 * Checks if the outgoing packet with lsis has already ESTABLISHED the Base Exchange
 * with the peer host. In case the BEX is not done, it triggers it. Otherwise, it looks up 
 * in the local database the necessary information for doing the packet reinjection with HITs.
 *
 * @param m           pointer to the packet
 * @param lsi_src     source LSI 
 * @param lsi_dst     destination LSI
 * @return	      err during the BEX
 */
int hip_fw_handle_outgoing_lsi(ipq_packet_msg_t *m, struct in_addr *lsi_src,
			       struct in_addr *lsi_dst)
{
	int err = 0, msg_type, state_ha, new_fw_entry_state;
	struct in6_addr src_lsi, dst_lsi;
	struct in6_addr src_hit, dst_hit;
	struct in6_addr src_ip, dst_ip;
	firewall_hl_t *entry_peer = NULL;

	if (lsi_dst) {
		HIP_DEBUG_LSI("lsi dst", lsi_dst);
	}

	memset(&src_lsi, 0, sizeof(struct in6_addr));
	memset(&dst_lsi, 0, sizeof(struct in6_addr));
	memset(&src_hit, 0, sizeof(struct in6_addr));
	memset(&dst_hit, 0, sizeof(struct in6_addr));
	memset(&src_ip, 0, sizeof(struct in6_addr));
	memset(&dst_ip, 0, sizeof(struct in6_addr));

	/* get the corresponding ip address for this lsi,
	   as well as the current ha state */
	if(firewall_cache_db_match(NULL, NULL, lsi_src, lsi_dst,
				   &src_ip, &dst_ip, &state_ha)){
		HIP_DEBUG("No HA found yet\n");
	}

	entry_peer = (firewall_hl_t *) firewall_ip_db_match(&dst_ip);	
	if (entry_peer) {
		/* if the firewall entry is still undefined
		   check whether the base exchange has been established */
		if(entry_peer->bex_state == FIREWALL_STATE_BEX_DEFAULT){
			/* find the correct state for the fw entry state */
			if(state_ha == HIP_STATE_ESTABLISHED)
				new_fw_entry_state = FIREWALL_STATE_BEX_ESTABLISHED;
			else if( (state_ha == HIP_STATE_FAILED)  ||
				 (state_ha == HIP_STATE_CLOSING) ||
				 (state_ha == HIP_STATE_CLOSED)     )
				new_fw_entry_state = FIREWALL_STATE_BEX_NOT_SUPPORTED;
			else
				new_fw_entry_state = FIREWALL_STATE_BEX_DEFAULT;

			/* update fw entry state accordingly */
			firewall_update_entry(NULL, NULL, NULL, &dst_ip,
					      FIREWALL_STATE_BEX_ESTABLISHED);

			/* reobtain the entry in case it has been updated */
			entry_peer = firewall_ip_db_match(&dst_ip);
		}

		/* decide whether to reinject the packet */
		if (entry_peer->bex_state == FIREWALL_STATE_BEX_ESTABLISHED)
			HIP_IFEL(reinject_packet(&entry_peer->hit_our,
						 &entry_peer->hit_peer,
						 m, 4, 0),
				 -1, "Failed to reinject\n");
	} else {
		HIP_DEBUG("no ip db match\n");
		/* add default entry in the firewall db */
		HIP_IFEL(firewall_add_default_entry(&dst_ip), -1,
			 "Adding of fw entry failed\n");

	        /* Check if bex is already established: server case.
		   Get current connection state from hipd */
		state_ha = hip_get_bex_state_from_LSIs(lsi_src, lsi_dst,
						       &src_ip, &dst_ip,
						       &src_hit, &dst_hit);

		if( (state_ha == -1)                     || 
		    (state_ha == HIP_STATE_NONE)         || 
		    (state_ha == HIP_STATE_UNASSOCIATED)    ){
			/* initialize bex */
			IPV4_TO_IPV6_MAP(lsi_src, &src_lsi);
			IPV4_TO_IPV6_MAP(lsi_dst, &dst_lsi);
			HIP_IFEL(hip_trigger_bex(&src_hit, &dst_hit, &src_lsi,
						 &dst_lsi, NULL, NULL),
				 	-1, "Base Exchange Trigger failed\n");
			/* update fw db entry */
			HIP_IFEL(firewall_update_entry(&src_hit, &dst_hit,
						       lsi_dst, &dst_ip,
						       FIREWALL_STATE_BEX_DEFAULT), -1,
				 "Failed to update fw entry\n");
		}
		if(state_ha == HIP_STATE_ESTABLISHED){
			/* update fw db entry */
			HIP_IFEL(firewall_update_entry(&src_hit, &dst_hit,
						       lsi_dst, &dst_ip,
						       FIREWALL_STATE_BEX_ESTABLISHED),
				 -1, "Failed to update fw entry\n");

			HIP_IFEL(reinject_packet(&src_hit, &dst_hit, m, 4, 0),
				 -1, "Reinject failed\n");
		}
	}
out_err: 
	return err;
}
コード例 #4
0
ファイル: lsi.c プロジェクト: surki/hipl
/**
 * Executes the packet reinjection
 *

 * @param src_hit              ipv6 source address 
 * @param dst_hit              ipv6 destination address
 * @param m                    pointer to the packet
 * @param ipOrigTraffic        type of Traffic (IPv4 or IPv6)
 * @param incoming             packet direction
 * @return	               err during the reinjection
 */
int reinject_packet(struct in6_addr *src_hit, struct in6_addr *dst_hit,
		    ipq_packet_msg_t *m, int ipOrigTraffic, int incoming)
{
        int err = 0, ip_hdr_size, packet_length = 0, protocol, ttl;
	u8 *msg;  
	struct icmphdr *icmp = NULL;

	if (ipOrigTraffic == 4) {
		struct ip *iphdr = (struct ip*) m->payload;
		ip_hdr_size = (iphdr->ip_hl * 4);  
		protocol = iphdr->ip_p;
		ttl = iphdr->ip_ttl;
        	HIP_DEBUG_LSI("Ipv4 address src ", &(iphdr->ip_src));
	        HIP_DEBUG_LSI("Ipv4 address dst ", &(iphdr->ip_dst));
	} else {
	        struct ip6_hdr* ip6_hdr = (struct ip6_hdr*) m->payload;
		ip_hdr_size = sizeof(struct ip6_hdr); //Fixed size
		protocol = ip6_hdr->ip6_nxt;
		ttl = ip6_hdr->ip6_hlim;
		HIP_DEBUG_IN6ADDR("Orig packet src address: ", &(ip6_hdr->ip6_src));
		HIP_DEBUG_IN6ADDR("Orig packet dst address: ", &(ip6_hdr->ip6_dst));
		HIP_DEBUG_IN6ADDR("New packet src address:", src_hit);
		HIP_DEBUG_IN6ADDR("New packet dst address: ", dst_hit);
	}
	
	if (m->data_len <= (BUFSIZE - ip_hdr_size)) {
		packet_length = m->data_len - ip_hdr_size; 	
	  	HIP_DEBUG("packet size smaller than buffer size\n");
	} else { 
	  	packet_length = BUFSIZE - ip_hdr_size;
		HIP_DEBUG("HIP packet size greater than buffer size\n");
	}

	_HIP_DEBUG("Reinject packet packet length (%d)\n", packet_length);
	_HIP_DEBUG("      Protocol %d\n", protocol);
	_HIP_DEBUG("      ipOrigTraffic %d \n", ipOrigTraffic);

	/* Note: using calloc to zero memory region here because I think
	   firewall_send_incoming_pkt() calculates checksum
	   from too long region sometimes. See bug id 874 */
	msg = (u8 *)calloc((packet_length + sizeof(struct ip)), 1);
	memcpy(msg, (m->payload)+ip_hdr_size, packet_length);

	if (protocol == IPPROTO_ICMP && incoming) {
		  icmp = (struct icmphdr *)msg;
		  HIP_DEBUG("incoming ICMP type=%d code=%d\n",
			    icmp->type,icmp->code);
		  /* Manually built due to kernel messed up with the
		     ECHO_REPLY message. Kernel was building an answer
		     message with equals @src and @dst*/
		  if (icmp->type == ICMP_ECHO) {
		  	icmp->type = ICMP_ECHOREPLY;
		    	err = firewall_send_outgoing_pkt(dst_hit, src_hit,
							 msg, packet_length,
							 protocol);
		  } else {
		    	err = firewall_send_incoming_pkt(src_hit, dst_hit,
							 msg, packet_length,
							 protocol, ttl);
		  }
	} else {
		  if (incoming) {
			    HIP_DEBUG("Firewall send to the kernel an incoming packet\n");
			    err = firewall_send_incoming_pkt(src_hit,
							     dst_hit, msg,
							     packet_length,
							     protocol, ttl);
		  } else {
			    HIP_DEBUG("Firewall send to the kernel an outgoing packet\n");
			    err = firewall_send_outgoing_pkt(src_hit,
							     dst_hit, msg,
							     packet_length,
							     protocol);
		  }
	}

	if(msg)
	        HIP_FREE(msg);
	return err;	
}
コード例 #5
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");
        }
    }