VirtualBox

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


Ignore:
Timestamp:
Nov 18, 2013 2:17:46 PM (11 years ago)
Author:
vboxsync
Message:

Handle mapped loopbacks. Propagate TTL, TOS.

File:
1 edited

Legend:

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

    r49515 r49533  
    5858struct pxping {
    5959    SOCKET sock4;
     60    int ttl;
     61    int tos;
     62
    6063    SOCKET sock6;
    6164
     
    9699
    97100    u8_t is_ipv6;
     101    u8_t is_mapped;
    98102
    99103    u16_t guest_id;
     
    186190{
    187191    if (sock == INVALID_SOCKET) {
    188         return ERR_VAL;
    189     }
     192        return ERR_VAL;
     193    }
     194
     195    g_pxping.netif = netif;
    190196
    191197    g_pxping.sock4 = sock;
    192     g_pxping.netif = netif;
     198    g_pxping.ttl = -1;
     199    g_pxping.tos = 0;
    193200
    194201    sys_mutex_new(&g_pxping.lock);
     
    238245    struct ip_hdr *iph;
    239246    struct icmp_echo_hdr *icmph;
     247    int ttl, tos;
    240248    u32_t sum;
    241249    u16_t iphlen;
    242250    u16_t id, seq;
     251    int status;
    243252
    244253    iph = (/* UNCONST */ struct ip_hdr *)ip_current_header();
     
    260269
    261270    pxping_pcb_debug_print(pcb); /* XXX */
    262     printf(" seq %d len %u\n", ntohs(seq), (unsigned int)p->tot_len);
     271    printf(" seq %d len %u ttl %d\n",
     272           ntohs(seq), (unsigned int)p->tot_len,
     273           IPH_TTL(iph));
     274
     275    ttl = IPH_TTL(iph);
     276    if (!pcb->is_mapped) {
     277        if (ttl == 1) {
     278            pbuf_header(p, iphlen); /* back to IP header */
     279            icmp_time_exceeded(p, ICMP_TE_TTL);
     280            return;
     281        }
     282        --ttl;
     283    }
    263284
    264285    /* rewrite ICMP echo header */
     
    268289    icmph->chksum = ~sum;
    269290
    270     /*
    271      * TODO: Support TTL, TOS (and may be options?).
    272      *
    273      * At least on Linux "when the IP_HDRINCL option is set, datagrams
    274      * will not be fragmented and are limited to the interface MTU",
    275      * so we need to use setsockopt() to set those.
    276      */
     291    if (ttl != pxping->ttl) {
     292        status = setsockopt(pxping->sock4, IPPROTO_IP, IP_TTL,
     293                            (char *)&ttl, sizeof(ttl));
     294        if (status == 0) {
     295            pxping->ttl = ttl;
     296        }
     297        else {
     298            perror("IP_TTL");
     299        }
     300    }
     301
     302    tos = IPH_TOS(iph);
     303    if (tos != pxping->tos) {
     304        status = setsockopt(pxping->sock4, IPPROTO_IP, IP_TOS,
     305                            (char *)&tos, sizeof(tos));
     306        if (status == 0) {
     307            pxping->tos = tos;
     308        }
     309        else {
     310            perror("IP_TOS");
     311        }
     312    }
    277313
    278314    proxy_sendto(pxping->sock4, p,
     
    422458        }
    423459        else {
     460            int mapped;
     461
    424462            pcb->peer.sin.sin_family = AF_INET;
    425463#if HAVE_SA_LEN
    426464            pcb->peer.sin.sin_len = sizeof(pcb->peer.sin);
    427465#endif
    428             pxremap_outbound_ip4((ip_addr_t *)&pcb->peer.sin.sin_addr,
    429                                  ipX_2_ip(&pcb->dst));
     466            mapped = pxremap_outbound_ip4((ip_addr_t *)&pcb->peer.sin.sin_addr,
     467                                          ipX_2_ip(&pcb->dst));
     468            if (mapped == PXREMAP_FAILED) {
     469                free(pcb);
     470                return NULL;
     471            }
     472            else {
     473                pcb->is_mapped = (mapped == PXREMAP_MAPPED);
     474            }
    430475            pcb->peer.sin.sin_port = htons(IP_PROTO_ICMP);
    431476        }
     
    717762    struct icmp_echo_hdr *icmph;
    718763    u16_t id, seq;
     764    int mapped;
    719765    struct ping_pcb *pcb;
    720     ip_addr_t pcb_src, pcb_dst;
     766    ip_addr_t guest_ip, target_ip, unmapped_target_ip;
    721767    u16_t guest_id;
    722768    u32_t sum;
     
    737783    }
    738784
     785    ip_addr_copy(target_ip, iph->src);
     786    mapped = pxremap_inbound_ip4(&unmapped_target_ip, &target_ip);
     787    if (mapped == PXREMAP_FAILED) {
     788        return;
     789    }
     790
    739791    sys_mutex_lock(&pxping->lock);
    740     pcb = pxping_pcb_for_reply(pxping, 0, ip_2_ipX(&iph->src), id);
     792    pcb = pxping_pcb_for_reply(pxping, 0, ip_2_ipX(&unmapped_target_ip), id);
    741793    if (pcb == NULL) {
    742794        sys_mutex_unlock(&pxping->lock);
     
    748800
    749801    /* save info before unlocking since pcb may expire */
    750     ip_addr_copy(pcb_src, *ipX_2_ip(&pcb->src));
    751     ip_addr_copy(pcb_dst, *ipX_2_ip(&pcb->dst));
     802    ip_addr_copy(guest_ip, *ipX_2_ip(&pcb->src));
    752803    guest_id = pcb->guest_id;
    753804
     
    762813    /* rewrite outer IP header */
    763814    sum = (u16_t)~IPH_CHKSUM(iph);
    764     sum += update32_with_chksum((u32_t *)&iph->dest, ip4_addr_get_u32(&pcb_src));
    765     IPH_TTL_SET(iph, IPH_TTL(iph) - 1);
    766     sum += PP_NTOHS(~0x0100);
     815    sum += update32_with_chksum((u32_t *)&iph->dest,
     816                                ip4_addr_get_u32(&guest_ip));
     817    if (mapped == PXREMAP_MAPPED) {
     818        sum += update32_with_chksum((u32_t *)&iph->src,
     819                                    ip4_addr_get_u32(&unmapped_target_ip));
     820    }
     821    else {
     822        IPH_TTL_SET(iph, IPH_TTL(iph) - 1);
     823        sum += PP_NTOHS(~0x0100);
     824    }
    767825    sum = FOLD_U32T(sum);
    768826    IPH_CHKSUM_SET(iph, ~sum);
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