aboutsummaryrefslogtreecommitdiff
path: root/src/vpn
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2012-01-21 19:28:46 +0000
committerChristian Grothoff <christian@grothoff.org>2012-01-21 19:28:46 +0000
commitee731605205a1629d672e65e8372167460bb9f45 (patch)
tree1ad5121f55b5245cafc6a0f7ce9d267e13191ee9 /src/vpn
parent7e7ac6e0b1230a74684f13ced5c49dfaf52f3753 (diff)
downloadgnunet-ee731605205a1629d672e65e8372167460bb9f45.tar.gz
gnunet-ee731605205a1629d672e65e8372167460bb9f45.zip
-avoid sending useless ICMP payloads and add ICMP PT support for sender side (vpn) of direction vpn->mesh->exit
Diffstat (limited to 'src/vpn')
-rw-r--r--src/vpn/gnunet-service-vpn.c181
1 files changed, 171 insertions, 10 deletions
diff --git a/src/vpn/gnunet-service-vpn.c b/src/vpn/gnunet-service-vpn.c
index 47a6a7dc4..403570e26 100644
--- a/src/vpn/gnunet-service-vpn.c
+++ b/src/vpn/gnunet-service-vpn.c
@@ -1238,14 +1238,69 @@ route_packet (struct DestinationEntry *destination,
1238 return; 1238 return;
1239 } 1239 }
1240 tnq = GNUNET_malloc (sizeof (struct TunnelMessageQueueEntry) + mlen); 1240 tnq = GNUNET_malloc (sizeof (struct TunnelMessageQueueEntry) + mlen);
1241 tnq->len = mlen;
1242 tnq->msg = &tnq[1]; 1241 tnq->msg = &tnq[1];
1243 ism = (struct GNUNET_EXIT_IcmpServiceMessage *) &tnq[1]; 1242 ism = (struct GNUNET_EXIT_IcmpServiceMessage *) &tnq[1];
1244 ism->header.size = htons ((uint16_t) mlen);
1245 ism->header.type = htons (GNUNET_MESSAGE_TYPE_VPN_ICMP_TO_SERVICE); 1243 ism->header.type = htons (GNUNET_MESSAGE_TYPE_VPN_ICMP_TO_SERVICE);
1246 ism->af = htonl (af); /* need to tell destination ICMP protocol family! */ 1244 ism->af = htonl (af); /* need to tell destination ICMP protocol family! */
1247 ism->service_descriptor = destination->details.service_destination.service_descriptor; 1245 ism->service_descriptor = destination->details.service_destination.service_descriptor;
1248 ism->icmp_header = *icmp; 1246 ism->icmp_header = *icmp;
1247 /* ICMP protocol translation will be done by the receiver (as we don't know
1248 the target AF); however, we still need to possibly discard the payload
1249 depending on the ICMP type */
1250 switch (af)
1251 {
1252 case AF_INET:
1253 switch (icmp->type)
1254 {
1255 case GNUNET_TUN_ICMPTYPE_ECHO_REPLY:
1256 case GNUNET_TUN_ICMPTYPE_ECHO_REQUEST:
1257 break;
1258 case GNUNET_TUN_ICMPTYPE_DESTINATION_UNREACHABLE:
1259 case GNUNET_TUN_ICMPTYPE_SOURCE_QUENCH:
1260 case GNUNET_TUN_ICMPTYPE_TIME_EXCEEDED:
1261 /* throw away ICMP payload, won't be useful for the other side anyway */
1262 payload_length = sizeof (struct GNUNET_TUN_IcmpHeader);
1263 break;
1264 default:
1265 GNUNET_STATISTICS_update (stats,
1266 gettext_noop ("# ICMPv4 packets dropped (not allowed)"),
1267 1, GNUNET_NO);
1268 return;
1269 }
1270 /* end of AF_INET */
1271 break;
1272 case AF_INET6:
1273 switch (icmp->type)
1274 {
1275 case GNUNET_TUN_ICMPTYPE6_DESTINATION_UNREACHABLE:
1276 case GNUNET_TUN_ICMPTYPE6_PACKET_TOO_BIG:
1277 case GNUNET_TUN_ICMPTYPE6_TIME_EXCEEDED:
1278 case GNUNET_TUN_ICMPTYPE6_PARAMETER_PROBLEM:
1279 /* throw away ICMP payload, won't be useful for the other side anyway */
1280 payload_length = sizeof (struct GNUNET_TUN_IcmpHeader);
1281 break;
1282 case GNUNET_TUN_ICMPTYPE6_ECHO_REQUEST:
1283 case GNUNET_TUN_ICMPTYPE6_ECHO_REPLY:
1284 break;
1285 default:
1286 GNUNET_STATISTICS_update (stats,
1287 gettext_noop ("# ICMPv6 packets dropped (not allowed)"),
1288 1, GNUNET_NO);
1289 return;
1290 }
1291 /* end of AF_INET6 */
1292 break;
1293 default:
1294 GNUNET_assert (0);
1295 break;
1296 }
1297
1298 /* update length calculations, as payload_length may have changed */
1299 mlen = sizeof (struct GNUNET_EXIT_IcmpServiceMessage) +
1300 alen + payload_length - sizeof (struct GNUNET_TUN_IcmpHeader);
1301 tnq->len = mlen;
1302 ism->header.size = htons ((uint16_t) mlen);
1303 /* finally, copy payload (if there is any left...) */
1249 memcpy (&ism[1], 1304 memcpy (&ism[1],
1250 &icmp[1], 1305 &icmp[1],
1251 payload_length - sizeof (struct GNUNET_TUN_IcmpHeader)); 1306 payload_length - sizeof (struct GNUNET_TUN_IcmpHeader));
@@ -1266,19 +1321,125 @@ route_packet (struct DestinationEntry *destination,
1266 } 1321 }
1267 tnq = GNUNET_malloc (sizeof (struct TunnelMessageQueueEntry) + 1322 tnq = GNUNET_malloc (sizeof (struct TunnelMessageQueueEntry) +
1268 mlen); 1323 mlen);
1269 tnq->len = mlen;
1270 tnq->msg = &tnq[1]; 1324 tnq->msg = &tnq[1];
1271 iim = (struct GNUNET_EXIT_IcmpInternetMessage *) &tnq[1]; 1325 iim = (struct GNUNET_EXIT_IcmpInternetMessage *) &tnq[1];
1272 iim->header.size = htons ((uint16_t) mlen);
1273 iim->header.type = htons (GNUNET_MESSAGE_TYPE_VPN_ICMP_TO_INTERNET); 1326 iim->header.type = htons (GNUNET_MESSAGE_TYPE_VPN_ICMP_TO_INTERNET);
1274 iim->af = htonl (af); /* need to tell destination ICMP protocol family! */
1275 iim->icmp_header = *icmp; 1327 iim->icmp_header = *icmp;
1276 if (af != destination->details.exit_destination.af) 1328 /* Perform ICMP protocol-translation (depending on destination AF and source AF)
1329 and throw away ICMP payload depending on ICMP message type */
1330 switch (af)
1277 { 1331 {
1278 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 1332 case AF_INET:
1279 _("AF-translation for ICMP not implemented\n")); 1333 switch (icmp->type)
1280 return; 1334 {
1281 } 1335 case GNUNET_TUN_ICMPTYPE_ECHO_REPLY:
1336 if (destination->details.exit_destination.af == AF_INET6)
1337 iim->icmp_header.type = GNUNET_TUN_ICMPTYPE6_ECHO_REPLY;
1338 break;
1339 case GNUNET_TUN_ICMPTYPE_ECHO_REQUEST:
1340 if (destination->details.exit_destination.af == AF_INET6)
1341 iim->icmp_header.type = GNUNET_TUN_ICMPTYPE6_ECHO_REQUEST;
1342 break;
1343 case GNUNET_TUN_ICMPTYPE_DESTINATION_UNREACHABLE:
1344 if (destination->details.exit_destination.af == AF_INET6)
1345 iim->icmp_header.type = GNUNET_TUN_ICMPTYPE6_DESTINATION_UNREACHABLE;
1346 /* throw away IP-payload, exit will have to make it up anyway */
1347 payload_length = sizeof (struct GNUNET_TUN_IcmpHeader);
1348 break;
1349 case GNUNET_TUN_ICMPTYPE_TIME_EXCEEDED:
1350 if (destination->details.exit_destination.af == AF_INET6)
1351 iim->icmp_header.type = GNUNET_TUN_ICMPTYPE6_TIME_EXCEEDED;
1352 /* throw away IP-payload, exit will have to make it up anyway */
1353 payload_length = sizeof (struct GNUNET_TUN_IcmpHeader);
1354 break;
1355 case GNUNET_TUN_ICMPTYPE_SOURCE_QUENCH:
1356 if (destination->details.exit_destination.af == AF_INET6)
1357 {
1358 GNUNET_STATISTICS_update (stats,
1359 gettext_noop ("# ICMPv4 packets dropped (impossible PT to v6)"),
1360 1, GNUNET_NO);
1361 GNUNET_free (tnq);
1362 return;
1363 }
1364 /* throw away IP-payload, exit will have to make it up anyway */
1365 payload_length = sizeof (struct GNUNET_TUN_IcmpHeader);
1366 break;
1367 default:
1368 GNUNET_STATISTICS_update (stats,
1369 gettext_noop ("# ICMPv4 packets dropped (type not allowed)"),
1370 1, GNUNET_NO);
1371 GNUNET_free (tnq);
1372 return;
1373 }
1374 /* end of AF_INET */
1375 break;
1376 case AF_INET6:
1377 switch (icmp->type)
1378 {
1379 case GNUNET_TUN_ICMPTYPE6_DESTINATION_UNREACHABLE:
1380 if (destination->details.exit_destination.af == AF_INET6)
1381 iim->icmp_header.type = GNUNET_TUN_ICMPTYPE6_DESTINATION_UNREACHABLE;
1382 /* throw away IP-payload, exit will have to make it up anyway */
1383 payload_length = sizeof (struct GNUNET_TUN_IcmpHeader);
1384 break;
1385 case GNUNET_TUN_ICMPTYPE6_TIME_EXCEEDED:
1386 if (destination->details.exit_destination.af == AF_INET)
1387 iim->icmp_header.type = GNUNET_TUN_ICMPTYPE_TIME_EXCEEDED;
1388 /* throw away IP-payload, exit will have to make it up anyway */
1389 payload_length = sizeof (struct GNUNET_TUN_IcmpHeader);
1390 break;
1391 case GNUNET_TUN_ICMPTYPE6_PACKET_TOO_BIG:
1392 if (destination->details.exit_destination.af == AF_INET)
1393 {
1394 GNUNET_STATISTICS_update (stats,
1395 gettext_noop ("# ICMPv6 packets dropped (impossible PT to v4)"),
1396 1, GNUNET_NO);
1397 GNUNET_free (tnq);
1398 return;
1399 }
1400 /* throw away IP-payload, exit will have to make it up anyway */
1401 payload_length = sizeof (struct GNUNET_TUN_IcmpHeader);
1402 break;
1403 case GNUNET_TUN_ICMPTYPE6_PARAMETER_PROBLEM:
1404 if (destination->details.exit_destination.af == AF_INET)
1405 {
1406 GNUNET_STATISTICS_update (stats,
1407 gettext_noop ("# ICMPv6 packets dropped (impossible PT to v4)"),
1408 1, GNUNET_NO);
1409 GNUNET_free (tnq);
1410 return;
1411 }
1412 /* throw away IP-payload, exit will have to make it up anyway */
1413 payload_length = sizeof (struct GNUNET_TUN_IcmpHeader);
1414 break;
1415 case GNUNET_TUN_ICMPTYPE6_ECHO_REQUEST:
1416 if (destination->details.exit_destination.af == AF_INET)
1417 iim->icmp_header.type = GNUNET_TUN_ICMPTYPE_ECHO_REQUEST;
1418 break;
1419 case GNUNET_TUN_ICMPTYPE6_ECHO_REPLY:
1420 if (destination->details.exit_destination.af == AF_INET)
1421 iim->icmp_header.type = GNUNET_TUN_ICMPTYPE_ECHO_REPLY;
1422 break;
1423 default:
1424 GNUNET_STATISTICS_update (stats,
1425 gettext_noop ("# ICMPv6 packets dropped (type not allowed)"),
1426 1, GNUNET_NO);
1427 GNUNET_free (tnq);
1428 return;
1429 }
1430 /* end of AF_INET6 */
1431 break;
1432 default:
1433 GNUNET_assert (0);
1434 }
1435 /* update length calculations, as payload_length may have changed */
1436 mlen = sizeof (struct GNUNET_EXIT_IcmpInternetMessage) +
1437 alen + payload_length - sizeof (struct GNUNET_TUN_IcmpHeader);
1438 tnq->len = mlen;
1439 iim->header.size = htons ((uint16_t) mlen);
1440
1441 /* need to tell destination ICMP protocol family! */
1442 iim->af = htonl (destination->details.exit_destination.af);
1282 switch (destination->details.exit_destination.af) 1443 switch (destination->details.exit_destination.af)
1283 { 1444 {
1284 case AF_INET: 1445 case AF_INET: