- tnq = GNUNET_malloc (sizeof (struct TunnelMessageQueueEntry) +
- mlen);
- tnq->msg = &tnq[1];
- iim = (struct GNUNET_EXIT_IcmpInternetMessage *) &tnq[1];
- iim->header.type = htons (GNUNET_MESSAGE_TYPE_VPN_ICMP_TO_INTERNET);
- iim->icmp_header = *icmp;
- /* Perform ICMP protocol-translation (depending on destination AF and source AF)
- and throw away ICMP payload depending on ICMP message type */
- switch (af)
- {
- case AF_INET:
- switch (icmp->type)
- {
- case GNUNET_TUN_ICMPTYPE_ECHO_REPLY:
- if (destination->details.exit_destination.af == AF_INET6)
- iim->icmp_header.type = GNUNET_TUN_ICMPTYPE6_ECHO_REPLY;
- break;
- case GNUNET_TUN_ICMPTYPE_ECHO_REQUEST:
- if (destination->details.exit_destination.af == AF_INET6)
- iim->icmp_header.type = GNUNET_TUN_ICMPTYPE6_ECHO_REQUEST;
- break;
- case GNUNET_TUN_ICMPTYPE_DESTINATION_UNREACHABLE:
- if (destination->details.exit_destination.af == AF_INET6)
- iim->icmp_header.type = GNUNET_TUN_ICMPTYPE6_DESTINATION_UNREACHABLE;
- /* throw away IP-payload, exit will have to make it up anyway */
- payload_length = sizeof (struct GNUNET_TUN_IcmpHeader);
- break;
- case GNUNET_TUN_ICMPTYPE_TIME_EXCEEDED:
- if (destination->details.exit_destination.af == AF_INET6)
- iim->icmp_header.type = GNUNET_TUN_ICMPTYPE6_TIME_EXCEEDED;
- /* throw away IP-payload, exit will have to make it up anyway */
- payload_length = sizeof (struct GNUNET_TUN_IcmpHeader);
- break;
- case GNUNET_TUN_ICMPTYPE_SOURCE_QUENCH:
- if (destination->details.exit_destination.af == AF_INET6)
- {
- GNUNET_STATISTICS_update (stats,
- gettext_noop ("# ICMPv4 packets dropped (impossible PT to v6)"),
- 1, GNUNET_NO);
- GNUNET_free (tnq);
- return;
- }
- /* throw away IP-payload, exit will have to make it up anyway */
- payload_length = sizeof (struct GNUNET_TUN_IcmpHeader);
- break;
- default:
- GNUNET_STATISTICS_update (stats,
- gettext_noop ("# ICMPv4 packets dropped (type not allowed)"),
- 1, GNUNET_NO);
- GNUNET_free (tnq);
- return;
- }
- /* end of AF_INET */
- break;
- case AF_INET6:
- switch (icmp->type)
- {
- case GNUNET_TUN_ICMPTYPE6_DESTINATION_UNREACHABLE:
- if (destination->details.exit_destination.af == AF_INET6)
- iim->icmp_header.type = GNUNET_TUN_ICMPTYPE6_DESTINATION_UNREACHABLE;
- /* throw away IP-payload, exit will have to make it up anyway */
- payload_length = sizeof (struct GNUNET_TUN_IcmpHeader);
- break;
- case GNUNET_TUN_ICMPTYPE6_TIME_EXCEEDED:
- if (destination->details.exit_destination.af == AF_INET)
- iim->icmp_header.type = GNUNET_TUN_ICMPTYPE_TIME_EXCEEDED;
- /* throw away IP-payload, exit will have to make it up anyway */
- payload_length = sizeof (struct GNUNET_TUN_IcmpHeader);
- break;
- case GNUNET_TUN_ICMPTYPE6_PACKET_TOO_BIG:
- if (destination->details.exit_destination.af == AF_INET)
- {
- GNUNET_STATISTICS_update (stats,
- gettext_noop ("# ICMPv6 packets dropped (impossible PT to v4)"),
- 1, GNUNET_NO);
- GNUNET_free (tnq);
- return;
- }
- /* throw away IP-payload, exit will have to make it up anyway */
- payload_length = sizeof (struct GNUNET_TUN_IcmpHeader);
- break;
- case GNUNET_TUN_ICMPTYPE6_PARAMETER_PROBLEM:
- if (destination->details.exit_destination.af == AF_INET)
- {
- GNUNET_STATISTICS_update (stats,
- gettext_noop ("# ICMPv6 packets dropped (impossible PT to v4)"),
- 1, GNUNET_NO);
- GNUNET_free (tnq);
- return;
- }
- /* throw away IP-payload, exit will have to make it up anyway */
- payload_length = sizeof (struct GNUNET_TUN_IcmpHeader);
- break;
- case GNUNET_TUN_ICMPTYPE6_ECHO_REQUEST:
- if (destination->details.exit_destination.af == AF_INET)
- iim->icmp_header.type = GNUNET_TUN_ICMPTYPE_ECHO_REQUEST;
- break;
- case GNUNET_TUN_ICMPTYPE6_ECHO_REPLY:
- if (destination->details.exit_destination.af == AF_INET)
- iim->icmp_header.type = GNUNET_TUN_ICMPTYPE_ECHO_REPLY;
- break;
- default:
- GNUNET_STATISTICS_update (stats,
- gettext_noop ("# ICMPv6 packets dropped (type not allowed)"),
- 1, GNUNET_NO);
- GNUNET_free (tnq);
- return;
- }
- /* end of AF_INET6 */
- break;
- default:
- GNUNET_assert (0);
- }
- /* update length calculations, as payload_length may have changed */
- mlen = sizeof (struct GNUNET_EXIT_IcmpInternetMessage) +
- alen + payload_length - sizeof (struct GNUNET_TUN_IcmpHeader);
- tnq->len = mlen;
- iim->header.size = htons ((uint16_t) mlen);
-
- /* need to tell destination ICMP protocol family! */
- iim->af = htonl (destination->details.exit_destination.af);
- switch (destination->details.exit_destination.af)