datapath-windows/ovsext/Conntrack-nat.c
/*
 *----------------------------------------------------------------------------
 * OvsNatTranslateCtEntry
 *     Update an Conntrack entry with NAT information. Translated address and
 *     port will be generated and write back to the conntrack entry as a
 *     result.
 *     Note: For ICMP, only address is translated.
 *----------------------------------------------------------------------------
 */
OvsNatTranslateCtEntry
Update an Conntrack entry with NAT information. Translated address and
port will be generated and write back to the conntrack entry as a
result.
Note: For ICMP, only address is translated.
OvsNatTranslateCtEntry Update an Conntrack entry with NAT information . Translated address and port will be generated and write back to the conntrack entry as a result . Note : For ICMP only address is translated .
BOOLEAN
OvsNatTranslateCtEntry(OVS_CT_ENTRY *entry)
{
    const uint16_t MIN_NAT_EPHEMERAL_PORT = 1024;
    const uint16_t MAX_NAT_EPHEMERAL_PORT = 65535;
    uint16_t minPort;
    uint16_t maxPort;
    uint16_t firstPort;
    uint32_t addrDelta = 0;
    uint32_t addrIndex;
    struct ct_addr ctAddr, maxCtAddr;
    uint16_t port;
    BOOLEAN allPortsTried;
    BOOLEAN originalPortsTried;
    struct ct_addr firstAddr;
    uint32_t hash = OvsNatHashRange(entry, 0);
    if ((entry->natInfo.natAction & NAT_ACTION_SRC) &&
        (!(entry->natInfo.natAction & NAT_ACTION_SRC_PORT))) {
        firstPort = minPort = maxPort = ntohs(entry->key.src.port);
    } else if ((entry->natInfo.natAction & NAT_ACTION_DST) &&
               (!(entry->natInfo.natAction & NAT_ACTION_DST_PORT))) {
        firstPort = minPort = maxPort = ntohs(entry->key.dst.port);
    } else {
        uint16_t portDelta = entry->natInfo.maxPort - entry->natInfo.minPort;
        uint16_t portIndex = (uint16_t) hash % (portDelta + 1);
        firstPort = entry->natInfo.minPort + portIndex;
        minPort = entry->natInfo.minPort;
        maxPort = entry->natInfo.maxPort;
    }
    memset(&ctAddr, 0, sizeof ctAddr);
    memset(&maxCtAddr, 0, sizeof maxCtAddr);
    maxCtAddr = entry->natInfo.maxAddr;
    if (entry->key.dl_type == htons(ETH_TYPE_IPV4)) {
        addrDelta = ntohl(entry->natInfo.maxAddr.ipv4_aligned) -
                    ntohl(entry->natInfo.minAddr.ipv4_aligned);
        addrIndex = hash % (addrDelta + 1);
        ctAddr.ipv4_aligned = htonl(
            ntohl(entry->natInfo.minAddr.ipv4_aligned) + addrIndex);
    } else {
        return FALSE;
    }
    port = firstPort;
    allPortsTried = FALSE;
    originalPortsTried = FALSE;
    firstAddr = ctAddr;
    for (;;) {
        if (entry->natInfo.natAction & NAT_ACTION_SRC) {
            entry->rev_key.dst.addr = ctAddr;
            if (entry->rev_key.nw_proto != IPPROTO_ICMP) {
                entry->rev_key.dst.port = htons(port);
            }
        } else {
            entry->rev_key.src.addr = ctAddr;
            if (entry->rev_key.nw_proto != IPPROTO_ICMP) {
                entry->rev_key.src.port = htons(port);
            }
        }
        OVS_NAT_ENTRY *natEntry = OvsNatLookup(&entry->rev_key, TRUE);
        if (!natEntry) {
            natEntry = OvsAllocateMemoryWithTag(sizeof(*natEntry),
                                                OVS_CT_POOL_TAG);
            if (!natEntry) {
               return FALSE;
            }
            memcpy(&natEntry->key, &entry->key,
                   sizeof natEntry->key);
            memcpy(&natEntry->value, &entry->rev_key,
                   sizeof natEntry->value);
            natEntry->ctEntry = entry;
            OvsNatAddEntry(natEntry);
            return TRUE;
        } else if (!allPortsTried) {
            if (minPort == maxPort) {
                allPortsTried = TRUE;
            } else if (port == maxPort) {
                port = minPort;
            } else {
                port++;
            }
            if (port == firstPort) {
                allPortsTried = TRUE;
            }
        } else {
            if (memcmp(&ctAddr, &maxCtAddr, sizeof ctAddr)) {
                if (entry->key.dl_type == htons(ETH_TYPE_IPV4)) {
                    ctAddr.ipv4_aligned = htonl(
                        ntohl(ctAddr.ipv4_aligned) + 1);
                } else {
                    return FALSE;
                }
            } else {
                ctAddr = entry->natInfo.minAddr;
            }
            if (!memcmp(&ctAddr, &firstAddr, sizeof ctAddr)) {
                if (!originalPortsTried) {
                    originalPortsTried = TRUE;
                    ctAddr = entry->natInfo.minAddr;
                    minPort = MIN_NAT_EPHEMERAL_PORT;
                    maxPort = MAX_NAT_EPHEMERAL_PORT;
                } else {
                    break;
                }
            }
            firstPort = minPort;
            port = firstPort;
            allPortsTried = FALSE;
        }
    }
    return FALSE;
}
BOOLEAN OvsNatTranslateCtEntry ( OVS_CT_ENTRY * entry ) { const uint16_t MIN_NAT_EPHEMERAL_PORT = 1024 ; const uint16_t MAX_NAT_EPHEMERAL_PORT = 65535 ; uint16_t minPort ; uint16_t maxPort ; uint16_t firstPort ; uint32_t addrDelta = 0 ; uint32_t addrIndex ; struct ct_addr ctAddr , maxCtAddr ; uint16_t port ; BOOLEAN allPortsTried ; BOOLEAN originalPortsTried ; struct ct_addr firstAddr ; uint32_t hash = OvsNatHashRange ( entry , 0 ) ; if ( ( entry -> natInfo . natAction & NAT_ACTION_SRC ) && ( ! ( entry -> natInfo . natAction & NAT_ACTION_SRC_PORT ) ) ) { firstPort = minPort = maxPort = ntohs ( entry -> key . src . port ) ; } else if ( ( entry -> natInfo . natAction & NAT_ACTION_DST ) && ( ! ( entry -> natInfo . natAction & NAT_ACTION_DST_PORT ) ) ) { firstPort = minPort = maxPort = ntohs ( entry -> key . dst . port ) ; } else { uint16_t portDelta = entry -> natInfo . maxPort - entry -> natInfo . minPort ; uint16_t portIndex = ( uint16_t ) hash % ( portDelta + 1 ) ; firstPort = entry -> natInfo . minPort + portIndex ; minPort = entry -> natInfo . minPort ; maxPort = entry -> natInfo . maxPort ; } memset ( & ctAddr , 0 , sizeof ctAddr ) ; memset ( & maxCtAddr , 0 , sizeof maxCtAddr ) ; maxCtAddr = entry -> natInfo . maxAddr ; if ( entry -> key . dl_type == htons ( ETH_TYPE_IPV4 ) ) { addrDelta = ntohl ( entry -> natInfo . maxAddr . ipv4_aligned ) - ntohl ( entry -> natInfo . minAddr . ipv4_aligned ) ; addrIndex = hash % ( addrDelta + 1 ) ; ctAddr . ipv4_aligned = htonl ( ntohl ( entry -> natInfo . minAddr . ipv4_aligned ) + addrIndex ) ; } else { return FALSE ; } port = firstPort ; allPortsTried = FALSE ; originalPortsTried = FALSE ; firstAddr = ctAddr ; for ( ; ; ) { if ( entry -> natInfo . natAction & NAT_ACTION_SRC ) { entry -> rev_key . dst . addr = ctAddr ; if ( entry -> rev_key . nw_proto != IPPROTO_ICMP ) { entry -> rev_key . dst . port = htons ( port ) ; } } else { entry -> rev_key . src . addr = ctAddr ; if ( entry -> rev_key . nw_proto != IPPROTO_ICMP ) { entry -> rev_key . src . port = htons ( port ) ; } } OVS_NAT_ENTRY * natEntry = OvsNatLookup ( & entry -> rev_key , TRUE ) ; if ( ! natEntry ) { natEntry = OvsAllocateMemoryWithTag ( sizeof ( * natEntry ) , OVS_CT_POOL_TAG ) ; if ( ! natEntry ) { return FALSE ; } memcpy ( & natEntry -> key , & entry -> key , sizeof natEntry -> key ) ; memcpy ( & natEntry -> value , & entry -> rev_key , sizeof natEntry -> value ) ; natEntry -> ctEntry = entry ; OvsNatAddEntry ( natEntry ) ; return TRUE ; } else if ( ! allPortsTried ) { if ( minPort == maxPort ) { allPortsTried = TRUE ; } else if ( port == maxPort ) { port = minPort ; } else { port ++ ; } if ( port == firstPort ) { allPortsTried = TRUE ; } } else { if ( memcmp ( & ctAddr , & maxCtAddr , sizeof ctAddr ) ) { if ( entry -> key . dl_type == htons ( ETH_TYPE_IPV4 ) ) { ctAddr . ipv4_aligned = htonl ( ntohl ( ctAddr . ipv4_aligned ) + 1 ) ; } else { return FALSE ; } } else { ctAddr = entry -> natInfo . minAddr ; } if ( ! memcmp ( & ctAddr , & firstAddr , sizeof ctAddr ) ) { if ( ! originalPortsTried ) { originalPortsTried = TRUE ; ctAddr = entry -> natInfo . minAddr ; minPort = MIN_NAT_EPHEMERAL_PORT ; maxPort = MAX_NAT_EPHEMERAL_PORT ; } else { break ; } } firstPort = minPort ; port = firstPort ; allPortsTried = FALSE ; } } return FALSE ; }
OvsNatTranslateCtEntry
     Update an Conntrack entry with NAT information.
OvsNatTranslateCtEntry Update an Conntrack entry with NAT information .
// XXX: IPv6 not supported // XXX: IPv6 not supported