VirtualBox

Changeset 49648 in vbox for trunk/src/VBox/NetworkServices


Ignore:
Timestamp:
Nov 25, 2013 11:39:25 PM (11 years ago)
Author:
vboxsync
Message:

Complete ICMPv6.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/NetworkServices/NAT/pxping.c

    r49637 r49648  
    12101210
    12111211
     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 */
    12121216static void
    12131217pxping_pmgr_icmp6(struct pxping *pxping)
     
    12761280            DPRINTF2(("type %d len %u\n", icmph->type, (unsigned int)nread));
    12771281        }
    1278         return;
     1282
     1283        if (icmph->type >= ICMP6_TYPE_EREQ) {
     1284            return;             /* informational message */
     1285        }
    12791286    }
    12801287
     
    13251332                               hopl, tclass, (u16_t)nread);
    13261333    }
    1327     else {
     1334    else if (icmph->type < ICMP6_TYPE_EREQ) {
    13281335        pxping_pmgr_icmp6_error(pxping,
    13291336                                (ip6_addr_t *)&sin6.sin6_addr,
     
    13341341
    13351342
     1343/**
     1344 * Check if this incoming ICMPv6 echo reply is for one of our pings
     1345 * and forward it to the guest.
     1346 */
    13361347static void
    13371348pxping_pmgr_icmp6_echo(struct pxping *pxping,
     
    13391350                       int hopl, int tclass, u16_t icmplen)
    13401351{
     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 */
     1412static void
     1413pxping_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;
    13411421    struct ip6_hdr *oiph;
    1342     struct icmp6_hdr *icmph, *oicmph;
     1422    struct icmp6_echo_hdr *oicmph;
    13431423    struct ping_pcb *pcb;
    13441424    ip6_addr_t guest_ip, target_ip, error_ip;
     
    13531433     * anything, possibly malicious.
    13541434     */
    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);
    13771555}
    13781556
Note: See TracChangeset for help on using the changeset viewer.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette