diff options
author | Christian Grothoff <christian@grothoff.org> | 2012-01-21 19:28:46 +0000 |
---|---|---|
committer | Christian Grothoff <christian@grothoff.org> | 2012-01-21 19:28:46 +0000 |
commit | ee731605205a1629d672e65e8372167460bb9f45 (patch) | |
tree | 1ad5121f55b5245cafc6a0f7ce9d267e13191ee9 /src/vpn | |
parent | 7e7ac6e0b1230a74684f13ced5c49dfaf52f3753 (diff) | |
download | gnunet-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.c | 181 |
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: |