Ejemplo n.º 1
0
/*
 * Send an ICMPv4 packet with the unreach type and the needfrag code
 * to the node specidied by the remote_addrp parameter.  The source
 * address is the IPv4 address related to the final IPv6 node of the
 * original packet that caused this ICMPv4 error.
 */
   int
icmpsub_send_icmp4_unreach_needfrag(int tun_fd, void *in_pktp,
      const struct in_addr *local_addrp,
      const struct in_addr *remote_addrp,
      int mtu)
{
   assert(in_pktp != NULL);
   assert(local_addrp != NULL);
   assert(remote_addrp != NULL);

   /* Check if we can send this ICMPv4 packet or not. */
   if (icmpsub_check_sending_rate()) {
      warnx("ICMP rate limit over.");
      return (0);
   }


   /* Prepare IPv4 and ICMPv4 headers and fill most of their fields. */
   struct ip ip4_hdr;
   struct icmp icmp4_hdr;
   if (icmpsub_create_icmp4_unreach_needfrag(&ip4_hdr, &icmp4_hdr,
            local_addrp, remote_addrp,
            mtu) == -1) {
      warnx("ICMP unreach needfrag packet creation failed.");
      return (-1);
   }

   /* Calculate the IPv4 header checksum. */
   ip4_hdr.ip_sum = cksum_calc_ip4_header(&ip4_hdr);

   struct iovec iov[5];
   uint32_t af;
   tun_set_af(&af, AF_INET);
   iov[0].iov_base = ⁡
   iov[0].iov_len = sizeof(uint32_t);
   iov[1].iov_base = &ip4_hdr;
   iov[1].iov_len = sizeof(struct ip);
   iov[2].iov_base = NULL;
   iov[2].iov_len = 0;
   iov[3].iov_base = &icmp4_hdr;
   iov[3].iov_len = ICMP_MINLEN;
   iov[4].iov_base = in_pktp;
   iov[4].iov_len = sizeof(struct ip);

   /* Calculate the ICMPv4 header checksum. */
   cksum_calc_ulp(IPPROTO_ICMP, iov);

   if (writev(tun_fd, iov, 5) == -1) {
      warn("failed to write ICMP unreach needfrag packet to the tun device.");
      return (-1);
   }

   return (0);
}
Ejemplo n.º 2
0
/*
 * Send an ICMPv6 packet with the Packet Too Big type to the node
 * specidied by the remote_addrp parameter.  The source address is the
 * IPv6 address related to the final IPv4 node of the original packet
 * that caused this ICMPv6 error.
 */
   int
icmpsub_send_icmp6_packet_too_big(int tun_fd, void *in_pktp,
      const struct in6_addr *local_addrp,
      const struct in6_addr *remote_addrp,
      int mtu)
{
   assert(in_pktp != NULL);
   assert(local_addrp != NULL);
   assert(remote_addrp != NULL);

   /* Check if we can send this ICMPv6 packet or not. */
   if (icmpsub_check_sending_rate()) {
      warnx("ICMP rate limit over.");
      return (0);
   }

   /* Prepare IPv6 and ICMPv6 headers and fill most of their fields. */
   struct ip6_hdr ip6_hdr;
   struct icmp6_hdr icmp6_hdr;
   if (icmpsub_create_icmp6_packet_too_big(&ip6_hdr, &icmp6_hdr,
            local_addrp, remote_addrp,
            mtu) == -1) {
      warnx("ICMPv6 packet too big header creation failed.");
      return (-1);
   }

   struct iovec iov[5];
   uint32_t af;
   tun_set_af(&af, AF_INET6);
   iov[0].iov_base = ⁡
   iov[0].iov_len = sizeof(uint32_t);
   iov[1].iov_base = &ip6_hdr;
   iov[1].iov_len = sizeof(struct ip6_hdr);
   iov[2].iov_base = NULL;
   iov[2].iov_len = 0;
   iov[3].iov_base = &icmp6_hdr;
   iov[3].iov_len = sizeof(struct icmp6_hdr);
   iov[4].iov_base = in_pktp;
   iov[4].iov_len = sizeof(struct ip6_hdr);

   /* Calculate the ICMPv6 header checksum. */
   cksum_calc_ulp(IPPROTO_ICMPV6, iov);

   if (writev(tun_fd, iov, 5) == -1) {
      warn("failed to write ICMPv6 packet too big message to the tun device.");
      return (-1);
   }

   return (0);
}
Ejemplo n.º 3
0
void translate_6to4(struct mapping *st, char *buf, int len){
	struct ip6_hdr *ip6 = (struct ip6_hdr *)buf;
	struct ip ip;
        struct tun_pi pi;
        struct iovec iov[3];

	memset(&ip, 0, sizeof(struct ip));

        ip.ip_v = 4;
        ip.ip_hl = 5;
        ip.ip_len = htons(len - sizeof(struct ip6_hdr) + sizeof(struct ip));
        ip.ip_id = ip6->ip6_flow;
	ip.ip_off = htons(IP_DF);
        ip.ip_ttl = ip6->ip6_hlim;
        ip.ip_p = ip6->ip6_nxt;

        ip.ip_src = st->mapped_ipv4_addr;
	ip.ip_dst = sa46t_extract_6to4_addr(ip6->ip6_dst);

        if(ip6->ip6_nxt == IPPROTO_FRAGMENT){
                /* drop already fragmented packet */
		return;
        }

	if(ip6->ip6_nxt == IPPROTO_ICMPV6){
		ip.ip_p = IPPROTO_ICMP;
		process_icmpv6_packet(buf + sizeof(struct ip6_hdr), len - sizeof(struct ip6_hdr));
	}

	if(ip6->ip6_nxt == IPPROTO_TCP){
		process_tcp_packet(AF_INET, &ip, buf + sizeof(struct ip6_hdr), len - sizeof(struct ip6_hdr));
	}

	if(ip6->ip6_nxt == IPPROTO_UDP){
		process_udp_packet(AF_INET, &ip, buf + sizeof(struct ip6_hdr), len - sizeof(struct ip6_hdr));
	}

        ip.ip_sum = 0;
        ip.ip_sum = ip_checksum((unsigned short *)&ip, sizeof(struct ip));

        tun_set_af(&pi, AF_INET);
        iov[0].iov_base = π
        iov[0].iov_len = sizeof(pi);
        iov[1].iov_base = &ip;
        iov[1].iov_len = sizeof(ip);
        iov[2].iov_base = buf + sizeof(struct ip6_hdr);
        iov[2].iov_len = len - sizeof(struct ip6_hdr);

	send_iovec(iov, 3);
}
Ejemplo n.º 4
0
void translate_4to6(struct mapping *st, char *buf, int len){
	struct ip *ip = (struct ip *)buf;
	struct ip6_hdr ip6;
	struct tun_pi pi;
	struct iovec iov[4];

	memset(&ip6, 0, sizeof(struct ip6_hdr));

        ip6.ip6_vfc = 0x60;
        ip6.ip6_plen = htons(len - sizeof(struct ip));
        ip6.ip6_nxt = ip->ip_p;
        ip6.ip6_hlim = ip->ip_ttl;
	ip6.ip6_src = sa46t_map_4to6_addr(sa46t_addr, plane_id, ip->ip_src);
        ip6.ip6_dst = st->source_ipv6_addr;

        if((ip->ip_off & htons(IP_MF)) > 0){
                /* drop already fragmented packet */
                return;
        }

        if(sizeof(ip6) + len - sizeof(struct ip) > MTU){
                fragment_4to6(&ip6, ip, buf + sizeof(struct ip), len - sizeof(struct ip));
                return;
        }

        if(ip->ip_p == IPPROTO_ICMP){
		ip6.ip6_nxt = IPPROTO_ICMPV6;
                process_icmp_packet(&ip6, buf + sizeof(struct ip), len - sizeof(struct ip));
        }

	if(ip->ip_p == IPPROTO_TCP){
		process_tcp_packet(AF_INET6, &ip6, buf + sizeof(struct ip), len - sizeof(struct ip));
	}

	if(ip->ip_p == IPPROTO_UDP){
		process_udp_packet(AF_INET6, &ip6, buf + sizeof(struct ip), len - sizeof(struct ip));
	}

        tun_set_af(&pi, AF_INET6);

        iov[0].iov_base = π
       	iov[0].iov_len = sizeof(pi);
       	iov[1].iov_base = &ip6;
       	iov[1].iov_len = sizeof(ip6);
       	iov[2].iov_base = buf + sizeof(struct ip);
       	iov[2].iov_len = len - sizeof(struct ip);

        send_iovec(iov, 3);
}