Changeset 49648 in vbox for trunk/src/VBox/NetworkServices
- Timestamp:
- Nov 25, 2013 11:39:25 PM (11 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/NetworkServices/NAT/pxping.c
r49637 r49648 1210 1210 1211 1211 1212 /** 1213 * Process incoming ICMPv6 message for the host. 1214 * NB: we will get a lot of spam here and have to sift through it. 1215 */ 1212 1216 static void 1213 1217 pxping_pmgr_icmp6(struct pxping *pxping) … … 1276 1280 DPRINTF2(("type %d len %u\n", icmph->type, (unsigned int)nread)); 1277 1281 } 1278 return; 1282 1283 if (icmph->type >= ICMP6_TYPE_EREQ) { 1284 return; /* informational message */ 1285 } 1279 1286 } 1280 1287 … … 1325 1332 hopl, tclass, (u16_t)nread); 1326 1333 } 1327 else {1334 else if (icmph->type < ICMP6_TYPE_EREQ) { 1328 1335 pxping_pmgr_icmp6_error(pxping, 1329 1336 (ip6_addr_t *)&sin6.sin6_addr, … … 1334 1341 1335 1342 1343 /** 1344 * Check if this incoming ICMPv6 echo reply is for one of our pings 1345 * and forward it to the guest. 1346 */ 1336 1347 static void 1337 1348 pxping_pmgr_icmp6_echo(struct pxping *pxping, … … 1339 1350 int hopl, int tclass, u16_t icmplen) 1340 1351 { 1352 struct icmp6_echo_hdr *icmph; 1353 ip6_addr_t guest_ip, target_ip; 1354 int mapped; 1355 struct ping_pcb *pcb; 1356 u16_t id, guest_id; 1357 u32_t sum; 1358 1359 ip6_addr_copy(target_ip, *src); 1360 mapped = pxremap_inbound_ip6(&target_ip, &target_ip); 1361 if (mapped == PXREMAP_FAILED) { 1362 return; 1363 } 1364 else if (mapped == PXREMAP_ASIS) { 1365 if (hopl == 1) { 1366 DPRINTF2(("%s: dropping packet with ttl 1\n", __func__)); 1367 return; 1368 } 1369 --hopl; 1370 } 1371 1372 icmph = (struct icmp6_echo_hdr *)pollmgr_udpbuf; 1373 id = icmph->id; 1374 1375 sys_mutex_lock(&pxping->lock); 1376 pcb = pxping_pcb_for_reply(pxping, 1, ip6_2_ipX(&target_ip), id); 1377 if (pcb == NULL) { 1378 sys_mutex_unlock(&pxping->lock); 1379 DPRINTF2(("%s: no match\n", __func__)); 1380 return; 1381 } 1382 1383 DPRINTF2(("%s: pcb %p\n", __func__, (void *)pcb)); 1384 1385 /* save info before unlocking since pcb may expire */ 1386 ip6_addr_copy(guest_ip, *ipX_2_ip6(&pcb->src)); 1387 guest_id = pcb->guest_id; 1388 1389 sys_mutex_unlock(&pxping->lock); 1390 1391 /* rewrite ICMPv6 echo header */ 1392 sum = (u16_t)~icmph->chksum; 1393 sum += chksum_update_16(&icmph->id, guest_id); 1394 sum += chksum_delta_ipv6(dst, &guest_ip); /* pseudo */ 1395 if (mapped) { 1396 sum += chksum_delta_ipv6(src, &target_ip); /* pseudo */ 1397 } 1398 sum = FOLD_U32T(sum); 1399 icmph->chksum = ~sum; 1400 1401 pxping_pmgr_forward_inbound6(pxping, 1402 &target_ip, /* echo reply src */ 1403 &guest_ip, /* echo reply dst */ 1404 hopl, tclass, icmplen); 1405 } 1406 1407 1408 /** 1409 * Check if this incoming ICMPv6 error is about one of our pings and 1410 * forward it to the guest. 1411 */ 1412 static void 1413 pxping_pmgr_icmp6_error(struct pxping *pxping, 1414 ip6_addr_t *src, ip6_addr_t *dst, 1415 int hopl, int tclass, u16_t icmplen) 1416 { 1417 struct icmp6_hdr *icmph; 1418 u8_t *bufptr; 1419 size_t buflen, hlen; 1420 int proto; 1341 1421 struct ip6_hdr *oiph; 1342 struct icmp6_ hdr *icmph,*oicmph;1422 struct icmp6_echo_hdr *oicmph; 1343 1423 struct ping_pcb *pcb; 1344 1424 ip6_addr_t guest_ip, target_ip, error_ip; … … 1353 1433 * anything, possibly malicious. 1354 1434 */ 1355 oiph = (struct ip6_hdr *)(pollmgr_udpbuf + sizeof(*icmph)); 1356 1357 if (IP6H_V(oiph) != 6) { 1358 DPRINTF2(("%s: unexpected IP version %d\n", __func__, IP6H_V(oiph))); 1359 return; 1360 } 1361 1362 DPRINTF2(("%s: nexth = %d\n", __func__, IP6H_NEXTH(oiph))); 1363 } 1364 1365 1366 static void 1367 pxping_pmgr_icmp6_error(struct pxping *pxping, 1368 ip6_addr_t *src, ip6_addr_t *dst, 1369 int hopl, int tclass, u16_t icmplen) 1370 { 1371 struct icmp6_echo_hdr *icmph; 1372 int mapped; 1373 struct ping_pcb *pcb; 1374 ip6_addr_t guest_ip, target_ip; 1375 u16_t id, guest_id; 1376 u32_t sum; 1435 oiph = NULL; 1436 oicmph = NULL; 1437 1438 bufptr = pollmgr_udpbuf; 1439 buflen = icmplen; 1440 1441 hlen = sizeof(*icmph); 1442 proto = IP6_NEXTH_ENCAPS; /* i.e. IPv6, lwIP's name is unfortuate */ 1443 for (;;) { 1444 if (hlen > buflen) { 1445 DPRINTF2(("truncated datagram inside ICMPv6 error message is too short\n")); 1446 return; 1447 } 1448 buflen -= hlen; 1449 bufptr += hlen; 1450 1451 if (proto == IP6_NEXTH_ENCAPS && oiph == NULL) { /* outermost IPv6 */ 1452 oiph = (struct ip6_hdr *)bufptr; 1453 if (IP6H_V(oiph) != 6) { 1454 DPRINTF2(("%s: unexpected IP version %d\n", __func__, IP6H_V(oiph))); 1455 return; 1456 } 1457 1458 proto = IP6H_NEXTH(oiph); 1459 hlen = IP6_HLEN; 1460 } 1461 else if (proto == IP6_NEXTH_ICMP6) { 1462 oicmph = (struct icmp6_echo_hdr *)bufptr; 1463 break; 1464 } 1465 else if (proto == IP6_NEXTH_ROUTING 1466 || proto == IP6_NEXTH_HOPBYHOP 1467 || proto == IP6_NEXTH_DESTOPTS) 1468 { 1469 proto = bufptr[0]; 1470 hlen = (bufptr[1] + 1) * 8; 1471 } 1472 else { 1473 DPRINTF2(("%s: stopping at protocol %d\n", __func__, proto)); 1474 break; 1475 } 1476 } 1477 1478 if (oiph == NULL || oicmph == NULL) { 1479 return; 1480 } 1481 1482 if (buflen < sizeof(*oicmph)) { 1483 DPRINTF2(("%s: original ICMPv6 is truncated too short\n", __func__)); 1484 return; 1485 } 1486 1487 if (oicmph->type != ICMP6_TYPE_EREQ) { 1488 DPRINTF2(("%s: ignoring original ICMPv6 type %d\n", __func__, oicmph->type)); 1489 return; 1490 } 1491 1492 memcpy(&target_ip, &oiph->dest, sizeof(target_ip)); /* inner (failed) */ 1493 target_mapped = pxremap_inbound_ip6(&target_ip, &target_ip); 1494 if (target_mapped == PXREMAP_FAILED) { 1495 return; 1496 } 1497 1498 sys_mutex_lock(&pxping->lock); 1499 pcb = pxping_pcb_for_reply(pxping, 1, ip_2_ipX(&target_ip), oicmph->id); 1500 if (pcb == NULL) { 1501 sys_mutex_unlock(&pxping->lock); 1502 DPRINTF2(("%s: no match\n", __func__)); 1503 return; 1504 } 1505 1506 DPRINTF2(("%s: pcb %p\n", __func__, (void *)pcb)); 1507 1508 /* save info before unlocking since pcb may expire */ 1509 ip6_addr_copy(guest_ip, *ipX_2_ip6(&pcb->src)); 1510 guest_id = pcb->guest_id; 1511 1512 sys_mutex_unlock(&pxping->lock); 1513 1514 1515 /* 1516 * Rewrite inner and outer headers and forward to guest. Note 1517 * that IPv6 has no IP header checksum, but uses pseudo-header for 1518 * ICMPv6, so we update both in one go, adjusting ICMPv6 checksum 1519 * as we rewrite IP header. 1520 */ 1521 1522 ip6_addr_copy(error_ip, *src); /* node that reports the error */ 1523 error_mapped = pxremap_inbound_ip6(&error_ip, &error_ip); 1524 if (error_mapped == PXREMAP_FAILED) { 1525 return; 1526 } 1527 if (error_mapped == PXREMAP_ASIS && hopl == 1) { 1528 DPRINTF2(("%s: dropping packet with ttl 1\n", __func__)); 1529 return; 1530 } 1531 1532 /* rewrite inner ICMPv6 echo header and inner IPv6 header */ 1533 sum = (u16_t)~oicmph->chksum; 1534 sum += chksum_update_16(&oicmph->id, guest_id); 1535 sum += chksum_update_ipv6((ip6_addr_t *)&oiph->src, &guest_ip); 1536 if (target_mapped) { 1537 sum += chksum_delta_ipv6((ip6_addr_t *)&oiph->dest, &target_ip); 1538 } 1539 sum = FOLD_U32T(sum); 1540 oicmph->chksum = ~sum; 1541 1542 /* rewrite outer ICMPv6 error header */ 1543 sum = (u16_t)~icmph->chksum; 1544 sum += chksum_delta_ipv6(dst, &guest_ip); /* pseudo */ 1545 if (error_mapped) { 1546 sum += chksum_delta_ipv6(src, &error_ip); /* pseudo */ 1547 } 1548 sum = FOLD_U32T(sum); 1549 icmph->chksum = ~sum; 1550 1551 pxping_pmgr_forward_inbound6(pxping, 1552 &error_ip, /* error src */ 1553 &guest_ip, /* error dst */ 1554 hopl, tclass, icmplen); 1377 1555 } 1378 1556
Note:
See TracChangeset
for help on using the changeset viewer.